| #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()); |
| } |