testOOM.cpp (3461B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "jsapi-tests/tests.h" 6 7 #include "vm/HelperThreads.h" 8 9 BEGIN_TEST(testOOM) { 10 JS::RootedValue v(cx, JS::Int32Value(9)); 11 JS::RootedString jsstr(cx, JS::ToString(cx, v)); 12 char16_t ch; 13 if (!JS_GetStringCharAt(cx, jsstr, 0, &ch)) { 14 return false; 15 } 16 MOZ_RELEASE_ASSERT(ch == '9'); 17 return true; 18 } 19 20 virtual JSContext* createContext() override { 21 JSContext* cx = JS_NewContext(0); 22 if (!cx) { 23 return nullptr; 24 } 25 JS_SetGCParameter(cx, JSGC_MAX_BYTES, (uint32_t)-1); 26 return cx; 27 } 28 END_TEST(testOOM) 29 30 #ifdef DEBUG // js::oom functions are only available in debug builds. 31 32 const uint32_t maxAllocsPerTest = 100; 33 34 # define START_OOM_TEST(name) \ 35 testName = name; \ 36 for (bool always : {false, true}) { \ 37 const char* subTest = always ? "fail always" : "fail once"; \ 38 printf("Test %s (%s): started: ", testName, subTest); \ 39 for (oomAfter = 1; oomAfter < maxAllocsPerTest; ++oomAfter) { \ 40 js::oom::simulator.simulateFailureAfter( \ 41 js::oom::FailureSimulator::Kind::OOM, oomAfter, \ 42 js::THREAD_TYPE_MAIN, always) 43 44 # define END_OOM_TEST \ 45 if (!js::oom::HadSimulatedOOM()) { \ 46 printf("\nTest %s (%s): finished with %" PRIu64 " allocations\n", \ 47 testName, subTest, oomAfter - 1); \ 48 break; \ 49 } \ 50 } \ 51 } \ 52 js::oom::simulator.reset(); \ 53 CHECK(oomAfter != maxAllocsPerTest) 54 55 # define MARK_STAR printf("*"); 56 # define MARK_PLUS printf("+"); 57 # define MARK_DOT printf("."); 58 59 BEGIN_TEST(testNewContextOOM) { 60 uninit(); // Get rid of test harness' original JSContext. 61 62 const char* testName; 63 uint64_t oomAfter; 64 JSContext* cx; 65 START_OOM_TEST("new context"); 66 cx = JS_NewContext(8L * 1024 * 1024); 67 if (cx) { 68 MARK_PLUS; 69 JS_DestroyContext(cx); 70 } else { 71 MARK_DOT; 72 CHECK(!JSRuntime::hasLiveRuntimes()); 73 } 74 END_OOM_TEST; 75 return true; 76 } 77 END_TEST(testNewContextOOM) 78 79 BEGIN_TEST(testHelperThreadOOM) { 80 const char* testName; 81 uint64_t oomAfter; 82 START_OOM_TEST("helper thread state"); 83 84 if (js::CreateHelperThreadsState()) { 85 if (js::EnsureHelperThreadsInitialized()) { 86 MARK_STAR; 87 } else { 88 MARK_PLUS; 89 } 90 } else { 91 MARK_DOT; 92 } 93 94 // Reset the helper threads to ensure they get re-initalised in following 95 // iterations 96 js::DestroyHelperThreadsState(); 97 98 END_OOM_TEST; 99 100 return true; 101 } 102 103 bool init() override { 104 JSAPIRuntimeTest::uninit(); // Discard the just-created JSContext. 105 js::DestroyHelperThreadsState(); // The test creates this state. 106 return true; 107 } 108 void uninit() override { 109 // Leave things initialized after this test finishes. 110 js::CreateHelperThreadsState(); 111 } 112 113 END_TEST(testHelperThreadOOM) 114 115 #endif