Skip to content
This repository was archived by the owner on Oct 28, 2021. It is now read-only.

Commit 6ed646c

Browse files
author
Dimitry
committed
testeth print test suite suggestions
1 parent e80e197 commit 6ed646c

File tree

5 files changed

+89
-0
lines changed

5 files changed

+89
-0
lines changed

test/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ list(REMOVE_ITEM sources ${unittest_sources})
5353
# search for test names and create ctest tests
5454
set(excludeSuites jsonrpc \"customTestSuite\" BlockQueueSuite)
5555
set(allSuites jsonrpc)
56+
set(allTests "")
5657
foreach(file ${sources})
5758
file(STRINGS ${file} test_list_raw REGEX "BOOST_.*TEST_(SUITE|CASE|SUITE_END)")
5859
set(TestSuite "DEFAULT")
@@ -81,6 +82,7 @@ foreach(file ${sources})
8182
set(TestEthArgs -t ${TestSuitePathFixed} -- ${TESTETH_ARGS})
8283
add_test(NAME ${TestSuitePathFixed} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test COMMAND testeth ${TestEthArgs})
8384
set_tests_properties(${TestSuitePathFixed} PROPERTIES TIMEOUT ${timeout})
85+
set(allTests "${allTests} \"${TestSuitePathFixed}\",\n")
8486
endif()
8587
endif()
8688
elseif(test MATCHES "^CASE .*")
@@ -92,6 +94,11 @@ foreach(file ${sources})
9294
set(TestEthArgs -t ${TestSuitePathFixed}/${TestCase} -- ${TESTETH_ARGS})
9395
add_test(NAME ${TestSuitePathFixed}/${TestCase} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test COMMAND testeth ${TestEthArgs})
9496
set_tests_properties(${TestSuitePathFixed}/${TestCase} PROPERTIES TIMEOUT ${timeout})
97+
set(allTests "${allTests} \"${TestSuitePathFixed}/${TestCase}\",\n")
98+
if (NOT ";${allSuites};" MATCHES ";${TestSuitePathFixed};")
99+
list(APPEND allSuites ${TestSuitePathFixed})
100+
set(allTests "${allTests} \"${TestSuitePathFixed}\",\n")
101+
endif()
95102
endif()
96103
endif()
97104
elseif (";${test_raw};" MATCHES "BOOST_AUTO_TEST_SUITE_END()")
@@ -102,10 +109,14 @@ foreach(file ${sources})
102109
endforeach(test_raw)
103110
endforeach(file)
104111

112+
#Save allTests into a variable in include file
113+
configure_file(tools/libtesteth/cmakeAllTests.h.in tools/libtesteth/cmakeAllTests.h)
114+
105115
hunter_add_package(yaml-cpp)
106116
find_package(yaml-cpp CONFIG REQUIRED)
107117

108118
add_executable(testeth ${sources})
119+
target_include_directories(testeth PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
109120
target_include_directories(testeth PRIVATE ${UTILS_INCLUDE_DIR})
110121
target_link_libraries(testeth PRIVATE ethereum ethashseal web3jsonrpc devcrypto devcore aleth-buildinfo cryptopp-static yaml-cpp::yaml-cpp binaryen::binaryen libjson-rpc-cpp::client)
111122
install(TARGETS testeth DESTINATION ${CMAKE_INSTALL_BINDIR})

test/tools/libtesteth/TestHelper.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,36 @@ string prepareLLLCVersionString()
637637
return "Error getting LLLC Version";
638638
}
639639

640+
// A simple C++ implementation of the Levenshtein distance algorithm to measure the amount of
641+
// difference between two strings. https://gist.github.com/TheRayTracer/2644387
642+
size_t levenshteinDistance(char const* _s, size_t _n, char const* _t, size_t _m)
643+
{
644+
++_n;
645+
++_m;
646+
size_t* d = new size_t[_n * _m];
647+
648+
memset(d, 0, sizeof(size_t) * _n * _m);
649+
for (size_t i = 1, im = 0; i < _m; ++i, ++im)
650+
{
651+
for (size_t j = 1, jn = 0; j < _n; ++j, ++jn)
652+
{
653+
if (_s[jn] == _t[im])
654+
d[(i * _n) + j] = d[((i - 1) * _n) + (j - 1)];
655+
else
656+
{
657+
d[(i * _n) + j] = min(d[(i - 1) * _n + j] + 1, /* A deletion. */
658+
min(d[i * _n + (j - 1)] + 1, /* An insertion. */
659+
d[(i - 1) * _n + (j - 1)] + 1)); /* A substitution. */
660+
}
661+
}
662+
}
663+
664+
size_t r = d[_n * _m - 1];
665+
delete[] d;
666+
return r;
667+
}
668+
669+
640670
void copyFile(fs::path const& _source, fs::path const& _destination)
641671
{
642672
fs::ifstream src(_source, ios::binary);

test/tools/libtesteth/TestHelper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ bytes importByteArray(std::string const& _str);
105105
void requireJsonFields(json_spirit::mObject const& _o, std::string const& _section,
106106
std::map<std::string, json_spirit::Value_type> const& _validationMap);
107107
void checkHexHasEvenLength(std::string const&);
108+
size_t levenshteinDistance(char const* _s, size_t _n, char const* _t, size_t _m);
108109
void copyFile(boost::filesystem::path const& _source, boost::filesystem::path const& _destination);
109110
eth::LogEntries importLog(json_spirit::mArray const& _o);
110111
std::string exportLog(eth::LogEntries const& _logs);

test/tools/libtesteth/boostTest.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
#include <test/tools/jsontests/TransactionTests.h>
1717
#include <test/tools/jsontests/vm.h>
1818
#include <test/tools/libtesteth/TestHelper.h>
19+
#include <test/tools/libtesteth/cmakeAllTests.h>
1920
#include <boost/test/included/unit_test.hpp>
21+
#include <boost/tokenizer.hpp>
2022
#include <clocale>
2123
#include <cstdlib>
2224
#include <iostream>
@@ -81,6 +83,17 @@ int main(int argc, const char* argv[])
8183
std::string const dynamicTestSuiteName = "customTestSuite";
8284
setDefaultOrCLocale();
8385

86+
string sMinusTArg;
87+
for (int i = 0; i < argc; i++) // find -t boost arg
88+
{
89+
std::string const arg = std::string{argv[i]};
90+
if (arg == "-t" && i + 1 < argc)
91+
{
92+
sMinusTArg = std::string{argv[i + 1]};
93+
break;
94+
}
95+
}
96+
8497
// Initialize options
8598
try
8699
{
@@ -137,6 +150,34 @@ int main(int argc, const char* argv[])
137150
int result = 0;
138151
auto fakeInit = [](int, char* []) -> boost::unit_test::test_suite* { return nullptr; };
139152
result = unit_test_main(fakeInit, argc, const_cast<char**>(argv));
153+
154+
// Print suggestions of a test case
155+
if (result == boost::exit_exception_failure) // test suite not found
156+
{
157+
size_t allTestsElementIndex = 0;
158+
typedef std::pair<size_t, size_t> NameDistance; // <index in availableTests, compared
159+
// distance>
160+
161+
// Use `vector` here because `set` does not work with sort
162+
std::vector<NameDistance> distanceMap; // <test name, compared distance>
163+
for (auto& it : c_allTests)
164+
{
165+
int dist =
166+
test::levenshteinDistance(sMinusTArg.c_str(), sMinusTArg.size(), it, strlen(it));
167+
distanceMap.emplace_back(allTestsElementIndex++, dist);
168+
}
169+
std::sort(distanceMap.begin(), distanceMap.end(),
170+
[](NameDistance const& _a, NameDistance const& _b) { return _a.second < _b.second; });
171+
std::cerr << "Did you mean: \n";
172+
std::set<string> suggestionSet;
173+
for (size_t i = 0; i < 3 && i < distanceMap.size(); i++)
174+
{
175+
string name = c_allTests[distanceMap[i].first];
176+
suggestionSet.emplace(name);
177+
}
178+
for (auto const& suggestion : suggestionSet)
179+
std::cerr << "-t " << suggestion << "\n";
180+
}
140181
dev::test::TestOutputHelper::get().printTestExecStats();
141182
return result;
142183
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#pragma once
2+
3+
char const* c_allTests[] =
4+
{
5+
@allTests@
6+
};

0 commit comments

Comments
 (0)