Skip to content

Commit 08312cb

Browse files
committed
added memoization tests
1 parent 9260a1a commit 08312cb

3 files changed

Lines changed: 189 additions & 6 deletions

File tree

.github/workflows/cross-platform-build.yml

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
- 'CMakeLists.txt'
1111
- 'auxiliary/test_cli.sh'
1212
- 'auxiliary/test_cli.ps1'
13+
- 'auxiliary/memoize_test.cpp'
1314
pull_request:
1415
branches: ["main"]
1516
paths:
@@ -19,6 +20,7 @@ on:
1920
- 'CMakeLists.txt'
2021
- 'auxiliary/test_cli.sh'
2122
- 'auxiliary/test_cli.ps1'
23+
- 'auxiliary/memoize_test.cpp'
2224
workflow_dispatch:
2325

2426
env:
@@ -372,7 +374,7 @@ jobs:
372374
run: |
373375
$bin = Get-ChildItem build\vmaware64_release -Filter "*.exe" | Select-Object -First 1 -ExpandProperty FullName
374376
Write-Host "=== vmaware64_release ==="
375-
& $bin; $true
377+
& $bin; $true | Out-Null
376378
377379
- name: Run CLI test suite (vmaware64_release)
378380
shell: pwsh
@@ -385,7 +387,7 @@ jobs:
385387
run: |
386388
$bin = Get-ChildItem build\vmaware64_debug -Filter "*.exe" | Select-Object -First 1 -ExpandProperty FullName
387389
Write-Host "=== vmaware64_debug ==="
388-
& $bin; $true
390+
& $bin; $true | Out-Null
389391
390392
- name: Run CLI test suite (vmaware64_debug)
391393
shell: pwsh
@@ -398,7 +400,7 @@ jobs:
398400
run: |
399401
$bin = Get-ChildItem build\vmaware32_release -Filter "*.exe" | Select-Object -First 1 -ExpandProperty FullName
400402
Write-Host "=== vmaware32_release ==="
401-
& $bin; $true
403+
& $bin; $true | Out-Null
402404
403405
- name: Run CLI test suite (vmaware32_release)
404406
shell: pwsh
@@ -411,14 +413,36 @@ jobs:
411413
run: |
412414
$bin = Get-ChildItem build\vmaware32_debug -Filter "*.exe" | Select-Object -First 1 -ExpandProperty FullName
413415
Write-Host "=== vmaware32_debug ==="
414-
& $bin; $true
416+
& $bin; $true | Out-Null
415417
416418
- name: Run CLI test suite (vmaware32_debug)
417419
shell: pwsh
418420
run: |
419421
$bin = Get-ChildItem build\vmaware32_debug -Filter "*.exe" | Select-Object -First 1 -ExpandProperty FullName
420422
pwsh auxiliary/test_cli.ps1 -BIN $bin -TIMEOUT_SECS 10
421423
424+
memoize-test:
425+
runs-on: ubuntu-latest
426+
timeout-minutes: 10
427+
428+
steps:
429+
- uses: actions/checkout@v4
430+
431+
- name: Install g++
432+
run: |
433+
sudo apt-get update -q
434+
sudo apt-get install -y --no-install-recommends g++
435+
436+
- name: Compile memoize test
437+
run: |
438+
g++ -std=c++20 -O2 -Wall -Wextra -Wconversion -Wdouble-promotion \
439+
-Wno-unused-parameter -Wno-unused-function -Wno-sign-conversion \
440+
-Werror -D__VMAWARE_RELEASE__ \
441+
-o memoize_test auxiliary/memoize_test.cpp
442+
443+
- name: Run memoize test
444+
run: ./memoize_test
445+
422446
platform-builds:
423447
needs: [linux, macos, windows]
424448
runs-on: ubuntu-latest
@@ -432,7 +456,7 @@ jobs:
432456
- run: echo "All CLI tests completed"
433457

434458
completed:
435-
needs: [platform-builds, cli-tests]
459+
needs: [platform-builds, cli-tests, memoize-test]
436460
runs-on: ubuntu-latest
437461
steps:
438462
- run: echo "All checks passed"

