Skip to content

Commit 7004871

Browse files
authored
* Added ToolReturnCode to be more rigerous about how a return code is passed back from a tool (shader-slang#911)
* Added support for a tool being able to pass back an 'ignored' result. * Used enum codes to indicate meanings * Made spawnAndWait return a ToolReturnCode
1 parent 1bc99cf commit 7004871

File tree

6 files changed

+112
-54
lines changed

6 files changed

+112
-54
lines changed

slang.h

+2
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,8 @@ extern "C"
668668
#define SLANG_E_NOT_FOUND SLANG_MAKE_CORE_ERROR(5)
669669
//! An unhandled internal failure (typically from unhandled exception)
670670
#define SLANG_E_INTERNAL_FAIL SLANG_MAKE_CORE_ERROR(6)
671+
//! Could not complete because some underlying feature (hardware or software) was not available
672+
#define SLANG_E_NOT_AVAILABLE SLANG_MAKE_CORE_ERROR(7)
671673

672674
/** A "Universally Unique Identifier" (UUID)
673675

source/core/slang-test-tool-util.cpp

+22-6
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,34 @@
44
namespace Slang
55
{
66

7-
/* static */int TestToolUtil::getReturnCode(SlangResult res)
7+
/* static */ToolReturnCode TestToolUtil::getReturnCode(SlangResult res)
88
{
9-
if (SLANG_SUCCEEDED(res))
9+
switch (res)
1010
{
11-
return 0;
11+
case SLANG_OK: return ToolReturnCode::Success;
12+
case SLANG_E_INTERNAL_FAIL: return ToolReturnCode::CompilationFailed;
13+
case SLANG_FAIL: return ToolReturnCode::Failed;
14+
case SLANG_E_NOT_AVAILABLE: return ToolReturnCode::Ignored;
15+
default:
16+
{
17+
return (SLANG_SUCCEEDED(res)) ? ToolReturnCode::Success : ToolReturnCode::Failed;
18+
}
1219
}
13-
else if (res == SLANG_E_INTERNAL_FAIL)
20+
}
21+
22+
/* static */ToolReturnCode TestToolUtil::getReturnCodeFromInt(int code)
23+
{
24+
if (code >= int(ToolReturnCodeSpan::First) && code <= int(ToolReturnCodeSpan::Last))
1425
{
15-
return -1;
26+
return ToolReturnCode(code);
27+
}
28+
else
29+
{
30+
SLANG_ASSERT(!"Invalid integral code");
31+
return ToolReturnCode::Failed;
1632
}
17-
return 1;
1833
}
1934

35+
2036
}
2137

source/core/slang-test-tool-util.h

+29-1
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,41 @@ namespace Slang {
1111
# define SLANG_TEST_TOOL_API
1212
#endif
1313

14+
/* When a tool is run as an executable the return code is the code returned from
15+
the last return of main. On unix this can be up to 8 bits.
16+
By normal command line tool conventions returning 0 means success. */
17+
enum class ToolReturnCode
18+
{
19+
CompilationFailed = -1, ///< Compilation failure (-1 to maintain compatibility). This may still produce output and may mean a test was successful.
20+
Success = 0, ///< Tool ran normally
21+
Failed, ///< Tool failed
22+
Ignored, ///< The run was ignored because it couldn't be run (because some optional feature was not present for example)
23+
FailedToRun, ///< Could not even run the test
24+
};
25+
26+
enum class ToolReturnCodeSpan
27+
{
28+
// Span of all valid values
29+
First = int(ToolReturnCode::CompilationFailed),
30+
Last = int(ToolReturnCode::FailedToRun),
31+
// Span of all values that indicate the test is 'done'
32+
FirstIsDone = int(ToolReturnCode::Ignored),
33+
LastIsDone = int(ToolReturnCode::FailedToRun)
34+
};
35+
1436
/* Utility functions for 'test tools' */
1537
struct TestToolUtil
1638
{
1739
typedef SlangResult(*InnerMainFunc)(Slang::StdWriters* stdWriters, SlangSession* session, int argc, const char*const* argv);
1840

41+
/// If the test failed to run or was ignored then we are done
42+
static bool isDone(ToolReturnCode code) { return int(code) >= int(ToolReturnCodeSpan::FirstIsDone) && int(code) <= int(ToolReturnCodeSpan::LastIsDone); }
43+
44+
/// Convert from an int
45+
static ToolReturnCode getReturnCodeFromInt(int code);
46+
1947
/// Given a slang result, returns a return code that can be returned from an executable
20-
static int getReturnCode(SlangResult res);
48+
static ToolReturnCode getReturnCode(SlangResult res);
2149
};
2250

2351
} // namespace Slang

source/slangc/main.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ int MAIN(int argc, char** argv)
8787
res = innerMain(stdWriters, session, argc, argv);
8888
spDestroySession(session);
8989
}
90-
return TestToolUtil::getReturnCode(res);
90+
return (int)TestToolUtil::getReturnCode(res);
9191
}
9292

