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

Commit a70a45d

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

File tree

5 files changed

+88
-0
lines changed

5 files changed

+88
-0
lines changed

test/CMakeLists.txt

Lines changed: 6 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")
@@ -92,6 +93,7 @@ foreach(file ${sources})
9293
set(TestEthArgs -t ${TestSuitePathFixed}/${TestCase} -- ${TESTETH_ARGS})
9394
add_test(NAME ${TestSuitePathFixed}/${TestCase} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test COMMAND testeth ${TestEthArgs})
9495
set_tests_properties(${TestSuitePathFixed}/${TestCase} PROPERTIES TIMEOUT ${timeout})
96+
list(APPEND allTests "${TestSuitePathFixed}/${TestCase} ")
9597
endif()
9698
endif()
9799
elseif (";${test_raw};" MATCHES "BOOST_AUTO_TEST_SUITE_END()")
@@ -102,10 +104,14 @@ foreach(file ${sources})
102104
endforeach(test_raw)
103105
endforeach(file)
104106

107+
#Save allTests into a variable in include file
108+
configure_file(tools/libtesteth/boostTest.h.in tools/libtesteth/boostTest.h)
109+
105110
hunter_add_package(yaml-cpp)
106111
find_package(yaml-cpp CONFIG REQUIRED)
107112

108113
add_executable(testeth ${sources})
114+
target_include_directories(testeth PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
109115
target_include_directories(testeth PRIVATE ${UTILS_INCLUDE_DIR})
110116
target_link_libraries(testeth PRIVATE ethereum ethashseal web3jsonrpc devcrypto devcore aleth-buildinfo cryptopp-static yaml-cpp::yaml-cpp binaryen::binaryen libjson-rpc-cpp::client)
111117
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 levenshtein_distance(const char* s, size_t n, const char* 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 levenshtein_distance(const char* s, size_t n, const char* 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: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
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/boostTest.h>
20+
#include <boost/algorithm/string.hpp>
1921
#include <boost/test/included/unit_test.hpp>
2022
#include <clocale>
2123
#include <cstdlib>
@@ -82,9 +84,19 @@ int main(int argc, const char* argv[])
8284
setDefaultOrCLocale();
8385

8486
// Initialize options
87+
string sMinusTArg;
8588
try
8689
{
8790
dev::test::Options::get(argc, argv);
91+
for (int i = 0; i < argc; i++) // find -t boost arg
92+
{
93+
std::string arg = std::string{argv[i]};
94+
if (arg == "-t" && i + 1 < argc)
95+
{
96+
sMinusTArg = std::string{argv[i + 1]};
97+
break;
98+
}
99+
}
88100
}
89101
catch (dev::test::InvalidOption const& e)
90102
{
@@ -137,6 +149,41 @@ int main(int argc, const char* argv[])
137149
int result = 0;
138150
auto fakeInit = [](int, char* []) -> boost::unit_test::test_suite* { return nullptr; };
139151
result = unit_test_main(fakeInit, argc, const_cast<char**>(argv));
152+
153+
// Print suggestions of a test case
154+
if (result == 200) // test suite not found
155+
{
156+
vector<string> availableTests;
157+
boost::split(availableTests, boost_all_unit_tests, boost::is_any_of(";"));
158+
159+
typedef std::pair<string, size_t> NameDistance;
160+
std::vector<NameDistance> distanceMap; // <index in availableTests, compared distance>
161+
for (auto& it : availableTests)
162+
{
163+
int dist = test::levenshtein_distance(
164+
sMinusTArg.c_str(), sMinusTArg.size(), it.c_str(), it.size());
165+
distanceMap.push_back({it, dist});
166+
}
167+
std::sort(distanceMap.begin(), distanceMap.end(),
168+
[](NameDistance const& a, NameDistance const& b) { return a.second < b.second; });
169+
std::cerr << "Did you mean: "
170+
<< "\n";
171+
std::set<string> suggestionSet;
172+
size_t hasSlash = sMinusTArg.find_first_of("/");
173+
for (size_t i = 0; i < 3; i++)
174+
{
175+
if (i < distanceMap.size())
176+
{
177+
string name = distanceMap[i].first;
178+
if (hasSlash ==
179+
string::npos) // if user input only test suite. print test suite suggestions
180+
name = name.substr(0, name.find_first_of("/"));
181+
suggestionSet.emplace(name);
182+
}
183+
}
184+
for (auto const& it : suggestionSet)
185+
std::cerr << "-t " << it << "\n";
186+
}
140187
dev::test::TestOutputHelper::get().printTestExecStats();
141188
return result;
142189
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#pragma once
2+
#include <string>
3+
4+
std::string boost_all_unit_tests = "@allTests@";

0 commit comments

Comments
 (0)