auxiliary/memoize_test.cpp

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
#include "../src/vmaware.hpp"
2+
#include <array>
3+
#include <cstdlib>
4+
#include <iostream>
5+
#include <string>
6+
7+
static int pass_count = 0;
8+
static int fail_count = 0;
9+
10+
static void check(bool condition, const char* label) {
11+
if (condition) {
12+
std::cout << " PASS " << label << "\n";
13+
++pass_count;
14+
} else {
15+
std::cerr << " FAIL " << label << "\n";
16+
++fail_count;
17+
}
18+
}
19+
20+
static bool scoreboards_equal(
21+
const std::array<VM::core::brand_entry, VM::MAX_BRANDS>& a,
22+
const std::array<VM::core::brand_entry, VM::MAX_BRANDS>& b
23+
) {
24+
for (std::size_t i = 0; i < VM::MAX_BRANDS; ++i) {
25+
if (a.at(i).name != b.at(i).name || a.at(i).score != b.at(i).score) {
26+
return false;
27+
}
28+
}
29+
return true;
30+
}
31+
32+
static bool scoreboard_non_decreasing(
33+
const std::array<VM::core::brand_entry, VM::MAX_BRANDS>& a,
34+
const std::array<VM::core::brand_entry, VM::MAX_BRANDS>& b
35+
) {
36+
for (std::size_t i = 0; i < VM::MAX_BRANDS; ++i) {
37+
if (b.at(i).score < a.at(i).score) {
38+
return false;
39+
}
40+
}
41+
return true;
42+
}
43+
44+
int main() {
45+
std::cout << "=== Mixed-flag: detected_count_num contamination ===\n";
46+
{
47+
VM::detected_count(VM::HYPERVISOR_BIT);
48+
const auto num_after_single = VM::detected_count_num.load();
49+
50+
VM::detected_count();
51+
const auto num_after_full = VM::detected_count_num.load();
52+
53+
VM::detected_count(VM::HYPERVISOR_BIT);
54+
const auto num_after_single_again = VM::detected_count_num.load();
55+
56+
check(num_after_full >= num_after_single,
57+
"detected_count_num non-decreasing: full run >= single-technique run");
58+
check(num_after_single_again == num_after_full,
59+
"detected_count_num from restricted call reflects full accumulated count (contamination)");
60+
}
61+
62+
std::cout << "\n=== Mixed-flag: brand_scoreboard contamination ===\n";
63+
{
64+
VM::brand(VM::HYPERVISOR_BIT);
65+
const auto scoreboard_after_single_brand = VM::core::brand_scoreboard;
66+
67+
VM::detected_count();
68+
const auto scoreboard_after_full_detect = VM::core::brand_scoreboard;
69+
70+
VM::brand(VM::HYPERVISOR_BIT);
71+
const auto scoreboard_after_single_brand_again = VM::core::brand_scoreboard;
72+
73+
check(scoreboard_non_decreasing(scoreboard_after_single_brand, scoreboard_after_full_detect),
74+
"brand_scoreboard scores only increase across different arg calls (monotonic)");
75+
check(scoreboards_equal(scoreboard_after_full_detect, scoreboard_after_single_brand_again),
76+
"brand_scoreboard unchanged when brand() returns from single_brand cache");
77+
}
78+
79+
std::cout << "\n=== VM::detected_count() consistency ===\n";
80+
{
81+
const auto dc1 = VM::detected_count();
82+
const auto num1 = VM::detected_count_num.load();
83+
84+
const auto dc2 = VM::detected_count();
85+
const auto num2 = VM::detected_count_num.load();
86+
87+
const auto dc3 = VM::detected_count();
88+
const auto num3 = VM::detected_count_num.load();
89+
90+
check(dc1 == dc2, "VM::detected_count() 2nd call matches 1st");
91+
check(dc1 == dc3, "VM::detected_count() 3rd call matches 1st");
92+
check(num1 == num2, "detected_count_num unchanged after 2nd VM::detected_count()");
93+
check(num1 == num3, "detected_count_num unchanged after 3rd VM::detected_count()");
94+
}
95+
96+
std::cout << "\n=== VM::brand() consistency ===\n";
97+
{
98+
const std::string brand1 = VM::brand();
99+
const auto scoreboard1 = VM::core::brand_scoreboard;
100+
101+
const std::string brand2 = VM::brand();
102+
const auto scoreboard2 = VM::core::brand_scoreboard;
103+
104+
const std::string brand3 = VM::brand();
105+
const auto scoreboard3 = VM::core::brand_scoreboard;
106+
107+
check(brand1 == brand2, "VM::brand() 2nd call matches 1st");
108+
check(brand1 == brand3, "VM::brand() 3rd call matches 1st");
109+
check(scoreboards_equal(scoreboard1, scoreboard2), "brand_scoreboard unchanged after 2nd VM::brand()");
110+
check(scoreboards_equal(scoreboard1, scoreboard3), "brand_scoreboard unchanged after 3rd VM::brand()");
111+
}
112+
113+
std::cout << "\n=== VM::detect() consistency ===\n";
114+
{
115+
const bool result1 = VM::detect();
116+
const auto num1 = VM::detected_count_num.load();
117+
118+
const bool result2 = VM::detect();
119+
const auto num2 = VM::detected_count_num.load();
120+
121+
const bool result3 = VM::detect();
122+
const auto num3 = VM::detected_count_num.load();
123+
124+
check(result1 == result2, "VM::detect() 2nd call matches 1st");
125+
check(result1 == result3, "VM::detect() 3rd call matches 1st");
126+
check(num1 == num2, "detected_count_num unchanged after 2nd VM::detect()");
127+
check(num1 == num3, "detected_count_num unchanged after 3rd VM::detect()");
128+
}
129+
130+
std::cout << "\n=== VM::percentage() consistency ===\n";
131+
{
132+
const auto pct1 = VM::percentage();
133+
const auto pct2 = VM::percentage();
134+
const auto pct3 = VM::percentage();
135+
136+
check(pct1 == pct2, "VM::percentage() 2nd call matches 1st");
137+
check(pct1 == pct3, "VM::percentage() 3rd call matches 1st");
138+
}
139+
140+
std::cout << "\n=== VM::conclusion() consistency ===\n";
141+
{
142+
const std::string conc1 = VM::conclusion();
143+
const std::string conc2 = VM::conclusion();
144+
const std::string conc3 = VM::conclusion();
145+
146+
check(conc1 == conc2, "VM::conclusion() 2nd call matches 1st");
147+
check(conc1 == conc3, "VM::conclusion() 3rd call matches 1st");
148+
}
149+
150+
std::cout << "\n-----------\n";
151+
std::cout << "PASSED: " << pass_count << "\n";
152+
if (fail_count > 0) {
153+
std::cerr << "FAILED: " << fail_count << "\n";
154+
} else {
155+
std::cout << "FAILED: " << fail_count << "\n";
156+
}
157+
158+
return (fail_count > 0) ? EXIT_FAILURE : EXIT_SUCCESS;
159+
}

src/vmaware.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14130,7 +14130,7 @@ struct VM {
1413014130
// run all the techniques, which will set the detected_count variable
1413114131
core::run_all(flags);
1413214132

14133-
return detected_count_num;
14133+
return detected_count_num.load();
1413414134
}
1413514135

1413614136

0 commit comments

Comments
 (0)