9393
#ifdef _WIN32

tools/render-test/render-test-main.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ SLANG_TEST_TOOL_API SlangResult innerMain(Slang::StdWriters* stdWriters, SlangSe
574574
}
575575
}
576576

577-
// Use the profilename set on options if set
577+
// Use the profile name set on options if set
578578
profileName = gOptions.profileName ? gOptions.profileName : profileName;
579579

580580
ShaderCompiler shaderCompiler;
@@ -670,7 +670,6 @@ SLANG_TEST_TOOL_API SlangResult innerMain(Slang::StdWriters* stdWriters, SlangSe
670670
return SLANG_OK;
671671
}
672672

673-
674673
int main(int argc, char** argv)
675674
{
676675
using namespace Slang;
@@ -681,6 +680,6 @@ int main(int argc, char** argv)
681680
SlangResult res = innerMain(stdWriters, session, argc, argv);
682681
spDestroySession(session);
683682

684-
return SLANG_FAILED(res) ? 1 : 0;
683+
return (int)TestToolUtil::getReturnCode(res);
685684
}
686685

tools/slang-test/slang-test-main.cpp

+56-43
Original file line numberDiff line numberDiff line change
@@ -437,29 +437,43 @@ OSError spawnAndWaitSharedLibrary(TestContext* context, const String& testPath,
437437
spawner.standardError_ = stdErrorString;
438438
spawner.standardOutput_ = stdOutString;
439439

440-
spawner.resultCode_ = TestToolUtil::getReturnCode(res);
440+
spawner.resultCode_ = (int)TestToolUtil::getReturnCode(res);
441441

442442
return kOSError_None;
443443
}
444444

445445
return kOSError_OperationFailed;
446446
}
447447

448+
ToolReturnCode getReturnCode(OSProcessSpawner& spawner)
449+
{
450+
return TestToolUtil::getReturnCodeFromInt(spawner.getResultCode());
451+
}
448452

449-
OSError spawnAndWait(TestContext* context, const String& testPath, SpawnType spawnType, OSProcessSpawner& spawner)
453+
ToolReturnCode spawnAndWait(TestContext* context, const String& testPath, SpawnType spawnType, OSProcessSpawner& spawner)
450454
{
455+
OSError spawnResult = kOSError_OperationFailed;
451456
switch (spawnType)
452457
{
453458
case SpawnType::UseExe:
454459
{
455-
return spawnAndWaitExe(context, testPath, spawner);
460+
spawnResult = spawnAndWaitExe(context, testPath, spawner);
461+
break;
456462
}
457463
case SpawnType::UseSharedLibrary:
458464
{
459-
return spawnAndWaitSharedLibrary(context, testPath, spawner);
465+
spawnResult = spawnAndWaitSharedLibrary(context, testPath, spawner);
466+
break;
460467
}
468+
default: break;
461469
}
462-
return kOSError_OperationFailed;
470+
471+
if (spawnResult != kOSError_None)
472+
{
473+
return ToolReturnCode::FailedToRun;
474+
}
475+
476+
return getReturnCode(spawner);
463477
}
464478

465479
String getOutput(OSProcessSpawner& spawner)
@@ -530,6 +544,25 @@ static void _initSlangCompiler(TestContext* context, OSProcessSpawner& spawnerOu
530544
}
531545
}
532546

547+
TestResult asTestResult(ToolReturnCode code)
548+
{
549+
switch (code)
550+
{
551+
case ToolReturnCode::Success: return TestResult::Pass;
552+
case ToolReturnCode::Ignored: return TestResult::Ignored;
553+
default: return TestResult::Fail;
554+
}
555+
}
556+
557+
#define TEST_RETURN_ON_DONE(x) \
558+
{ \
559+
const ToolReturnCode toolRet_ = x; \
560+
if (TestToolUtil::isDone(toolRet_)) \
561+
{ \
562+
return asTestResult(toolRet_); \
563+
} \
564+
}
565+
533566
TestResult runSimpleTest(TestContext* context, TestInput& input)
534567
{
535568
// need to execute the stand-alone Slang compiler on the file, and compare its output to what we expect
@@ -547,10 +580,7 @@ TestResult runSimpleTest(TestContext* context, TestInput& input)
547580
spawner.pushArgument(arg);
548581
}
549582

550-
if (spawnAndWait(context, outputStem, input.spawnType, spawner) != kOSError_None)
551-
{
552-
return TestResult::Fail;
553-
}
583+
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
554584

555585
String actualOutput = getOutput(spawner);
556586

@@ -621,10 +651,7 @@ TestResult runReflectionTest(TestContext* context, TestInput& input)
621651
spawner.pushArgument(arg);
622652
}
623653

