-
Notifications
You must be signed in to change notification settings - Fork 119
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
b/326457979 This set of BlackBox tests causes Cobalt to SEGFAULT by forcing Garbage Collection to execute while the JS Profiler is running. It adds a new API to CrashLog called h5vcc.crashLog.forceGarbageCollection() for the purposes of testing. Reverts [an existing revert in PR 2567](#2567). Tests are rewritten to be less CPU-intensive; expecting fewer stack frames over a longer period of time. Test-On-Device: true --------- Co-authored-by: Ahmed Elzeiny <[email protected]> (cherry picked from commit 30dacbc)
- Loading branch information
Showing
3 changed files
with
129 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
<!DOCTYPE html> | ||
|
||
<head> | ||
<title>JavaScript Profiler Test</title> | ||
<script async src="black_box_js_test_utils.js"></script> | ||
<script> | ||
|
||
const testPrimeProfiler = async () => { | ||
const profiler = new Profiler({ sampleInterval: 10 /**ms**/, maxBufferSize: 10 /**number of samples*/ }); | ||
|
||
// sleep 10 seconds | ||
await new Promise(resolve => setTimeout(resolve, 10000 /**ms**/)); | ||
|
||
// stop & check | ||
const trace = await profiler.stop(); | ||
assertTrue(trace.samples.length > 0, "expected some stack traces"); | ||
}; | ||
|
||
const testSampleBufferFullProfiler = async () => { | ||
const promise = new Promise((resolve, reject) => { | ||
const profiler = new Profiler({ maxBufferSize: 1, sampleInterval: 10 }); | ||
profiler.addEventListener("samplebufferfull", () => { | ||
profiler.stop().then(() => { resolve(true); }); | ||
}); | ||
}); | ||
const timeoutPromise = new Promise((resolve) => { | ||
setTimeout(() => { | ||
resolve(false); | ||
}, 60000); | ||
}); | ||
|
||
const result = await Promise.race([timeoutPromise, promise]); | ||
assertTrue(result, "expected sample buffer to be full"); | ||
}; | ||
|
||
/** | ||
* Creates a new Profiler and then deletes it before the sample buffer is full. | ||
* Expects the SampleBuffer to be full and the callback to be executed. | ||
*/ | ||
const testAbruptGarbageCollection = async () => { | ||
const profilerPromise = new Promise((resolve) => { | ||
window.profiler = new Profiler({ maxBufferSize: 100, sampleInterval: 10 }); | ||
delete window.profiler; // simulates the effects of GC. | ||
resolve(true); | ||
}); | ||
|
||
const survivePromise = new Promise((resolve) => { | ||
setTimeout(() => { | ||
resolve(true); | ||
}, 10000); | ||
}); | ||
|
||
// must survive for 10 seconds | ||
const result = await Promise.all([survivePromise, profilerPromise]); | ||
assertTrue(result.every(p => p), "expected cobalt to survive 10 sec if GC collects profiler"); | ||
}; | ||
|
||
window.addEventListener("load", async () => { | ||
setupFinished(); | ||
// Test Case 1: Prime Profiler | ||
if (window.location.search.includes("mode=testPrimeProfiler")) { | ||
console.log("testPrimeProfiler"); | ||
await testPrimeProfiler(); | ||
} | ||
// Test Case 2: SampleBufferFull Profiler | ||
else if (window.location.search.includes("mode=testSampleBufferFullProfiler")) { | ||
console.log("testSampleBufferFullProfiler"); | ||
await testSampleBufferFullProfiler(); | ||
} | ||
// Test Case 3: GC Profiler | ||
else if (window.location.search.includes("mode=testAbruptGarbageCollection")) { | ||
console.log("testAbruptGarbageCollection"); | ||
await testAbruptGarbageCollection(); | ||
} | ||
else { | ||
console.log("Running all tests"); | ||
await testPrimeProfiler(); | ||
await testSampleBufferFullProfiler(); | ||
await testAbruptGarbageCollection(); | ||
} | ||
console.log("DONE"); | ||
onEndTest(); | ||
}); | ||
</script> | ||
</head> | ||
|
||
<body> | ||
</body> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# Copyright 2024 The Cobalt Authors. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
"""Tests if Cobalt client page can use window.Profiler.""" | ||
|
||
from __future__ import absolute_import | ||
from __future__ import division | ||
from __future__ import print_function | ||
|
||
from cobalt.black_box_tests import black_box_tests | ||
from cobalt.black_box_tests.threaded_web_server import ThreadedWebServer | ||
|
||
|
||
class JavaScriptProfilerTest(black_box_tests.BlackBoxTestCase): | ||
"""Ensure that the client can declare a `window.Profiler` object.""" | ||
|
||
def test_javascript_profiler_prime_profiler(self): | ||
with ThreadedWebServer(binding_address=self.GetBindingAddress()) as server: | ||
modes = [ | ||
'testPrimeProfiler', | ||
'testSampleBufferFullProfiler', | ||
'testAbruptGarbageCollection', | ||
] | ||
for mode in modes: | ||
url = server.GetURL( | ||
file_name=f'testdata/javascript_profiler.html?mode={mode}') | ||
with self.CreateCobaltRunner(url=url) as runner: | ||
runner.WaitForJSTestsSetup() | ||
self.assertTrue(runner.JSTestsSucceeded(), | ||
f'JavaScript profiler failed at case mode="{mode}".') |