| #include "support/delta_debugging.h" | |
| #include "gtest/gtest.h" | |
| #include <algorithm> | |
| #include <string> | |
| #include <vector> | |
| using namespace wasm; | |
| TEST(DeltaDebuggingTest, EmptyInput) { | |
| std::vector<int> items; | |
| DeltaDebugger<int> dd(items); | |
| while (!dd.finished()) { | |
| dd.resolve(false); | |
| } | |
| EXPECT_TRUE(dd.working.empty()); | |
| } | |
| TEST(DeltaDebuggingTest, SingleInputEmptySetWorks) { | |
| std::vector<int> items = {42}; | |
| DeltaDebugger<int> dd(items); | |
| while (!dd.finished()) { | |
| dd.resolve(dd.test.empty()); | |
| } | |
| EXPECT_TRUE(dd.working.empty()); | |
| } | |
| TEST(DeltaDebuggingTest, SingleInputEmptySetFails) { | |
| std::vector<int> items = {42}; | |
| DeltaDebugger<int> dd(items); | |
| while (!dd.finished()) { | |
| dd.resolve(!dd.test.empty()); | |
| } | |
| std::vector<int> expected = {42}; | |
| EXPECT_EQ(dd.working, expected); | |
| } | |
| TEST(DeltaDebuggingTest, SingleItem) { | |
| std::vector<int> items = {0, 1, 2, 3, 4, 5, 6, 7}; | |
| DeltaDebugger<int> dd(items); | |
| while (!dd.finished()) { | |
| dd.resolve(std::find(dd.test.begin(), dd.test.end(), 3) != dd.test.end()); | |
| } | |
| std::vector<int> expected = {3}; | |
| EXPECT_EQ(dd.working, expected); | |
| } | |
| TEST(DeltaDebuggingTest, MultipleItemsAdjacent) { | |
| std::vector<int> items = {0, 1, 2, 3, 4, 5, 6, 7}; | |
| DeltaDebugger<int> dd(items); | |
| while (!dd.finished()) { | |
| bool has2 = std::find(dd.test.begin(), dd.test.end(), 2) != dd.test.end(); | |
| bool has3 = std::find(dd.test.begin(), dd.test.end(), 3) != dd.test.end(); | |
| dd.resolve(has2 && has3); | |
| } | |
| std::vector<int> expected = {2, 3}; | |
| EXPECT_EQ(dd.working, expected); | |
| } | |
| TEST(DeltaDebuggingTest, MultipleItemsNonAdjacent) { | |
| std::vector<int> items = {0, 1, 2, 3, 4, 5, 6, 7}; | |
| DeltaDebugger<int> dd(items); | |
| while (!dd.finished()) { | |
| bool has2 = std::find(dd.test.begin(), dd.test.end(), 2) != dd.test.end(); | |
| bool has5 = std::find(dd.test.begin(), dd.test.end(), 5) != dd.test.end(); | |
| dd.resolve(has2 && has5); | |
| } | |
| std::vector<int> expected = {2, 5}; | |
| EXPECT_EQ(dd.working, expected); | |
| } | |
| TEST(DeltaDebuggingTest, OrderMaintained) { | |
| std::vector<int> items = {3, 1, 4, 2}; | |
| DeltaDebugger<int> dd(items); | |
| while (!dd.finished()) { | |
| bool has3 = std::find(dd.test.begin(), dd.test.end(), 3) != dd.test.end(); | |
| bool has2 = std::find(dd.test.begin(), dd.test.end(), 2) != dd.test.end(); | |
| dd.resolve(has3 && has2); | |
| } | |
| std::vector<int> expected = {3, 2}; | |
| EXPECT_EQ(dd.working, expected); | |
| } | |
| TEST(DeltaDebuggingTest, DifferentTypes) { | |
| std::vector<std::string> items = {"apple", "banana", "cherry", "date"}; | |
| DeltaDebugger<std::string> dd(items); | |
| while (!dd.finished()) { | |
| bool hasBanana = | |
| std::find(dd.test.begin(), dd.test.end(), "banana") != dd.test.end(); | |
| bool hasDate = | |
| std::find(dd.test.begin(), dd.test.end(), "date") != dd.test.end(); | |
| dd.resolve(hasBanana && hasDate); | |
| } | |
| std::vector<std::string> expected = {"banana", "date"}; | |
| EXPECT_EQ(dd.working, expected); | |
| } | |
| TEST(DeltaDebuggingTest, UnconditionallyTrue) { | |
| std::vector<int> items = {0, 1, 2, 3}; | |
| DeltaDebugger<int> dd(items); | |
| while (!dd.finished()) { | |
| dd.resolve(true); | |
| } | |
| EXPECT_TRUE(dd.working.empty()); | |
| } | |
| TEST(DeltaDebuggingTest, UnconditionallyFalse) { | |
| std::vector<int> items = {0, 1, 2, 3}; | |
| DeltaDebugger<int> dd(items); | |
| while (!dd.finished()) { | |
| dd.resolve(false); | |
| } | |
| std::vector<int> expected = {0, 1, 2, 3}; | |
| EXPECT_EQ(dd.working, expected); | |
| } | |
| TEST(DeltaDebuggingTest, StructBasic) { | |
| std::vector<int> items = {0, 1, 2, 3, 4, 5, 6, 7}; | |
| DeltaDebugger<int> dd(items); | |
| while (!dd.finished()) { | |
| bool has3 = std::find(dd.test.begin(), dd.test.end(), 3) != dd.test.end(); | |
| dd.resolve(has3); | |
| } | |
| std::vector<int> expected = {3}; | |
| EXPECT_EQ(dd.working, expected); | |
| } | |
| TEST(DeltaDebuggingTest, HierarchicalExample) { | |
| std::vector<std::vector<int>> items = {{1, 10}, {2, 10}, {3, 10}}; | |
| auto testProperty = [](const std::vector<std::vector<int>>& lists) { | |
| int sum = 0; | |
| for (const auto& list : lists) { | |
| for (int x : list) { | |
| sum += x; | |
| } | |
| } | |
| return sum >= 20; | |
| }; | |
| DeltaDebugger<std::vector<int>> dd(items); | |
| while (!dd.finished()) { | |
| dd.resolve(testProperty(dd.test)); | |
| } | |
| std::vector<std::vector<int>> currentLists = dd.working; | |
| for (size_t i = 0; i < currentLists.size(); ++i) { | |
| std::vector<int> currentList = currentLists[i]; | |
| DeltaDebugger<int> subDd(currentList); | |
| while (!subDd.finished()) { | |
| std::vector<std::vector<int>> fullTestSet; | |
| for (size_t j = 0; j < currentLists.size(); ++j) { | |
| if (j == i) { | |
| fullTestSet.push_back(subDd.test); | |
| } else { | |
| fullTestSet.push_back(currentLists[j]); | |
| } | |
| } | |
| subDd.resolve(testProperty(fullTestSet)); | |
| } | |
| currentLists[i] = subDd.working; | |
| } | |
| std::vector<std::vector<int>> expected = {{10}, {10}}; | |
| EXPECT_EQ(currentLists, expected); | |
| } | |
| TEST(DeltaDebuggingTest, ResolveAfterFinished) { | |
| std::vector<int> items = {0, 1, 2, 3}; | |
| DeltaDebugger<int> dd(items); | |
| while (!dd.finished()) { | |
| dd.resolve(false); | |
| } | |
| std::vector<int> expected = {0, 1, 2, 3}; | |
| EXPECT_EQ(dd.working, expected); | |
| EXPECT_TRUE(dd.finished()); | |
| // Call resolve again | |
| dd.resolve(true); | |
| EXPECT_EQ(dd.working, expected); | |
| EXPECT_TRUE(dd.finished()); | |
| dd.resolve(false); | |
| EXPECT_EQ(dd.working, expected); | |
| EXPECT_TRUE(dd.finished()); | |
| } |