|
15 | 15 | #include "callTraceHashTable.h" |
16 | 16 | #include "gtest_crash_handler.h" |
17 | 17 | #include "arch.h" |
| 18 | +#include "counters.h" |
18 | 19 |
|
19 | 20 | // Test name for crash handler |
20 | 21 | static constexpr char TEST_NAME[] = "CallTraceStorageTest"; |
@@ -914,6 +915,60 @@ std::unique_ptr<CallTraceHashTable, void(*)(CallTraceHashTable*)> makeHeapCallTr |
914 | 915 | } |
915 | 916 | } // namespace |
916 | 917 |
|
| 918 | +// Test-only accessor granting access to CallTraceHashTable::seedTableForTesting, |
| 919 | +// following the CallTraceHashTable::friend CallTraceHashTableTestAccessor; |
| 920 | +// convention used elsewhere in this codebase (e.g. ObjectSamplerTestAccessor, |
| 921 | +// ProfilerTestAccessor). |
| 922 | +class CallTraceHashTableTestAccessor { |
| 923 | +public: |
| 924 | + static void seedTable(CallTraceHashTable* table, u32 slot_base, u32 capacity) { |
| 925 | + table->seedTableForTesting(slot_base, capacity); |
| 926 | + } |
| 927 | +}; |
| 928 | + |
| 929 | +// Companion to Test 4 below: the expansion-overflow guard's real integration |
| 930 | +// point inside |
| 931 | +// expandTableIfNeeded() must skip the actual table swap (not just the pure |
| 932 | +// wouldExceedSlotIdRange() helper exercised in Test 4) once a real put() |
| 933 | +// crosses the load-ratio threshold on a table seeded at the 2^32 slot-id |
| 934 | +// boundary, incrementing CALLTRACE_STORAGE_EXPANSION_SKIPPED and keeping |
| 935 | +// put() functional afterwards. The table is seeded via |
| 936 | +// CallTraceHashTableTestAccessor since reaching this boundary through real |
| 937 | +// put()-driven expansions alone would require billions of inserts. |
| 938 | +TEST_F(CallTraceStorageTest, ExpansionGuardSkipsRealExpansionNearSlotIdBoundary) { |
| 939 | + auto hash_table_ptr = makeHeapCallTraceHashTable(); |
| 940 | + ASSERT_NE(hash_table_ptr.get(), nullptr) << "Failed to allocate aligned memory for CallTraceHashTable"; |
| 941 | + CallTraceHashTable& hash_table = *hash_table_ptr; |
| 942 | + hash_table.setInstanceId(1); |
| 943 | + |
| 944 | + // Matches the "one past the boundary" case from Test 4: with this |
| 945 | + // slot_base/capacity pair, wouldExceedSlotIdRange() is true, so |
| 946 | + // expandTableIfNeeded() must take the skip branch instead of expanding. |
| 947 | + constexpr u64 kSlotIdRange = 0x100000000ull; // 2^32 |
| 948 | + u64 boundary_slot_base = kSlotIdRange - kInitialCapacity - (u64)kInitialCapacity * 2 + 1; |
| 949 | + CallTraceHashTableTestAccessor::seedTable(&hash_table, static_cast<u32>(boundary_slot_base), kInitialCapacity); |
| 950 | + |
| 951 | + long long skipped_before = Counters::getCounter(CALLTRACE_STORAGE_EXPANSION_SKIPPED); |
| 952 | + |
| 953 | + // Insert past the load-ratio threshold; every put() past it re-checks the |
| 954 | + // guard (since the table is never actually swapped), so the counter must |
| 955 | + // increase by more than one, proving the degraded state persists rather |
| 956 | + // than being a one-off fluke. |
| 957 | + const u32 TOTAL_COUNT = kExpansionThreshold + 100; |
| 958 | + for (u32 i = 0; i < TOTAL_COUNT; i++) { |
| 959 | + ASGCT_CallFrame frame; |
| 960 | + frame.bci = static_cast<int>(i); |
| 961 | + frame.method_id = reinterpret_cast<jmethodID>(static_cast<uintptr_t>(i + 1)); |
| 962 | + u64 trace_id = hash_table.put(1, &frame, false, 1); |
| 963 | + ASSERT_NE(trace_id, kOverflowTraceId) << "Unexpected overflow at i=" << i; |
| 964 | + ASSERT_NE(trace_id, CallTraceStorage::DROPPED_TRACE_ID) << "Unexpected drop at i=" << i; |
| 965 | + } |
| 966 | + |
| 967 | + long long skipped_after = Counters::getCounter(CALLTRACE_STORAGE_EXPANSION_SKIPPED); |
| 968 | + EXPECT_GT(skipped_after - skipped_before, 1) |
| 969 | + << "Expansion-overflow guard did not repeatedly skip expansion near the slot-id boundary"; |
| 970 | +} |
| 971 | + |
917 | 972 | // Test 1: forcing at least one expansion must not produce duplicate |
918 | 973 | // trace_ids, and no successful put() may return OVERFLOW_TRACE_ID or |
919 | 974 | // DROPPED_TRACE_ID. |
|
0 commit comments