Commit d2afb65b authored by wooway777's avatar wooway777
Browse files

issue/593 - added verbose test mode

parent 576b7552
import torch import torch
import infinicore import infinicore
import traceback # Add import for traceback
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import List, Dict, Any, Optional from typing import List, Dict, Any, Optional
...@@ -216,14 +217,19 @@ class TestCase: ...@@ -216,14 +217,19 @@ class TestCase:
class TestConfig: class TestConfig:
"""Test configuration""" """Test configuration"""
def __init__(self, debug=False, bench=False, num_prerun=10, num_iterations=1000): def __init__(
self,
debug=False,
bench=False,
num_prerun=10,
num_iterations=1000,
verbose=False,
):
self.debug = debug self.debug = debug
self.bench = bench self.bench = bench
self.num_prerun = num_prerun self.num_prerun = num_prerun
self.num_iterations = num_iterations self.num_iterations = num_iterations
self.verbose = verbose
# In base.py - update the TestRunner class
class TestRunner: class TestRunner:
...@@ -273,16 +279,11 @@ class TestRunner: ...@@ -273,16 +279,11 @@ class TestRunner:
# Test was skipped due to both operators not being implemented # Test was skipped due to both operators not being implemented
skip_msg = f"{test_case} - {InfiniDeviceNames[device]} - Both operators not implemented" skip_msg = f"{test_case} - {InfiniDeviceNames[device]} - Both operators not implemented"
self.skipped_tests.append(skip_msg) self.skipped_tests.append(skip_msg)
print(
f"\033[93m⚠\033[0m Skipped - both operators not implemented"
)
elif status == "partial": elif status == "partial":
# Test was partially executed (one operator not implemented) # Test was partially executed (one operator not implemented)
partial_msg = f"{test_case} - {InfiniDeviceNames[device]} - One operator not implemented" partial_msg = f"{test_case} - {InfiniDeviceNames[device]} - One operator not implemented"
self.partial_tests.append(partial_msg) self.partial_tests.append(partial_msg)
print(
f"\033[93m⚠\033[0m Partial - one operator not implemented"
)
# Failed tests are handled in the exception handler below # Failed tests are handled in the exception handler below
except Exception as e: except Exception as e:
...@@ -291,6 +292,12 @@ class TestRunner: ...@@ -291,6 +292,12 @@ class TestRunner:
) )
print(f"\033[91m✗\033[0m {error_msg}") print(f"\033[91m✗\033[0m {error_msg}")
self.failed_tests.append(error_msg) self.failed_tests.append(error_msg)
# In verbose mode, print full traceback and stop execution
if self.config.verbose:
traceback.print_exc()
return False # Stop test execution immediately
if self.config.debug: if self.config.debug:
raise raise
...@@ -312,34 +319,16 @@ class TestRunner: ...@@ -312,34 +319,16 @@ class TestRunner:
print(f"\n{'='*60}") print(f"\n{'='*60}")
print("TEST SUMMARY") print("TEST SUMMARY")
print(f"{'='*60}")
print(f"Total tests: {total_tests}") print(f"Total tests: {total_tests}")
print(f"\033[92mPassed: {passed_count}\033[0m") print(f"\033[92mPassed: {passed_count}\033[0m")
# Display partial tests (one operator not implemented) result = True
if self.partial_tests:
print(
f"\033[93mPartial (one operator not implemented): {partial_count}\033[0m"
)
for test in self.partial_tests:
print(f" - {test}")
# Display skipped tests (both operators not implemented)
if self.skipped_tests:
print(
f"\033[93mSkipped (both operators not implemented): {skipped_count}\033[0m"
)
for test in self.skipped_tests:
print(f" - {test}")
# Display failed tests # Display failed tests
if self.failed_tests: if self.failed_tests:
print(f"\033[91mFailed: {failed_count}\033[0m") print(f"\033[91mFailed: {failed_count}\033[0m")
for failure in self.failed_tests:
print(f" - {failure}")
# Return False only if there are actual test failures # Return False only if there are actual test failures
return False result = False
else: else:
# Calculate success rate based on actual executed tests # Calculate success rate based on actual executed tests
executed_tests = passed_count + partial_count + failed_count executed_tests = passed_count + partial_count + failed_count
...@@ -352,10 +341,11 @@ class TestRunner: ...@@ -352,10 +341,11 @@ class TestRunner:
print( print(
f"\n\033[93mTests completed with some implementations missing\033[0m" f"\n\033[93mTests completed with some implementations missing\033[0m"
) )
return True # Skipped/partial tests don't count as failures
else: else:
print(f"\n\033[92mAll tests passed!\033[0m") print(f"\n\033[92mAll tests passed!\033[0m")
return True
print(f"{'='*60}")
return result
class BaseOperatorTest(ABC): class BaseOperatorTest(ABC):
...@@ -537,6 +527,9 @@ class BaseOperatorTest(ABC): ...@@ -537,6 +527,9 @@ class BaseOperatorTest(ABC):
if torch_result is None: if torch_result is None:
torch_implemented = False torch_implemented = False
except NotImplementedError: except NotImplementedError:
if config.verbose:
traceback.print_exc()
return False # Stop test execution immediately
torch_implemented = False torch_implemented = False
torch_result = None torch_result = None
...@@ -545,6 +538,9 @@ class BaseOperatorTest(ABC): ...@@ -545,6 +538,9 @@ class BaseOperatorTest(ABC):
if infini_result is None: if infini_result is None:
infini_implemented = False infini_implemented = False
except NotImplementedError: except NotImplementedError:
if config.verbose:
traceback.print_exc()
return False # Stop test execution immediately
infini_implemented = False infini_implemented = False
infini_result = None infini_result = None
......
import argparse import argparse
from .devices import InfiniDeviceEnum from .devices import InfiniDeviceEnum
# hardware_info.py
""" """
Shared hardware platform information for the InfiniCore testing framework Shared hardware platform information for the InfiniCore testing framework
""" """
...@@ -61,6 +60,9 @@ Examples: ...@@ -61,6 +60,9 @@ Examples:
# Run with debug mode on multiple devices # Run with debug mode on multiple devices
python test_operator.py --cpu --nvidia --debug python test_operator.py --cpu --nvidia --debug
# Run with verbose mode to stop on first error with full traceback
python test_operator.py --cpu --nvidia --verbose
# Run performance profiling with custom iterations # Run performance profiling with custom iterations
python test_operator.py --nvidia --bench --num_prerun 50 --num_iterations 5000 python test_operator.py --nvidia --bench --num_prerun 50 --num_iterations 5000
...@@ -90,6 +92,11 @@ Examples: ...@@ -90,6 +92,11 @@ Examples:
action="store_true", action="store_true",
help="Enable debug mode for detailed tensor comparison", help="Enable debug mode for detailed tensor comparison",
) )
parser.add_argument(
"--verbose",
action="store_true",
help="Enable verbose mode to stop on first error with full traceback",
)
# Device options using shared hardware info # Device options using shared hardware info
hardware_group = get_hardware_args_group(parser) hardware_group = get_hardware_args_group(parser)
......
...@@ -28,6 +28,7 @@ class GenericTestRunner: ...@@ -28,6 +28,7 @@ class GenericTestRunner:
bench=self.args.bench, bench=self.args.bench,
num_prerun=self.args.num_prerun, num_prerun=self.args.num_prerun,
num_iterations=self.args.num_iterations, num_iterations=self.args.num_iterations,
verbose=self.args.verbose, # Pass verbose flag to TestConfig
) )
runner = TestRunner(self.operator_test.test_cases, config) runner = TestRunner(self.operator_test.test_cases, config)
......
...@@ -122,6 +122,9 @@ def run_all_op_tests(ops_dir=None, specific_ops=None, extra_args=None): ...@@ -122,6 +122,9 @@ def run_all_op_tests(ops_dir=None, specific_ops=None, extra_args=None):
results = {} results = {}
# Check if verbose mode is enabled
verbose_mode = extra_args and "--verbose" in extra_args
for test_file in operator_test_files: for test_file in operator_test_files:
test_name = test_file.stem test_name = test_file.stem
...@@ -199,14 +202,27 @@ def run_all_op_tests(ops_dir=None, specific_ops=None, extra_args=None): ...@@ -199,14 +202,27 @@ def run_all_op_tests(ops_dir=None, specific_ops=None, extra_args=None):
f"{status_icon} {test_name}: {status_text} (return code: {returncode})" f"{status_icon} {test_name}: {status_text} (return code: {returncode})"
) )
# In verbose mode, stop execution on first failure
if verbose_mode and not success and returncode not in [-2, -3]:
break
except Exception as e: except Exception as e:
print(f"💥 {test_name}: ERROR - {str(e)}") print(f"💥 {test_name}: ERROR - {str(e)}")
results[test_name] = (False, -1, "", str(e)) results[test_name] = (False, -1, "", str(e))
# In verbose mode, stop execution on any exception
if verbose_mode:
print(f"\n{'!'*60}")
print(
f"VERBOSE MODE: Stopping execution due to exception in {test_name}"
)
print(f"{'!'*60}")
break
return results return results
def print_summary(results): def print_summary(results, verbose_mode=False, total_expected_tests=0):
"""Print a comprehensive summary of test results.""" """Print a comprehensive summary of test results."""
print(f"\n{'='*80}") print(f"\n{'='*80}")
print("CUMULATIVE TEST SUMMARY") print("CUMULATIVE TEST SUMMARY")
...@@ -242,7 +258,11 @@ def print_summary(results): ...@@ -242,7 +258,11 @@ def print_summary(results):
total = len(results) total = len(results)
print(f"Total tests: {total}") print(f"Total tests run: {total}")
if total_expected_tests > 0 and total < total_expected_tests:
print(f"Total tests expected: {total_expected_tests}")
print(f"Tests not executed: {total_expected_tests - total}")
print(f"Passed: {passed}") print(f"Passed: {passed}")
print(f"Failed: {failed}") print(f"Failed: {failed}")
...@@ -290,6 +310,10 @@ def print_summary(results): ...@@ -290,6 +310,10 @@ def print_summary(results):
success_rate = passed / executed_tests * 100 success_rate = passed / executed_tests * 100
print(f"\nSuccess rate: {success_rate:.1f}%") print(f"\nSuccess rate: {success_rate:.1f}%")
if verbose_mode and total < total_expected_tests:
print(f"\n💡 Verbose mode: Execution stopped after first failure")
print(f" {total_expected_tests - total} tests were not executed")
if failed == 0: if failed == 0:
if skipped > 0 or partial > 0: if skipped > 0 or partial > 0:
print(f"\n⚠️ Tests completed with some operators not implemented") print(f"\n⚠️ Tests completed with some operators not implemented")
...@@ -358,6 +382,11 @@ def generate_help_epilog(ops_dir): ...@@ -358,6 +382,11 @@ def generate_help_epilog(ops_dir):
epilog_parts.append(" # Run with debug mode on multiple devices") epilog_parts.append(" # Run with debug mode on multiple devices")
epilog_parts.append(" python run.py --cpu --nvidia --debug") epilog_parts.append(" python run.py --cpu --nvidia --debug")
epilog_parts.append("") epilog_parts.append("")
epilog_parts.append(
" # Run with verbose mode to stop on first error with full traceback"
)
epilog_parts.append(" python run.py --cpu --nvidia --verbose")
epilog_parts.append("")
epilog_parts.append(" # List available tests without running") epilog_parts.append(" # List available tests without running")
epilog_parts.append(" python run.py --list") epilog_parts.append(" python run.py --list")
epilog_parts.append("") epilog_parts.append("")
...@@ -386,6 +415,12 @@ def generate_help_epilog(ops_dir): ...@@ -386,6 +415,12 @@ def generate_help_epilog(ops_dir):
epilog_parts.append( epilog_parts.append(
" - --bench option is disabled in batch mode (run individual tests for benchmarking)" " - --bench option is disabled in batch mode (run individual tests for benchmarking)"
) )
epilog_parts.append(
" - --verbose mode stops execution on first error and shows full traceback"
)
epilog_parts.append(
" - In verbose mode, subsequent tests are skipped after first failure"
)
return "\n".join(epilog_parts) return "\n".join(epilog_parts)
...@@ -413,6 +448,11 @@ def main(): ...@@ -413,6 +448,11 @@ def main():
action="store_true", action="store_true",
help="List all available test files without running them", help="List all available test files without running them",
) )
parser.add_argument(
"--verbose",
action="store_true",
help="Enable verbose mode to stop on first error with full traceback (passed to individual tests)",
)
from framework import get_hardware_args_group from framework import get_hardware_args_group
...@@ -442,6 +482,10 @@ def main(): ...@@ -442,6 +482,10 @@ def main():
print(f"Error: Ops directory '{ops_dir}' does not exist.") print(f"Error: Ops directory '{ops_dir}' does not exist.")
sys.exit(1) sys.exit(1)
# Add verbose flag to extra arguments if specified
if args.verbose and "--verbose" not in unknown_args:
unknown_args.append("--verbose")
# Show what extra arguments will be passed # Show what extra arguments will be passed
if unknown_args: if unknown_args:
print(f"Passing extra arguments to test scripts: {unknown_args}") print(f"Passing extra arguments to test scripts: {unknown_args}")
...@@ -453,6 +497,9 @@ def main(): ...@@ -453,6 +497,9 @@ def main():
print(f"Operating directory: {ops_dir}") print(f"Operating directory: {ops_dir}")
print(f"Available operators: {len(available_operators)}") print(f"Available operators: {len(available_operators)}")
if args.verbose:
print(f"Verbose mode: ENABLED (will stop on first error with full traceback)")
if args.ops: if args.ops:
# Validate requested operators # Validate requested operators
valid_ops = [] valid_ops = []
...@@ -469,10 +516,13 @@ def main(): ...@@ -469,10 +516,13 @@ def main():
if valid_ops: if valid_ops:
print(f"Testing operators: {', '.join(valid_ops)}") print(f"Testing operators: {', '.join(valid_ops)}")
total_expected_tests = len(valid_ops)
else: else:
print("No valid operators specified. Running all available tests.") print("No valid operators specified. Running all available tests.")
total_expected_tests = len(available_operators)
else: else:
print("Testing all available operators") print("Testing all available operators")
total_expected_tests = len(available_operators)
print() print()
...@@ -484,7 +534,7 @@ def main(): ...@@ -484,7 +534,7 @@ def main():
) )
# Print summary and exit with appropriate code # Print summary and exit with appropriate code
all_passed = print_summary(results) all_passed = print_summary(results, args.verbose, total_expected_tests)
# Check if there were any tests with missing implementations # Check if there were any tests with missing implementations
has_missing_implementations = any( has_missing_implementations = any(
...@@ -495,6 +545,18 @@ def main(): ...@@ -495,6 +545,18 @@ def main():
print(f"\n⚠️ Note: Some operators are not fully implemented") print(f"\n⚠️ Note: Some operators are not fully implemented")
print(f" Run individual tests for details on missing implementations") print(f" Run individual tests for details on missing implementations")
if args.verbose and not all_passed:
print(
f"\n💡 Verbose mode tip: Use individual test commands for detailed debugging:"
)
failed_ops = [
name
for name, (success, _, _, _) in results.items()
if not success and name in results
]
for op in failed_ops[:3]: # Show first 3 failed operators
print(f" python {ops_dir / (op + '.py')} --verbose")
sys.exit(0 if all_passed else 1) sys.exit(0 if all_passed else 1)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment