summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2021-11-24 09:34:05 -0500
committerGitHub <noreply@github.com>2021-11-24 09:34:05 -0500
commitbdc61bb8db321a8d788aa739b889354540a49ee0 (patch)
tree16c564282a28d69e77d51855a41f11bdfa80fded
parent9e084ffab37c276d40931a58633041a2e10de623 (diff)
Remove test-proxy (#2027)
* #include an absolute path didn't work - because paths were taken to always be relative. * Use 'Process' to communicate with an command line tool. * Remove slang-win-stream * Tidy up windows ProcessUtil. * First version of BufferedReadStream. * Windows working IPC for steams. * Test proxy count option. * Split Process/ProcessUtil. Process is platform dependant. ProcessUtil are functions that are platform independent. * First implementation of Unix Process interface. * Unix process compiles on cygwin. * Fix typo in unix process. * Separate unix pipe stream error of invalid access, from pipe availability. * Fix in standard line extraction. * Make fd non blocking. * Fix issues with Windows Process streams. * Added UnixPipe. * Some fixes around UnixPipeStream. * Make a unix stream closed explicit. * Hack to debug linux process/stream. * Revert to old linux pipe handling. * Pass executable path for unit tests. Split out CommandLine into own source. * Small improvements in process/command line. * Check process behavior with crash. * Make stderr and stdout unbuffered for crash testing. * Only turn disable buffering in crash test. * Disable crash test on CI. * Fix crash on clang/linux. * Enable crash test. Remove _appendBuffer as can use StreamUtil functionality. * Added inital processing for http headers. * Small improvements to HttpHeader. * First pass HTTPPacketConnection working on windows. * Enable other Process communication tests. * Update comments. * WIP JSON RPC. * Add terminate to Process. Made JSONRPC a Util. * Small tidy up around HTTPPacketConnection. * Improve process termination options. * WIP for test-server. * Add diagnostics error handling to test-server. * Improved JSON support. Parsing/creating JSON-RPC messages. * WIP JSONRPC parsing. * First pass RttiInfo support. * WIP converting between JSON/native types. * Project files. * Split out RttiUtil. Made RttiInfo constuction thread safe. * WIP RTTI<->JSON. * Add diagnostics to JSON<->native conversions. * Make RttiInfo for structs globals. Avoids problem around derived types (like pointers), being able to cause an abort. * Add pointer support to RTTI. Fixed some compilation issues on linux. * Add fixed array support. * Added Rtti unit test. * Add rtti unit test. * Split out quoted/unquoted key handling. Fix bugs in JSON value/container. Added JSON native test. * Make default array allocator use malloc/free. Remove the new[] handler (doesn't work on visuals studio). * Fix for linux warning. * Remove some test code. * Fix issues on x86 win. * Fix warning on aarch64. * Fix some bugs in JSON parsing/handling. Make Rtti work copy/dtor/ctor struct types. * Testing JSON<->native with fixed array. Make makeArrayView explicit if it's just a single value. Added array type. * Fix getting arrayView. * Improve JSON diagnostic name. * First pass refactor using Rtti for JSON RPC. * First pass of test server using RTTI/JSON-RPC. * Added JSONRPCConnection. * Fix some naming issues. * First pass of test-server working. * Added unit test support for JSON-RPC test server. * Fix compilation issues on linux around template handling. * Typo fix. * Fix a bug around SourceLoc lookup with JSONContainer. * Set the console type to console for ISlangWriters. * Small improvements to test-server. * Small improvements in test-server. * Small fix. * Remove test-proxy. Make test-process a process that can be used to unit test 'Process'. Adding mechanism to control spawning that will create a new process for every test. * Ability to remove source manager for JSONValue.
-rw-r--r--build/visual-studio/test-process/test-process.vcxproj (renamed from build/visual-studio/test-proxy/test-proxy.vcxproj)31
-rw-r--r--build/visual-studio/test-process/test-process.vcxproj.filters (renamed from build/visual-studio/test-proxy/test-proxy.vcxproj.filters)2
-rw-r--r--premake5.lua4
-rw-r--r--slang.sln2
-rw-r--r--source/compiler-core/slang-json-value.cpp76
-rw-r--r--source/compiler-core/slang-json-value.h11
-rw-r--r--tools/slang-test/options.cpp8
-rw-r--r--tools/slang-test/options.h6
-rw-r--r--tools/slang-test/slang-test-main.cpp69
-rw-r--r--tools/slang-unit-test/unit-test-process.cpp51
-rw-r--r--tools/test-process/test-process-main.cpp193
-rw-r--r--tools/test-proxy/test-proxy-main.cpp406
12 files changed, 348 insertions, 511 deletions
diff --git a/build/visual-studio/test-proxy/test-proxy.vcxproj b/build/visual-studio/test-process/test-process.vcxproj
index 3b7dfbb58..97663425f 100644
--- a/build/visual-studio/test-proxy/test-proxy.vcxproj
+++ b/build/visual-studio/test-process/test-process.vcxproj
@@ -54,7 +54,7 @@
<ProjectGuid>{BE412850-4BB9-429A-877C-BFBC4B34186C}</ProjectGuid>
<IgnoreWarnCompileDuplicatedFilename>true</IgnoreWarnCompileDuplicatedFilename>
<Keyword>Win32Proj</Keyword>
- <RootNamespace>test-proxy</RootNamespace>
+ <RootNamespace>test-process</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -120,43 +120,43 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>..\..\..\bin\windows-x86\debug\</OutDir>
- <IntDir>..\..\..\intermediate\windows-x86\debug\test-proxy\</IntDir>
- <TargetName>test-proxy</TargetName>
+ <IntDir>..\..\..\intermediate\windows-x86\debug\test-process\</IntDir>
+ <TargetName>test-process</TargetName>
<TargetExt>.exe</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>..\..\..\bin\windows-x64\debug\</OutDir>
- <IntDir>..\..\..\intermediate\windows-x64\debug\test-proxy\</IntDir>
- <TargetName>test-proxy</TargetName>
+ <IntDir>..\..\..\intermediate\windows-x64\debug\test-process\</IntDir>
+ <TargetName>test-process</TargetName>
<TargetExt>.exe</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug aarch64|ARM'">
<LinkIncremental>true</LinkIncremental>
<OutDir>..\..\..\bin\windows-aarch64\debug\</OutDir>
- <IntDir>..\..\..\intermediate\windows-aarch64\debug\test-proxy\</IntDir>
- <TargetName>test-proxy</TargetName>
+ <IntDir>..\..\..\intermediate\windows-aarch64\debug\test-process\</IntDir>
+ <TargetName>test-process</TargetName>
<TargetExt>.exe</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>..\..\..\bin\windows-x86\release\</OutDir>
- <IntDir>..\..\..\intermediate\windows-x86\release\test-proxy\</IntDir>
- <TargetName>test-proxy</TargetName>
+ <IntDir>..\..\..\intermediate\windows-x86\release\test-process\</IntDir>
+ <TargetName>test-process</TargetName>
<TargetExt>.exe</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>..\..\..\bin\windows-x64\release\</OutDir>
- <IntDir>..\..\..\intermediate\windows-x64\release\test-proxy\</IntDir>
- <TargetName>test-proxy</TargetName>
+ <IntDir>..\..\..\intermediate\windows-x64\release\test-process\</IntDir>
+ <TargetName>test-process</TargetName>
<TargetExt>.exe</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release aarch64|ARM'">
<LinkIncremental>false</LinkIncremental>
<OutDir>..\..\..\bin\windows-aarch64\release\</OutDir>
- <IntDir>..\..\..\intermediate\windows-aarch64\release\test-proxy\</IntDir>
- <TargetName>test-proxy</TargetName>
+ <IntDir>..\..\..\intermediate\windows-aarch64\release\test-process\</IntDir>
+ <TargetName>test-process</TargetName>
<TargetExt>.exe</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@@ -262,7 +262,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
- <ClCompile Include="..\..\..\tools\test-proxy\test-proxy-main.cpp" />
+ <ClCompile Include="..\..\..\tools\test-process\test-process-main.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\compiler-core\compiler-core.vcxproj">
@@ -271,9 +271,6 @@
<ProjectReference Include="..\core\core.vcxproj">
<Project>{F9BE7957-8399-899E-0C49-E714FDDD4B65}</Project>
</ProjectReference>
- <ProjectReference Include="..\slang\slang.vcxproj">
- <Project>{DB00DA62-0533-4AFD-B59F-A67D5B3A0808}</Project>
- </ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/build/visual-studio/test-proxy/test-proxy.vcxproj.filters b/build/visual-studio/test-process/test-process.vcxproj.filters
index 965d73999..96d7f8b1d 100644
--- a/build/visual-studio/test-proxy/test-proxy.vcxproj.filters
+++ b/build/visual-studio/test-process/test-process.vcxproj.filters
@@ -6,7 +6,7 @@
</Filter>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="..\..\..\tools\test-proxy\test-proxy-main.cpp">
+ <ClCompile Include="..\..\..\tools\test-process\test-process-main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
diff --git a/premake5.lua b/premake5.lua
index 13fee9e22..a7f213b95 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -757,11 +757,11 @@ end
links { "compiler-core", "core" }
- tool "test-proxy"
+ tool "test-process"
uuid "BE412850-4BB9-429A-877C-BFBC4B34186C"
includedirs { "." }
- links { "compiler-core", "core", "slang" }
+ links { "compiler-core", "core" }
tool "test-server"
uuid "23149706-C12F-4329-B6AA-8266407C32D3"
diff --git a/slang.sln b/slang.sln
index bdd9545dd..b4b30eeee 100644
--- a/slang.sln
+++ b/slang.sln
@@ -17,7 +17,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-embed", "build\visual
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-generate", "build\visual-studio\slang-generate\slang-generate.vcxproj", "{66174227-8541-41FC-A6DF-4764FC66F78E}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test-proxy", "build\visual-studio\test-proxy\test-proxy.vcxproj", "{BE412850-4BB9-429A-877C-BFBC4B34186C}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test-process", "build\visual-studio\test-process\test-process.vcxproj", "{BE412850-4BB9-429A-877C-BFBC4B34186C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test-server", "build\visual-studio\test-server\test-server.vcxproj", "{23149706-C12F-4329-B6AA-8266407C32D3}"
EndProject
diff --git a/source/compiler-core/slang-json-value.cpp b/source/compiler-core/slang-json-value.cpp
index 216512407..ba4ccad09 100644
--- a/source/compiler-core/slang-json-value.cpp
+++ b/source/compiler-core/slang-json-value.cpp
@@ -401,6 +401,82 @@ bool JSONContainer::asBool(const JSONValue& value)
}
}
+JSONValue JSONContainer::asValue(const JSONValue& inValue)
+{
+ JSONValue value = inValue;
+ switch (value.type)
+ {
+ case JSONValue::Type::StringLexeme:
+ {
+ const UnownedStringSlice slice = getTransientString(inValue);
+ value.stringKey = getKey(slice);
+ value.type = JSONValue::Type::StringValue;
+ break;
+ }
+ case JSONValue::Type::IntegerLexeme:
+ {
+ value.floatValue = value.asFloat();
+ value.type = JSONValue::Type::IntegerValue;
+ break;
+ }
+ case JSONValue::Type::FloatLexeme:
+ {
+ value.floatValue = value.asFloat();
+ value.type = JSONValue::Type::FloatValue;
+ break;
+ }
+ default: break;
+ }
+
+ return value;
+}
+
+void JSONContainer::_clearSourceManagerDependency(JSONValue* ioValues, Index count)
+{
+ for (Index i = 0; i < count; ++i)
+ {
+ auto& value = ioValues[i];
+ value = asValue(value);
+ value.loc = SourceLoc();
+ }
+}
+
+void JSONContainer::clearSourceManagerDependency(JSONValue* ioValues, Index valuesCount)
+{
+ _clearSourceManagerDependency(ioValues, valuesCount);
+
+ // We need to find ranges that are available
+ for (auto& range : m_ranges)
+ {
+ switch (range.type)
+ {
+ case Range::Type::Array:
+ {
+ _clearSourceManagerDependency(m_arrayValues.getBuffer() + range.startIndex, range.count);
+ break;
+ }
+ case Range::Type::Object:
+ {
+ const Index count = range.count;
+ auto pairs = m_objectValues.getBuffer() + range.startIndex;
+
+ for (Index i = 0; i < count; ++i)
+ {
+ auto& pair = pairs[i];
+ pair.keyLoc = SourceLoc();
+ pair.value = asValue(pair.value);
+ pair.value.loc = SourceLoc();
+ }
+ break;
+ }
+ default: break;
+ }
+ }
+
+ // Remove the source manager
+ m_sourceManager = nullptr;
+}
+
int64_t JSONContainer::asInteger(const JSONValue& value)
{
switch (value.type)
diff --git a/source/compiler-core/slang-json-value.h b/source/compiler-core/slang-json-value.h
index b94283d81..2e8707a87 100644
--- a/source/compiler-core/slang-json-value.h
+++ b/source/compiler-core/slang-json-value.h
@@ -233,9 +233,17 @@ public:
/// Set the source manager
void setSourceManager(SourceManager* sourceManger) { m_sourceManager = sourceManger; }
+ /// Clears all the source locs. Useful if the sourceManager is no longer available, or has itself been reset.
+ /// All JSONValues which were Lexeme based will become held in the container
+ /// The source manager will set to nullptr
+ void clearSourceManagerDependency(JSONValue* ioValues, Index count);
+
/// Reset the state
void reset();
+ /// Return inValue as a regular value (ie not held as a lexeme)
+ JSONValue asValue(const JSONValue& inValue);
+
// Ctor
JSONContainer(SourceManager* sourceManger);
@@ -278,6 +286,9 @@ protected:
/// True if the key and value are equal
bool _areEqualOrderedKeys(const JSONKeyValue* a, const JSONKeyValue* b, Index count);
+ void _clearSourceManagerDependency(JSONValue* ioValues, Index count);
+ JSONValue _removeManagerDependency(const JSONValue& inValue);
+
StringBuilder m_buf; ///< A temporary buffer used to hold unescaped strings
SourceView* m_currentView = nullptr;
diff --git a/tools/slang-test/options.cpp b/tools/slang-test/options.cpp
index 4fe7ea6bd..d4dedcf81 100644
--- a/tools/slang-test/options.cpp
+++ b/tools/slang-test/options.cpp
@@ -126,9 +126,13 @@ static bool _isSubCommand(const char* arg)
}
optionsOut->binDir = *argCursor++;
}
- else if (strcmp(arg, "-use-test-proxy") == 0)
+ else if (strcmp(arg, "-use-test-server") == 0)
+ {
+ optionsOut->defaultSpawnType = SpawnType::UseTestServer;
+ }
+ else if (strcmp(arg, "-use-fully-isolated-test-server") == 0)
{
- optionsOut->defaultSpawnType = SpawnType::UseProxy;
+ optionsOut->defaultSpawnType = SpawnType::UseFullyIsolatedTestServer;
}
else if (strcmp(arg, "-use-test-server") == 0)
{
diff --git a/tools/slang-test/options.h b/tools/slang-test/options.h
index 5dc3ca1fb..3b62c903b 100644
--- a/tools/slang-test/options.h
+++ b/tools/slang-test/options.h
@@ -39,9 +39,9 @@ protected:
enum class SpawnType
{
UseExe,
- UseSharedLibrary,
- UseProxy,
- UseTestServer,
+ UseSharedLibrary, ///< Runs testing in process (a crash tan take down the
+ UseTestServer, ///< Use the test server to isolate testing
+ UseFullyIsolatedTestServer, ///< Uses a test server for each test (slow!)
};
struct Options
diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp
index 000ee462c..9648b2ed1 100644
--- a/tools/slang-test/slang-test-main.cpp
+++ b/tools/slang-test/slang-test-main.cpp
@@ -655,8 +655,15 @@ Result spawnAndWaitProxy(TestContext* context, const String& testPath, const Com
return res;
}
-static Result _executeRPC(TestContext* context, const UnownedStringSlice& method, const RttiInfo* rttiInfo, const void* args, ExecuteResult& outRes)
+static Result _executeRPC(TestContext* context, SpawnType spawnType, const UnownedStringSlice& method, const RttiInfo* rttiInfo, const void* args, ExecuteResult& outRes)
{
+ // If we are 'fully isolated', we cannot share a test server.
+ // So tear down the RPC connection if there is one currently.
+ if (spawnType == SpawnType::UseFullyIsolatedTestServer)
+ {
+ context->destroyRPCConnection();
+ }
+
JSONRPCConnection* rpcConnection = context->getOrCreateJSONRPCConnection();
if (!rpcConnection)
{
@@ -693,12 +700,12 @@ static Result _executeRPC(TestContext* context, const UnownedStringSlice& method
}
template <typename T>
-static Result _executeRPC(TestContext* context, const UnownedStringSlice& method, const T* msg, ExecuteResult& outRes)
+static Result _executeRPC(TestContext* context, SpawnType spawnType, const UnownedStringSlice& method, const T* msg, ExecuteResult& outRes)
{
- return _executeRPC(context, method, GetRttiInfo<T>::get(), (const void*)msg, outRes);
+ return _executeRPC(context, spawnType, method, GetRttiInfo<T>::get(), (const void*)msg, outRes);
}
-Result spawnAndWaitTestServer(TestContext* context, const String& testPath, const CommandLine& inCmdLine, ExecuteResult& outRes)
+Result spawnAndWaitTestServer(TestContext* context, SpawnType spawnType, const String& testPath, const CommandLine& inCmdLine, ExecuteResult& outRes)
{
String exeName = Path::getFileNameWithoutExt(inCmdLine.m_executable);
@@ -708,7 +715,7 @@ Result spawnAndWaitTestServer(TestContext* context, const String& testPath, cons
args.toolName = exeName;
args.args = inCmdLine.m_args;
- return _executeRPC(context, TestServerProtocol::ExecuteToolTestArgs::g_methodName, &args, outRes);
+ return _executeRPC(context, spawnType, TestServerProtocol::ExecuteToolTestArgs::g_methodName, &args, outRes);
}
static SlangResult _extractArg(const CommandLine& cmdLine, const String& argName, String& outValue)
@@ -1063,14 +1070,10 @@ ToolReturnCode spawnAndWait(TestContext* context, const String& testPath, SpawnT
spawnResult = spawnAndWaitSharedLibrary(context, testPath, cmdLine, outExeRes);
break;
}
- case SpawnType::UseProxy:
- {
- spawnResult = spawnAndWaitProxy(context, testPath, cmdLine, outExeRes);
- break;
- }
+ case SpawnType::UseFullyIsolatedTestServer:
case SpawnType::UseTestServer:
{
- spawnResult = spawnAndWaitTestServer(context, testPath, cmdLine, outExeRes);
+ spawnResult = spawnAndWaitTestServer(context, spawnType, testPath, cmdLine, outExeRes);
break;
}
default: break;
@@ -3501,46 +3504,8 @@ static SlangResult runUnitTestModule(TestContext* context, TestOptions& testOpti
{
if (testPassesCategoryMask(context, testOptions))
{
- if (spawnType == SpawnType::UseProxy)
- {
- CommandLine cmdLine;
-
- // The 'command' is the module
- cmdLine.setExecutablePath(Path::combine(context->exeDirectoryPath, moduleName));
-
- // Pass the test name / index
- cmdLine.addArg(testName);
-
- {
- StringBuilder buf;
- buf << i;
- cmdLine.addArg(buf.ProduceString());
- }
-
- // Pass the enabled apis
- {
- StringBuilder buf;
- buf << context->options.enabledApis;
- cmdLine.addArg(buf.ProduceString());
- }
-
- {
- TestReporter::TestScope scopeTest(reporter, testOptions.command);
- ExecuteResult exeRes;
-
- const auto testResult = _asTestResult(spawnAndWait(context, filePath, spawnType, cmdLine, exeRes));
-
- // If the test fails, output any output - which might give information about individual tests that have failed.
- if (testResult == TestResult::Fail)
- {
- String output = getOutput(exeRes);
- reporter->message(TestMessageType::TestFailure, output.getBuffer());
- }
-
- reporter->addResult(testResult);
- }
- }
- else if (spawnType == SpawnType::UseTestServer)
+ if (spawnType == SpawnType::UseTestServer ||
+ spawnType == SpawnType::UseFullyIsolatedTestServer)
{
TestServerProtocol::ExecuteUnitTestArgs args;
args.enabledApis = context->options.enabledApis;
@@ -3551,7 +3516,7 @@ static SlangResult runUnitTestModule(TestContext* context, TestOptions& testOpti
TestReporter::TestScope scopeTest(reporter, testOptions.command);
ExecuteResult exeRes;
- SlangResult rpcRes = _executeRPC(context, TestServerProtocol::ExecuteUnitTestArgs::g_methodName, &args, exeRes);
+ SlangResult rpcRes = _executeRPC(context, spawnType, TestServerProtocol::ExecuteUnitTestArgs::g_methodName, &args, exeRes);
const auto testResult = _asTestResult(ToolReturnCode(exeRes.resultCode));
// If the test fails, output any output - which might give information about individual tests that have failed.
diff --git a/tools/slang-unit-test/unit-test-process.cpp b/tools/slang-unit-test/unit-test-process.cpp
index 548ef168f..77f03ddee 100644
--- a/tools/slang-unit-test/unit-test-process.cpp
+++ b/tools/slang-unit-test/unit-test-process.cpp
@@ -2,6 +2,7 @@
#include "../../source/core/slang-string-util.h"
#include "../../source/core/slang-process-util.h"
+
#include "../../source/core/slang-io.h"
#include "../../source/core/slang-http.h"
#include "../../source/core/slang-random-generator.h"
@@ -10,22 +11,30 @@
using namespace Slang;
+static SlangResult _createProcess(UnitTestContext* context, const char* toolName, const List<String>* optArgs, RefPtr<Process>& outProcess)
+{
+ CommandLine cmdLine;
+ cmdLine.setExecutable(context->executableDirectory, "test-process");
+ cmdLine.addArg(toolName);
+ if (optArgs)
+ {
+ cmdLine.m_args.addRange(optArgs->getBuffer(), optArgs->getCount());
+ }
+
+ SLANG_RETURN_ON_FAIL(Process::create(cmdLine, Process::Flag::AttachDebugger, outProcess));
+
+ return SLANG_OK;
+}
+
static SlangResult _httpReflectTest(UnitTestContext* context)
{
SlangResult finalRes = SLANG_OK;
RefPtr<Process> process;
-
- {
- CommandLine cmdLine;
- cmdLine.setExecutable(context->executableDirectory, "test-proxy");
- cmdLine.addArg("http-reflect");
- SLANG_RETURN_ON_FAIL(Process::create(cmdLine, Process::Flag::AttachDebugger, process));
- }
+ SLANG_RETURN_ON_FAIL(_createProcess(context, "http-reflect", nullptr, process));
Stream* writeStream = process->getStream(Process::StreamType::StdIn);
RefPtr<BufferedReadStream> readStream( new BufferedReadStream(process->getStream(Process::StreamType::StdOut)));
-
RefPtr<HTTPPacketConnection> connection = new HTTPPacketConnection(readStream, writeStream);
RefPtr<RandomGenerator> rand = RandomGenerator::create(10000);
@@ -81,32 +90,27 @@ static SlangResult _httpReflectTest(UnitTestContext* context)
static SlangResult _countTest(UnitTestContext* context, Index size, Index crashIndex = -1)
{
- RefPtr<Process> process;
-
/* Here we are trying to test what happens if the server produces a large amount of data, and
we just wait for termination. Do we receive all of the data irrespective of how much there is? */
+ List<String> args;
{
- CommandLine cmdLine;
-
- cmdLine.setExecutable(context->executableDirectory, "test-proxy");
- cmdLine.addArg("count");
-
StringBuilder buf;
buf << size;
- cmdLine.addArg(buf);
+ args.add(buf);
if (crashIndex >= 0)
{
buf.Clear();
buf << crashIndex;
- cmdLine.addArg(buf);
+ args.add(buf);
}
-
- SLANG_RETURN_ON_FAIL(Process::create(cmdLine, Process::Flag::AttachDebugger, process));
}
+ RefPtr<Process> process;
+ SLANG_RETURN_ON_FAIL(_createProcess(context, "count", &args, process));
+
ExecuteResult exeRes;
#if 0
@@ -156,12 +160,7 @@ static SlangResult _countTests(UnitTestContext* context)
static SlangResult _reflectTest(UnitTestContext* context)
{
RefPtr<Process> process;
- {
- CommandLine cmdLine;
- cmdLine.setExecutable(context->executableDirectory, "test-proxy");
- cmdLine.addArg("reflect");
- SLANG_RETURN_ON_FAIL(Process::create(cmdLine, Process::Flag::AttachDebugger, process));
- }
+ SLANG_RETURN_ON_FAIL(_createProcess(context, "reflect", nullptr, process));
// Write a bunch of stuff to the stream
Stream* readStream = process->getStream(Process::StreamType::StdOut);
@@ -191,8 +190,6 @@ static SlangResult _reflectTest(UnitTestContext* context)
SLANG_UNIT_TEST(CommandLineProcess)
{
SLANG_CHECK(SLANG_SUCCEEDED(_countTests(unitTestContext)));
-
SLANG_CHECK(SLANG_SUCCEEDED(_reflectTest(unitTestContext)));
-
SLANG_CHECK(SLANG_SUCCEEDED(_httpReflectTest(unitTestContext)));
}
diff --git a/tools/test-process/test-process-main.cpp b/tools/test-process/test-process-main.cpp
new file mode 100644
index 000000000..c31fec3ed
--- /dev/null
+++ b/tools/test-process/test-process-main.cpp
@@ -0,0 +1,193 @@
+// test-process-main.cpp
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "../../slang-com-helper.h"
+
+#include "../../source/core/slang-string.h"
+#include "../../source/core/slang-io.h"
+#include "../../source/core/slang-string-util.h"
+#include "../../source/core/slang-process-util.h"
+
+#include "../../source/core/slang-test-tool-util.h"
+#include "../../source/core/slang-http.h"
+
+namespace TestProcess
+{
+using namespace Slang;
+
+static void _makeStdStreamsUnbuffered()
+{
+ // Make these streams unbuffered
+ setvbuf(stdout, nullptr, _IONBF, 0);
+ setvbuf(stderr, nullptr, _IONBF, 0);
+}
+
+static SlangResult _outputCount(int argc, const char* const* argv)
+{
+ if (argc < 3)
+ {
+ return SLANG_FAIL;
+ }
+ // Get the count
+ const Index count = StringToInt(argv[2]);
+
+ // If we want to crash
+ Index crashIndex = -1;
+ if (argc > 3)
+ {
+ // When we crash, we want to make sure everything is flushed...
+ _makeStdStreamsUnbuffered();
+ crashIndex = StringToInt(argv[3]);
+ }
+
+ FILE* fileOut = stdout;
+
+ StringBuilder buf;
+ for (Index i = 0; i < count; ++i)
+ {
+ buf.Clear();
+ buf << i << "\n";
+
+ fwrite(buf.getBuffer(), 1, buf.getLength(), fileOut);
+
+ if (i == crashIndex)
+ {
+ // Use to simulate a crash.
+ SLANG_BREAKPOINT(0);
+ throw;
+ }
+ }
+
+ // NOTE! There is no flush here, we want to see if everything works if we just stream out.
+ return SLANG_OK;
+}
+
+static SlangResult _outputReflect()
+{
+ // Read lines from std input.
+ // When hit line with just 'end', terminate
+
+ // Get in as Stream
+
+ RefPtr<Stream> stdinStream;
+ Process::getStdStream(Process::StreamType::StdIn, stdinStream);
+
+ FILE* fileOut = stdout;
+
+ List<Byte> buffer;
+
+ Index lineCount = 0;
+ Index startIndex = 0;
+
+ while (true)
+ {
+ SLANG_RETURN_ON_FAIL(StreamUtil::read(stdinStream, 0, buffer));
+
+ while (true)
+ {
+ UnownedStringSlice slice((const char*)buffer.begin() + startIndex, (const char*)buffer.end());
+ UnownedStringSlice line;
+
+ if (!StringUtil::extractLine(slice, line) || slice.begin() == nullptr)
+ {
+ break;
+ }
+
+ // Process the line
+ if (line == UnownedStringSlice::fromLiteral("end"))
+ {
+ return SLANG_OK;
+ }
+
+ // Write the text to the output stream
+ fwrite(line.begin(), 1, line.getLength(), fileOut);
+ fputc('\n', fileOut);
+
+ lineCount++;
+
+ // Move the start index forward
+ const Index newStartIndex = slice.begin() ? Index(slice.begin() - (const char*)buffer.getBuffer()) : buffer.getCount();
+ SLANG_ASSERT(newStartIndex > startIndex);
+ startIndex = newStartIndex;
+ }
+ }
+}
+
+static SlangResult _httpReflect(int argc, const char* const* argv)
+{
+ SLANG_UNUSED(argc);
+ SLANG_UNUSED(argv);
+
+ RefPtr<Stream> stdinStream, stdoutStream;
+
+ Process::getStdStream(Process::StreamType::StdIn, stdinStream);
+ Process::getStdStream(Process::StreamType::StdOut, stdoutStream);
+
+ RefPtr<BufferedReadStream> readStream(new BufferedReadStream(stdinStream));
+
+ RefPtr<HTTPPacketConnection> connection = new HTTPPacketConnection(readStream, stdoutStream);
+
+ while (connection->isActive())
+ {
+ // Block waiting for content (or error/closed)
+ SLANG_RETURN_ON_FAIL(connection->waitForResult());
+
+ // If we have content do something with it
+ if (connection->hasContent())
+ {
+ auto content = connection->getContent();
+
+ // If it just holds 'end' then we are done
+ const UnownedStringSlice slice((const char*)content.begin(), content.getCount());
+
+ if (slice == UnownedStringSlice::fromLiteral("end"))
+ {
+ break;
+ }
+
+ // Else reflect it back
+ SLANG_RETURN_ON_FAIL(connection->write(content.begin(), content.getCount()));
+
+ // Consume that content/packet
+ connection->consumeContent();
+ }
+ }
+
+ return SLANG_OK;
+}
+
+static SlangResult execute(int argc, const char*const* argv)
+{
+ if (argc < 2)
+ {
+ return SLANG_FAIL;
+ }
+
+ // Get the tool name
+ const String toolName = argv[1];
+ if (toolName == "reflect")
+ {
+ return _outputReflect();
+ }
+ else if (toolName == "count")
+ {
+ return _outputCount(argc, argv);
+ }
+ else if (toolName == "http-reflect")
+ {
+ return _httpReflect(argc, argv);
+ }
+ return SLANG_E_NOT_AVAILABLE;
+}
+
+} // namespace TestProcess
+
+int main(int argc, const char* const* argv)
+{
+ SlangResult res = TestProcess::execute(argc, argv);
+ return (int)Slang::TestToolUtil::getReturnCode(res);
+}
diff --git a/tools/test-proxy/test-proxy-main.cpp b/tools/test-proxy/test-proxy-main.cpp
deleted file mode 100644
index bcb8f2a92..000000000
--- a/tools/test-proxy/test-proxy-main.cpp
+++ /dev/null
@@ -1,406 +0,0 @@
-// main.cpp
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../../source/core/slang-secure-crt.h"
-
-#include "../../slang-com-helper.h"
-
-#include "../../source/core/slang-string.h"
-#include "../../source/core/slang-io.h"
-#include "../../source/core/slang-writer.h"
-#include "../../source/core/slang-string-util.h"
-#include "../../source/core/slang-process-util.h"
-
-#include "../../source/core/slang-shared-library.h"
-
-#include "../../source/core/slang-test-tool-util.h"
-#include "../../source/core/slang-http.h"
-
-#include "tools/unit-test/slang-unit-test.h"
-
-namespace TestProxy
-{
-using namespace Slang;
-
-class TestReporter : public ITestReporter
-{
-public:
- // ITestReporter
- virtual SLANG_NO_THROW void SLANG_MCALL startTest(const char* testName) SLANG_OVERRIDE { }
- virtual SLANG_NO_THROW void SLANG_MCALL addResult(TestResult result)SLANG_OVERRIDE;
- virtual SLANG_NO_THROW void SLANG_MCALL addResultWithLocation(TestResult result, const char* testText, const char* file, int line) SLANG_OVERRIDE;
- virtual SLANG_NO_THROW void SLANG_MCALL addResultWithLocation(bool testSucceeded, const char* testText, const char* file, int line) SLANG_OVERRIDE;
- virtual SLANG_NO_THROW void SLANG_MCALL addExecutionTime(double time) SLANG_OVERRIDE { }
- virtual SLANG_NO_THROW void SLANG_MCALL message(TestMessageType type, const char* message) SLANG_OVERRIDE;
- virtual SLANG_NO_THROW void SLANG_MCALL endTest() SLANG_OVERRIDE { }
-
- StringBuilder m_buf;
- Index m_failCount = 0;
- Index m_testCount = 0;
-};
-
-
-void TestReporter::message(TestMessageType type, const char* message)
-{
- if (type == TestMessageType::RunError ||
- type == TestMessageType::TestFailure)
- {
- m_failCount++;
- }
-
- m_buf << message << "\n";
-}
-
-void TestReporter::addResultWithLocation(TestResult result, const char* testText, const char* file, int line)
-{
- if (result == TestResult::Fail)
- {
- addResultWithLocation(false, testText, file, line);
- }
- else
- {
- m_testCount++;
- }
-}
-
-void TestReporter::addResultWithLocation(bool testSucceeded, const char* testText, const char* file, int line)
-{
- m_testCount++;
-
- if (testSucceeded)
- {
- return;
- }
-
- m_buf << "[Failed]: " << testText << "\n";
- m_buf << file << ":" << line << "\n";
-
- m_failCount++;
-}
-
-void TestReporter::addResult(TestResult result)
-{
- if (result == TestResult::Fail)
- {
- m_failCount++;
- }
-}
-
-static SlangResult _createSlangSession(const char* exePath, int argc, const char* const* argv, ComPtr<slang::IGlobalSession>& outSession)
-{
-
- ComPtr<slang::IGlobalSession> session;
-
- // The sharedSession always has a pre-loaded stdlib, is sharedSession is not nullptr.
- // This differed test checks if the command line has an option to setup the stdlib.
- // If so we *don't* use the sharedSession, and create a new stdlib-less session just for this compilation.
- if (TestToolUtil::hasDeferredStdLib(argc, argv))
- {
- SLANG_RETURN_ON_FAIL(slang_createGlobalSessionWithoutStdLib(SLANG_API_VERSION, session.writeRef()));
- TestToolUtil::setSessionDefaultPreludeFromExePath(exePath, session);
- }
- else
- {
- // Just create the global session in the regular way if there isn't one set
- SLANG_RETURN_ON_FAIL(slang_createGlobalSession(SLANG_API_VERSION, session.writeRef()));
- TestToolUtil::setSessionDefaultPreludeFromExePath(exePath, session);
- }
-
- outSession.swap(session);
- return SLANG_OK;
-}
-
-static void _makeStdStreamsUnbuffered()
-{
- // Make these streams unbuffered
- setvbuf(stdout, nullptr, _IONBF, 0);
- setvbuf(stderr, nullptr, _IONBF, 0);
-}
-
-static SlangResult _outputCount(int argc, const char* const* argv)
-{
- if (argc < 3)
- {
- return SLANG_FAIL;
- }
- // Get the count
- const Index count = StringToInt(argv[2]);
-
- // If we want to crash
- Index crashIndex = -1;
- if (argc > 3)
- {
- // When we crash, we want to make sure everything is flushed...
- _makeStdStreamsUnbuffered();
- crashIndex = StringToInt(argv[3]);
- }
-
- FILE* fileOut = stdout;
-
- StringBuilder buf;
- for (Index i = 0; i < count; ++i)
- {
- buf.Clear();
- buf << i << "\n";
-
- fwrite(buf.getBuffer(), 1, buf.getLength(), fileOut);
-
- if (i == crashIndex)
- {
- // Use to simulate a crash.
- SLANG_BREAKPOINT(0);
- throw;
- }
- }
-
- // NOTE! There is no flush here, we want to see if everything works if we just stream out.
- return SLANG_OK;
-}
-
-static SlangResult _outputReflect()
-{
- // Read lines from std input.
- // When hit line with just 'end', terminate
-
- // Get in as Stream
-
- RefPtr<Stream> stdinStream;
- Process::getStdStream(Process::StreamType::StdIn, stdinStream);
-
- FILE* fileOut = stdout;
-
- List<Byte> buffer;
-
- Index lineCount = 0;
- Index startIndex = 0;
-
- while (true)
- {
- SLANG_RETURN_ON_FAIL(StreamUtil::read(stdinStream, 0, buffer));
-
- while (true)
- {
- UnownedStringSlice slice((const char*)buffer.begin() + startIndex, (const char*)buffer.end());
- UnownedStringSlice line;
-
- if (!StringUtil::extractLine(slice, line) || slice.begin() == nullptr)
- {
- break;
- }
-
- // Process the line
- if (line == UnownedStringSlice::fromLiteral("end"))
- {
- return SLANG_OK;
- }
-
- // Write the text to the output stream
- fwrite(line.begin(), 1, line.getLength(), fileOut);
- fputc('\n', fileOut);
-
- lineCount++;
-
- // Move the start index forward
- const Index newStartIndex = slice.begin() ? Index(slice.begin() - (const char*)buffer.getBuffer()) : buffer.getCount();
- SLANG_ASSERT(newStartIndex > startIndex);
- startIndex = newStartIndex;
- }
- }
-}
-
-static SlangResult _httpReflect(int argc, const char* const* argv)
-{
- SLANG_UNUSED(argc);
- SLANG_UNUSED(argv);
-
- RefPtr<Stream> stdinStream, stdoutStream;
-
- Process::getStdStream(Process::StreamType::StdIn, stdinStream);
- Process::getStdStream(Process::StreamType::StdOut, stdoutStream);
-
- RefPtr<BufferedReadStream> readStream(new BufferedReadStream(stdinStream));
-
- RefPtr<HTTPPacketConnection> connection = new HTTPPacketConnection(readStream, stdoutStream);
-
- while (connection->isActive())
- {
- // Block waiting for content (or error/closed)
- SLANG_RETURN_ON_FAIL(connection->waitForResult());
-
- // If we have content do something with it
- if (connection->hasContent())
- {
- auto content = connection->getContent();
-
- // If it just holds 'end' then we are done
- const UnownedStringSlice slice((const char*)content.begin(), content.getCount());
-
- if (slice == UnownedStringSlice::fromLiteral("end"))
- {
- break;
- }
-
- // Else reflect it back
- SLANG_RETURN_ON_FAIL(connection->write(content.begin(), content.getCount()));
-
- // Consume that content/packet
- connection->consumeContent();
- }
- }
-
- return SLANG_OK;
-}
-
-static SlangResult execute(int argc, const char*const* argv)
-{
- typedef Slang::TestToolUtil::InnerMainFunc InnerMainFunc;
-
- if (argc < 2)
- {
- return SLANG_FAIL;
- }
-
- String exePath = Path::getParentDirectory(argv[0]);
-
- // The 'exeName' of the tool.
- const String toolName = argv[1];
-
- if (toolName == "reflect")
- {
- return _outputReflect();
- }
-
- if (toolName == "count")
- {
- return _outputCount(argc, argv);
- }
-
- if (toolName == "http-reflect")
- {
- return _httpReflect(argc, argv);
- }
-
- {
- StringBuilder sharedLibToolBuilder;
- sharedLibToolBuilder.append(toolName);
- sharedLibToolBuilder.append("-tool");
-
- auto toolPath = Path::combine(exePath, sharedLibToolBuilder);
-
- ComPtr<ISlangSharedLibrary> sharedLibrary;
- if (SLANG_SUCCEEDED(DefaultSharedLibraryLoader::getSingleton()->loadSharedLibrary(toolPath.getBuffer(), sharedLibrary.writeRef())))
- {
- // Assume we will used the shared session
- ComPtr<slang::IGlobalSession> session;
- SLANG_RETURN_ON_FAIL(_createSlangSession(argv[0], argc - 2, argv + 2, session));
-
- auto func = (InnerMainFunc)sharedLibrary->findFuncByName("innerMain");
- if (!func)
- {
- return SLANG_FAIL;
- }
-
- // Work out the args sent to the shared library
- List<const char*> args;
- args.add(argv[0]);
- args.addRange(argv + 2, Index(argc - 2));
-
- RefPtr<StdWriters> stdWriters = StdWriters::createDefault();
-
- const SlangResult res = func(stdWriters, session, int(args.getCount()), args.begin());
- return res;
- }
- }
-
- // Okay lets assume it's a unit test
- {
- auto toolPath = Path::combine(exePath, toolName);
-
- ComPtr<ISlangSharedLibrary> sharedLibrary;
- SLANG_RETURN_ON_FAIL(SLANG_SUCCEEDED(DefaultSharedLibraryLoader::getSingleton()->loadSharedLibrary(toolPath.getBuffer(), sharedLibrary.writeRef())));
-
- // get the unit test export name
-
- UnitTestGetModuleFunc getModuleFunc = (UnitTestGetModuleFunc)sharedLibrary->findFuncByName("slangUnitTestGetModule");
- if (!getModuleFunc)
- return SLANG_FAIL;
-
- IUnitTestModule* testModule = getModuleFunc();
- if (!testModule)
- return SLANG_FAIL;
-
- // argv[0] exe,
- // argv[1] tool
- // argv[2] test name
- // argv[3] test index
- // argv[4] the enabled apis
-
- if (argc < 5)
- {
- return SLANG_FAIL;
- }
-
- TestReporter testReporter;
-
- testModule->setTestReporter(&testReporter);
-
- Int enabledApis;
- SLANG_RETURN_ON_FAIL(StringUtil::parseInt(UnownedStringSlice(argv[4]), enabledApis));
-
- Int testIndex;
- SLANG_RETURN_ON_FAIL(StringUtil::parseInt(UnownedStringSlice(argv[3]), testIndex));
-
- // Assume we will used the shared session
- ComPtr<slang::IGlobalSession> session;
- SLANG_RETURN_ON_FAIL(_createSlangSession(argv[0], argc - 5, argv + 5, session));
-
- UnitTestContext unitTestContext;
- unitTestContext.slangGlobalSession = session;
- unitTestContext.workDirectory = "";
- unitTestContext.enabledApis = RenderApiFlags(enabledApis);
- unitTestContext.executableDirectory = exePath.getBuffer();
-
- auto testCount = testModule->getTestCount();
- SLANG_ASSERT(testIndex >= 0 && testIndex < testCount);
-
- UnitTestFunc testFunc = testModule->getTestFunc(testIndex);
-
- try
- {
- testFunc(&unitTestContext);
- }
- catch (...)
- {
- testReporter.m_failCount++;
- }
-
- if (testReporter.m_failCount > 0)
- {
- // Write out to stderr...
- auto writers = StdWriters::createDefault();
- writers->getError().put(testReporter.m_buf.getUnownedSlice());
- return SLANG_FAIL;
- }
-
- if (testReporter.m_testCount == 0)
- {
- return SLANG_E_NOT_AVAILABLE;
- }
-
- return SLANG_OK;
- }
-
- return SLANG_E_NOT_AVAILABLE;
-}
-
-} // namespace TestProxy
-
-int main(int argc, const char* const* argv)
-{
- using namespace TestProxy;
- SlangResult res = execute(argc, argv);
- return (int)TestToolUtil::getReturnCode(res);
-}