yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Jay KwakAdding slang-test option to ignore abort popup message (#8492)979e16a34

master
8.8 KiB316 linesraw
1// test-context.cpp
2#include "test-context.h"
3
4#include "../../source/compiler-core/slang-language-server-protocol.h"
5#include "../../source/core/slang-io.h"
6#include "../../source/core/slang-shared-library.h"
7#include "../../source/core/slang-string-util.h"
8#include "../../source/core/slang-test-tool-util.h"
9
10#include <stdio.h>
11#include <stdlib.h>
12
13using namespace Slang;
14
15thread_local int slangTestThreadIndex = 0;
16
17TestContext::TestContext()
18{
19    /// if we are testing on arm, debug, we may want to increase the connection timeout
20#if (SLANG_PROCESSOR_ARM || SLANG_PROCESSOR_ARM_64) && defined(_DEBUG)
21    // 10 mins(!). This seems to be the order of time needed for timeout on a CI ARM test system on
22    // debug
23    connectionTimeOutInMs = 1000 * 60 * 10;
24#endif
25}
26
27void TestContext::setThreadIndex(int index)
28{
29    slangTestThreadIndex = index;
30}
31
32void TestContext::setMaxTestRunnerThreadCount(int count)
33{
34    m_jsonRpcConnections.setCount(count);
35    m_testRequirements.setCount(count);
36    m_reporters.setCount(count);
37    for (auto& reporter : m_reporters)
38    {
39        reporter = nullptr;
40    }
41}
42
43void TestContext::setTestRequirements(TestRequirements* req)
44{
45    m_testRequirements[slangTestThreadIndex] = req;
46}
47
48TestRequirements* TestContext::getTestRequirements() const
49{
50    return m_testRequirements[slangTestThreadIndex];
51}
52
53void TestContext::setTestReporter(TestReporter* reporter)
54{
55    m_reporters[slangTestThreadIndex] = reporter;
56}
57
58TestReporter* TestContext::getTestReporter()
59{
60    return m_reporters[slangTestThreadIndex];
61}
62
63SlangResult TestContext::locateFileCheck()
64{
65    DefaultSharedLibraryLoader* loader = DefaultSharedLibraryLoader::getSingleton();
66
67    SLANG_RETURN_ON_FAIL(loader->loadSharedLibrary("slang-llvm", m_fileCheckLibrary.writeRef()));
68
69    if (!m_fileCheckLibrary)
70    {
71        return SLANG_FAIL;
72    }
73
74    using CreateFileCheckFunc = SlangResult (*)(const SlangUUID&, void**);
75    auto fn = reinterpret_cast<CreateFileCheckFunc>(
76        m_fileCheckLibrary->findFuncByName("createLLVMFileCheck_V1"));
77    if (!fn)
78    {
79        return SLANG_FAIL;
80    }
81    return fn(SLANG_IID_PPV_ARGS(m_fileCheck.writeRef()));
82}
83
84Result TestContext::init(const char* inExePath)
85{
86    SlangGlobalSessionDesc desc = {};
87    desc.enableGLSL = true;
88    SLANG_RETURN_ON_FAIL(slang::createGlobalSession(&desc, m_session.writeRef()));
89    exePath = inExePath;
90    SLANG_RETURN_ON_FAIL(TestToolUtil::getExeDirectoryPath(inExePath, exeDirectoryPath));
91    SLANG_RETURN_ON_FAIL(TestToolUtil::getDllDirectoryPath(inExePath, dllDirectoryPath));
92
93    SLANG_RETURN_ON_FAIL(locateFileCheck());
94
95    return SLANG_OK;
96}
97
98TestContext::~TestContext()
99{
100    if (m_languageServerConnection)
101    {
102        m_languageServerConnection->sendCall(
103            LanguageServerProtocol::ExitParams::methodName,
104            JSONValue::makeInt(0));
105    }
106}
107
108TestContext::InnerMainFunc TestContext::getInnerMainFunc(const String& dirPath, const String& name)
109{
110    {
111        SharedLibraryTool* tool = m_sharedLibTools.tryGetValue(name);
112        if (tool)
113        {
114            return tool->m_func;
115        }
116    }
117
118    StringBuilder sharedLibToolBuilder;
119    sharedLibToolBuilder.append(name);
120    sharedLibToolBuilder.append("-tool");
121
122    StringBuilder path;
123    SharedLibrary::appendPlatformFileName(sharedLibToolBuilder.getUnownedSlice(), path);
124
125    DefaultSharedLibraryLoader* loader = DefaultSharedLibraryLoader::getSingleton();
126
127    SharedLibraryTool tool = {};
128
129    if (SLANG_SUCCEEDED(
130            loader->loadPlatformSharedLibrary(path.begin(), tool.m_sharedLibrary.writeRef())))
131    {
132        tool.m_func = (InnerMainFunc)tool.m_sharedLibrary->findFuncByName("innerMain");
133        tool.m_cleanDeviceCacheFunc =
134            (CleanDeviceCacheFunc)tool.m_sharedLibrary->findFuncByName("cleanDeviceCache");
135    }
136
137    m_sharedLibTools.add(name, tool);
138    return tool.m_func;
139}
140
141void TestContext::setInnerMainFunc(const String& name, InnerMainFunc func)
142{
143    SharedLibraryTool* tool = m_sharedLibTools.tryGetValue(name);
144    if (tool)
145    {
146        tool->m_sharedLibrary.setNull();
147        tool->m_func = func;
148    }
149    else
150    {
151        SharedLibraryTool tool = {};
152        tool.m_func = func;
153        m_sharedLibTools.add(name, tool);
154    }
155}
156
157TestContext::CleanDeviceCacheFunc TestContext::getCleanDeviceCacheFunc(const String& name)
158{
159    SharedLibraryTool* tool = m_sharedLibTools.tryGetValue(name);
160    if (tool)
161    {
162        return tool->m_cleanDeviceCacheFunc;
163    }
164
165    return nullptr;
166}
167
168DownstreamCompilerSet* TestContext::getCompilerSet()
169{
170    std::lock_guard<std::mutex> lock(mutex);
171    if (!compilerSet)
172    {
173        compilerSet = new DownstreamCompilerSet;
174
175        DownstreamCompilerLocatorFunc locators[int(SLANG_PASS_THROUGH_COUNT_OF)] = {nullptr};
176
177        DownstreamCompilerUtil::setDefaultLocators(locators);
178        for (Index i = 0; i < Index(SLANG_PASS_THROUGH_COUNT_OF); ++i)
179        {
180            auto locator = locators[i];
181            if (locator)
182            {
183                locator(String(), DefaultSharedLibraryLoader::getSingleton(), compilerSet);
184            }
185        }
186
187        DownstreamCompilerUtil::updateDefaults(compilerSet);
188    }
189    return compilerSet;
190}
191
192SlangResult TestContext::_createJSONRPCConnection(RefPtr<JSONRPCConnection>& out)
193{
194    RefPtr<Process> process;
195
196    {
197        CommandLine cmdLine;
198        cmdLine.setExecutableLocation(ExecutableLocation(exeDirectoryPath, "test-server"));
199
200        if (options.ignoreAbortMsg)
201        {
202            cmdLine.addArg("-ignore-abort-msg");
203        }
204
205        SLANG_RETURN_ON_FAIL(Process::create(
206            cmdLine,
207            Process::Flag::AttachDebugger | Process::Flag::DisableStdErrRedirection,
208            process));
209    }
210
211    Stream* writeStream = process->getStream(StdStreamType::In);
212    RefPtr<BufferedReadStream> readStream(
213        new BufferedReadStream(process->getStream(StdStreamType::Out)));
214    RefPtr<BufferedReadStream> readErrStream(
215        new BufferedReadStream(process->getStream(StdStreamType::ErrorOut)));
216
217    RefPtr<HTTPPacketConnection> connection = new HTTPPacketConnection(readStream, writeStream);
218    RefPtr<JSONRPCConnection> rpcConnection = new JSONRPCConnection;
219
220    SLANG_RETURN_ON_FAIL(
221        rpcConnection->init(connection, JSONRPCConnection::CallStyle::Default, process));
222
223    out = rpcConnection;
224
225    return SLANG_OK;
226}
227
228SlangResult TestContext::createLanguageServerJSONRPCConnection(RefPtr<JSONRPCConnection>& out)
229{
230    RefPtr<Process> process;
231
232    {
233        CommandLine cmdLine;
234        cmdLine.setExecutableLocation(ExecutableLocation(exeDirectoryPath, "slangd"));
235        cmdLine.addArg("-periodic-diagnostic-update");
236        cmdLine.addArg("false");
237        SLANG_RETURN_ON_FAIL(Process::create(cmdLine, Process::Flag::AttachDebugger, process));
238    }
239
240    Stream* writeStream = process->getStream(StdStreamType::In);
241    RefPtr<BufferedReadStream> readStream(
242        new BufferedReadStream(process->getStream(StdStreamType::Out)));
243
244    RefPtr<HTTPPacketConnection> connection = new HTTPPacketConnection(readStream, writeStream);
245    RefPtr<JSONRPCConnection> rpcConnection = new JSONRPCConnection;
246
247    SLANG_RETURN_ON_FAIL(
248        rpcConnection->init(connection, JSONRPCConnection::CallStyle::Object, process));
249
250    out = rpcConnection;
251
252    return SLANG_OK;
253}
254
255void TestContext::destroyRPCConnection()
256{
257    if (m_jsonRpcConnections[slangTestThreadIndex])
258    {
259        m_jsonRpcConnections[slangTestThreadIndex]->disconnect();
260        m_jsonRpcConnections[slangTestThreadIndex].setNull();
261    }
262}
263
264Slang::JSONRPCConnection* TestContext::getOrCreateJSONRPCConnection()
265{
266    if (!m_jsonRpcConnections[slangTestThreadIndex])
267    {
268        if (SLANG_FAILED(_createJSONRPCConnection(m_jsonRpcConnections[slangTestThreadIndex])))
269        {
270            return nullptr;
271        }
272    }
273
274    return m_jsonRpcConnections[slangTestThreadIndex];
275}
276
277
278Slang::IDownstreamCompiler* TestContext::getDefaultCompiler(SlangSourceLanguage sourceLanguage)
279{
280    DownstreamCompilerSet* set = getCompilerSet();
281    return set ? set->getDefaultCompiler(sourceLanguage) : nullptr;
282}
283
284bool TestContext::canRunTestWithRenderApiFlags(Slang::RenderApiFlags requiredFlags)
285{
286    // If only allow tests that use API - then the requiredFlags must be 0
287    if (options.apiOnly && requiredFlags == 0)
288    {
289        return false;
290    }
291    // Are the required rendering APIs enabled from the -api command line switch
292    return (requiredFlags & options.enabledApis) == requiredFlags;
293}
294
295SpawnType TestContext::getFinalSpawnType(SpawnType spawnType)
296{
297    if (spawnType == SpawnType::Default)
298    {
299        if (options.outputMode == TestOutputMode::Default)
300        {
301            return SpawnType::UseSharedLibrary;
302        }
303        else
304        {
305            return SpawnType::UseTestServer;
306        }
307    }
308
309    // Just return whatever spawnType was passed in
310    return spawnType;
311}
312
313SpawnType TestContext::getFinalSpawnType()
314{
315    return getFinalSpawnType(options.defaultSpawnType);
316}