mirror of
https://github.com/4ian/GDevelop.git
synced 2026-10-12 02:01:17 +00:00
@@ -326,7 +326,13 @@ jobs:
|
||||
|
||||
- run:
|
||||
name: Run tests
|
||||
command: cd GDevelop.js && npm run test -- --maxWorkers=4
|
||||
# Tests are slow under ASan and jest (in a non-TTY environment) only prints
|
||||
# output when a whole test file finishes, so allow long silences instead of
|
||||
# killing the step after the default 10 minutes without output.
|
||||
no_output_timeout: 30m
|
||||
# malloc_context_size: record fewer stack frames on each malloc/free (default
|
||||
# is 30) - a small, free speedup that only shortens traces in ASan reports.
|
||||
command: cd GDevelop.js && ASAN_OPTIONS=malloc_context_size=5 npm run test -- --maxWorkers=4
|
||||
|
||||
# Upload artifacts (CircleCI)
|
||||
- store_artifacts:
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
// If running under ASAN, disable the "container overflow" checks because of false positives
|
||||
// with std::vector<gd::String>. See https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow.
|
||||
if (Module['ASAN_OPTIONS'] === undefined)
|
||||
Module['ASAN_OPTIONS'] ='detect_container_overflow=0';
|
||||
// Also append options from the ASAN_OPTIONS environment variable when running in Node.js,
|
||||
// as Emscripten only reads them from Module['ASAN_OPTIONS'] (not from the environment).
|
||||
if (Module['ASAN_OPTIONS'] === undefined) {
|
||||
var envAsanOptions =
|
||||
typeof process !== 'undefined' && process.env && process.env.ASAN_OPTIONS
|
||||
? ':' + process.env.ASAN_OPTIONS
|
||||
: '';
|
||||
Module['ASAN_OPTIONS'] = 'detect_container_overflow=0' + envAsanOptions;
|
||||
}
|
||||
|
||||
// Prevent calling process["exit"] when there is a abort/runtime crash
|
||||
// (useful for tests when running ASAN, to see the logs).
|
||||
|
||||
@@ -23,7 +23,7 @@ elseif("${GDEVELOPJS_BUILD_VARIANT}" STREQUAL "debug-assertions")
|
||||
# Debug with assertions: no optimization.
|
||||
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g --profiling") # Debugging + profiling support
|
||||
elseif("${GDEVELOPJS_BUILD_VARIANT}" STREQUAL "debug-sanitizers")
|
||||
# Debug with sanitizers: no optimization.
|
||||
# Debug with sanitizers (note: -O3 from the Release build type still applies at compile time).
|
||||
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g --profiling") # Debugging + profiling support
|
||||
add_compile_options(-fsanitize=address) # Uncomment to auto-detect occurences of memory bugs (memory leak, use after free, overflows, ...) - also enable linking below!
|
||||
# add_compile_options(-fsanitize=undefined) # Uncomment to auto-detect occurences of undefined behavior - also enable linking below!
|
||||
@@ -111,6 +111,8 @@ elseif("${GDEVELOPJS_BUILD_VARIANT}" STREQUAL "debug-assertions")
|
||||
# target_link_libraries(--memoryprofiler) # Uncomment for interactive memory profiling
|
||||
elseif("${GDEVELOPJS_BUILD_VARIANT}" STREQUAL "debug-sanitizers")
|
||||
message(STATUS "'debug-sanitizers' variant: enabling ASAN and other sanitizers")
|
||||
target_link_libraries(GD "-O1") # Some optimization at link time (default is -O0), to make the tests run a bit faster in CI.
|
||||
target_link_libraries(GD "-s INITIAL_MEMORY=512MB") # Start with a large heap: ASan needs a lot of memory (256MB quarantine for freed allocations, shadow memory) and growing the memory repeatedly has a cost. Overrides TOTAL_MEMORY set above.
|
||||
target_link_libraries(GD "-fsanitize=address") # Uncomment to auto-detect occurences of memory bugs (memory leak, use after free, overflows, ...) - also enable compiling above!
|
||||
# target_link_libraries(GD "-fsanitize=undefined") # Uncomment to auto-detect occurences of undefined behavior - also enable compiling above!
|
||||
target_link_libraries(GD "-fsanitize=null") # Uncomment to auto-detect occurences of undefined behavior - also enable compiling above!
|
||||
|
||||
@@ -105,10 +105,11 @@ describe('libGD.js object serialization', function () {
|
||||
']';
|
||||
|
||||
const element = gd.Serializer.fromJSON(json);
|
||||
// Do NOT delete element, it's a static value.
|
||||
|
||||
// Round-trips back to the same JSON (also proves the large input was
|
||||
// parsed correctly, not just that it didn't crash).
|
||||
expect(gd.Serializer.toJSON(element)).toBe(json);
|
||||
element.delete();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Generated
+478
-997
File diff suppressed because it is too large
Load Diff
@@ -34,12 +34,15 @@
|
||||
"grunt-shell": "^2.1.0",
|
||||
"grunt-string-replace": "^1.3.1",
|
||||
"jest": "^29.7.0",
|
||||
"jest-light-runner": "^0.5.1",
|
||||
"prettier": "^3.2.2",
|
||||
"shelljs": "^0.8.4",
|
||||
"webidl-tools": "github:4ian/webidl-tools#348f9c03afc9d8f278efccdd74543e265a41fd11"
|
||||
},
|
||||
"jest": {
|
||||
"testEnvironment": "node",
|
||||
"runner": "jest-light-runner",
|
||||
"testSequencer": "<rootDir>/scripts/test-sequencer.js",
|
||||
"transformIgnorePatterns": [
|
||||
"../Binaries/embuild/GDevelop.js/libGD.js"
|
||||
],
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
const Sequencer = require('@jest/test-sequencer').default;
|
||||
|
||||
// Test files that take much longer than the others (especially with the
|
||||
// 'debug-sanitizers' build variant in CI). Jest's default sequencer only
|
||||
// sorts by file size, which schedules them late: a single worker is then
|
||||
// stuck running one of them while the other workers are idle, which bounds
|
||||
// the total run time. Run them first instead.
|
||||
const slowestTestFiles = [
|
||||
'Serializer.js',
|
||||
'GDJSBooleanOperatorsCodeGenerationIntegrationTests.js',
|
||||
'GDJSDisabledCodeGenerationIntegrationTests.js',
|
||||
];
|
||||
|
||||
class SlowestFirstSequencer extends Sequencer {
|
||||
sort(tests) {
|
||||
const defaultOrder = super.sort(Array.from(tests));
|
||||
const rank = (test) => {
|
||||
const index = slowestTestFiles.findIndex((fileName) =>
|
||||
test.path.endsWith('/' + fileName)
|
||||
);
|
||||
return index === -1 ? slowestTestFiles.length : index;
|
||||
};
|
||||
// Stable sort: known slow files first (in the order listed above),
|
||||
// then the default order (largest file first).
|
||||
return defaultOrder
|
||||
.map((test, index) => ({ test, index }))
|
||||
.sort((a, b) => rank(a.test) - rank(b.test) || a.index - b.index)
|
||||
.map(({ test }) => test);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SlowestFirstSequencer;
|
||||
Reference in New Issue
Block a user