624-
if (spawnAndWait(context, outputStem, input.spawnType, spawner) != kOSError_None)
625-
{
626-
return TestResult::Fail;
627-
}
654+
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
628655

629656
String actualOutput = getOutput(spawner);
630657

@@ -772,11 +799,8 @@ TestResult runCrossCompilerTest(TestContext* context, TestInput& input)
772799
expectedSpawner.pushArgument(arg);
773800
}
774801

775-
if (spawnAndWait(context, outputStem, input.spawnType, expectedSpawner) != kOSError_None)
776-
{
777-
return TestResult::Fail;
778-
}
779-
802+
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, expectedSpawner));
803+
780804
String expectedOutput = getOutput(expectedSpawner);
781805
String expectedOutputPath = outputStem + ".expected";
782806
try
@@ -788,10 +812,8 @@ TestResult runCrossCompilerTest(TestContext* context, TestInput& input)
788812
return TestResult::Fail;
789813
}
790814

791-
if (spawnAndWait(context, outputStem, input.spawnType, actualSpawner) != kOSError_None)
792-
{
793-
return TestResult::Fail;
794-
}
815+
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, actualSpawner));
816+
795817
String actualOutput = getOutput(actualSpawner);
796818

797819
TestResult result = TestResult::Pass;
@@ -847,10 +869,7 @@ TestResult generateHLSLBaseline(TestContext* context, TestInput& input)
847869
spawner.pushArgument("-pass-through");
848870
spawner.pushArgument("fxc");
849871

850-
if (spawnAndWait(context, outputStem, input.spawnType, spawner) != kOSError_None)
851-
{
852-
return TestResult::Fail;
853-
}
872+
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
854873

855874
String expectedOutput = getOutput(spawner);
856875
String expectedOutputPath = outputStem + ".expected";
@@ -895,10 +914,7 @@ TestResult runHLSLComparisonTest(TestContext* context, TestInput& input)
895914
spawner.pushArgument("-target");
896915
spawner.pushArgument("dxbc-assembly");
897916

898-
if (spawnAndWait(context, outputStem, input.spawnType, spawner) != kOSError_None)
899-
{
900-
return TestResult::Fail;
901-
}
917+
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
902918

903919
// We ignore output to stdout, and only worry about what the compiler
904920
// wrote to stderr.
@@ -1004,10 +1020,7 @@ TestResult doGLSLComparisonTestRun(TestContext* context,
10041020
spawner.pushArgument(arg);
10051021
}
10061022

1007-
if (spawnAndWait(context, outputStem, input.spawnType, spawner) != kOSError_None)
1008-
{
1009-
return TestResult::Fail;
1010-
}
1023+
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
10111024

10121025
OSProcessSpawner::ResultCode resultCode = spawner.getResultCode();
10131026

@@ -1043,6 +1056,13 @@ TestResult runGLSLComparisonTest(TestContext* context, TestInput& input)
10431056
TestResult hlslResult = doGLSLComparisonTestRun(context, input, "__GLSL__", "glslang", ".expected", &expectedOutput);
10441057
TestResult slangResult = doGLSLComparisonTestRun(context, input, "__SLANG__", nullptr, ".actual", &actualOutput);
10451058

1059+
// If either is ignored, the whole test is
1060+
if (hlslResult == TestResult::Ignored ||
1061+
slangResult == TestResult::Ignored)
1062+
{
1063+
return TestResult::Ignored;
1064+
}
1065+
10461066
Slang::File::WriteAllText(outputStem + ".expected", expectedOutput);
10471067
Slang::File::WriteAllText(outputStem + ".actual", actualOutput);
10481068

@@ -1093,11 +1113,7 @@ TestResult runComputeComparisonImpl(TestContext* context, TestInput& input, cons
10931113
// clear the stale actual output file first. This will allow us to detect error if render-test fails and outputs nothing.
10941114
File::WriteAllText(actualOutputFile, "");
10951115

1096-
if (spawnAndWait(context, outputStem, input.spawnType, spawner) != kOSError_None)
1097-
{
1098-
printf("error spawning render-test\n");
1099-
return TestResult::Fail;
1100-
}
1116+
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
11011117

11021118
auto actualOutput = getOutput(spawner);
11031119
auto expectedOutput = getExpectedOutput(outputStem);
@@ -1192,10 +1208,7 @@ TestResult doRenderComparisonTestRun(TestContext* context, TestInput& input, cha
11921208
spawner.pushArgument("-o");
11931209
spawner.pushArgument(outputStem + outputKind + ".png");
11941210

1195-
if (spawnAndWait(context, outputStem, input.spawnType, spawner) != kOSError_None)
1196-
{
1197-
return TestResult::Fail;
1198-
}
1211+
TEST_RETURN_ON_DONE(spawnAndWait(context, outputStem, input.spawnType, spawner));
11991212

12001213
OSProcessSpawner::ResultCode resultCode = spawner.getResultCode();
12011214

0 commit comments

Comments
 (0)