From 22b9a53befbc58f9e05c85afbb7e0554ec115f37 Mon Sep 17 00:00:00 2001 From: John Keiser Date: Sat, 18 Apr 2020 16:37:11 -0700 Subject: [PATCH] Add SIMDJSON_FORCE_IMPLEMENTATION --- .circleci/config.yml | 3 +++ .gitignore | 1 + CMakeLists.txt | 7 ++++--- src/implementation.cpp | 9 +++++++++ tests/CMakeLists.txt | 30 ++++++++++++++++++++++++++++++ tests/checkimplementation.cpp | 23 +++++++++++++++++++++++ tools/json2json.cpp | 19 +++++++++++++------ 7 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 tests/checkimplementation.cpp diff --git a/.circleci/config.yml b/.circleci/config.yml index 81b11f294..2aa72bb50 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -85,6 +85,7 @@ commands: steps: - checkout - run: make + - run: ./json2json -h # Print out the implementation we're using on this hardware - run: make amalgamate - run: make test - run: make checkperf @@ -96,6 +97,7 @@ commands: - checkout - run: cmake $CMAKE_FLAGS $CMAKE_IMPLEMENTATION_FLAGS - run: make all + - run: tools/json2json -h # Print out the implementation we're using on this hardware - run: ctest --output-on-failure cmake_test: # this version builds, install, test and then verify from the installation @@ -105,6 +107,7 @@ commands: - checkout - run: cmake $CMAKE_FLAGS $CMAKE_IMPLEMENTATION_FLAGS -DCMAKE_INSTALL_PREFIX:PATH=destination - run: make all install + - run: tools/json2json -h # Print out the implementation we're using on this hardware - run: ctest --output-on-failure - run: echo -e '#include \nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json # we not only want cmake to build and run tests, but we want also a succesful installation from which we can build, link and run programs diff --git a/.gitignore b/.gitignore index 8ee77e6aa..a28285294 100644 --- a/.gitignore +++ b/.gitignore @@ -130,6 +130,7 @@ objs /singleheader/demo /tests/allparserscheckfile /tests/basictests +/tests/checkimplementation /tests/errortests /tests/extracting_values_example /tests/integer_tests diff --git a/CMakeLists.txt b/CMakeLists.txt index ac270c4c9..6b5826f22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,10 +122,12 @@ export_private_library(simdjson-flags) # # Create the top level simdjson library (must be done at this level to use both src/ and include/ -# directories) +# directories) and tools # add_subdirectory(include) add_subdirectory(src) +add_subdirectory(windows) +add_subdirectory(tools) # # Compile tools / tests / benchmarks @@ -135,12 +137,11 @@ enable_testing() add_library(test-data INTERFACE) target_compile_definitions(test-data INTERFACE SIMDJSON_TEST_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/jsonchecker/") target_compile_definitions(test-data INTERFACE SIMDJSON_BENCHMARK_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/jsonexamples/") +set(EXAMPLE_JSON ${CMAKE_CURRENT_SOURCE_DIR}/jsonexamples/twitter.json) -add_subdirectory(windows) add_subdirectory(dependencies) add_subdirectory(tests) add_subdirectory(examples) -add_subdirectory(tools) add_subdirectory(benchmark) # for fuzzing, read the comments in the fuzz/CMakeLists.txt file diff --git a/src/implementation.cpp b/src/implementation.cpp index c33111a3e..b2a7eb66a 100644 --- a/src/implementation.cpp +++ b/src/implementation.cpp @@ -122,6 +122,15 @@ const implementation *available_implementation_list::detect_best_supported() con } const implementation *detect_best_supported_implementation_on_first_use::set_best() const noexcept { + char *force_implementation_name = getenv("SIMDJSON_FORCE_IMPLEMENTATION"); + if (force_implementation_name) { + auto force_implementation = available_implementations[force_implementation_name]; + if (!force_implementation) { + fprintf(stderr, "SIMDJSON_FORCE_IMPLEMENTATION environment variable set to '%s', which is not a supported implementation name!\n", force_implementation_name); + abort(); + } + return active_implementation = force_implementation; + } return active_implementation = available_implementations.detect_best_supported(); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 41aebbcdd..c54722c87 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -43,6 +43,7 @@ endif() # All remaining tests link with simdjson proper link_libraries(simdjson) add_cpp_test(basictests basictests.cpp quicktests) +add_cpp_test(checkimplementation checkimplementation.cpp quicktests) add_cpp_test(errortests errortests.cpp quicktests) add_cpp_test(integer_tests integer_tests.cpp quicktests) add_cpp_test(jsoncheck jsoncheck.cpp quicktests) @@ -76,6 +77,35 @@ if (NOT MSVC) # Can't run .sh on windows endif() endif() +if (NOT MSVC) + # + # json2json tool tests + # + + add_test(NAME json2json COMMAND $ ${EXAMPLE_JSON}) + + # + # SIMDJSON_FORCE_IMPLEMENTATION tests + # + if (SIMDJSON_IMPLEMENTATION_FALLBACK) + add_test( + NAME simdjson_force_implementation_fallback + COMMAND + ${CMAKE_COMMAND} -E env + SIMDJSON_FORCE_IMPLEMENTATION=fallback + $ ${EXAMPLE_JSON} + ) + endif() + add_test( + NAME simdjson_force_implementation_error + COMMAND + ${CMAKE_COMMAND} -E env + SIMDJSON_FORCE_IMPLEMENTATION=doesnotexist + $ ${EXAMPLE_JSON} + ) + set_tests_properties(simdjson_force_implementation_error PROPERTIES WILL_FAIL TRUE) +endif() + # # Compile-only tests with simdjson flags on # diff --git a/tests/checkimplementation.cpp b/tests/checkimplementation.cpp new file mode 100644 index 000000000..86a0dcddf --- /dev/null +++ b/tests/checkimplementation.cpp @@ -0,0 +1,23 @@ +#include "simdjson.h" +#include +#include + +int main(int argc, const char *argv[]) { + std::cout << "simdjson v" << STRINGIFY(SIMDJSON_VERSION) << " is running the " << simdjson::active_implementation->name() << " implementation." << std::endl; + const char *expected_implementation = nullptr; + if (argc > 1) { + expected_implementation = argv[1]; + } else { + expected_implementation = getenv("SIMDJSON_FORCE_IMPLEMENTATION"); + if (!expected_implementation) { + std::cout << "No expected implementation argument and SIMDJSON_FORCE_IMPLEMENTATION is not set, success by default!" << std::endl; + return EXIT_SUCCESS; + } + std::cout << "No expected implementation argument, but SIMDJSON_FORCE_IMPLEMENTATION is set to " << expected_implementation << ", so we'll check for that." << std::endl; + } + if (strcmp(expected_implementation, simdjson::active_implementation->name().c_str())) { + std::cerr << "Wrong implementation! Expected " << expected_implementation << "." << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tools/json2json.cpp b/tools/json2json.cpp index 19fd466b4..a73dec5f5 100644 --- a/tools/json2json.cpp +++ b/tools/json2json.cpp @@ -4,17 +4,27 @@ #endif #include "simdjson.h" +void usage(const char *exe) { + std::cerr << exe << " v" << STRINGIFY(SIMDJSON_VERSION) << " (" << simdjson::active_implementation->name() << ")" << std::endl; + std::cerr << std::endl; + std::cerr << "Reads json in, out the result of the parsing. " << std::endl; + std::cerr << "Usage: " << exe << " " << std::endl; + std::cerr << "The -d flag dumps the raw content of the tape." << std::endl; +} int main(int argc, char *argv[]) { bool rawdump = false; #ifndef _MSC_VER int c; - while ((c = getopt(argc, argv, "d")) != -1) { + while ((c = getopt(argc, argv, "dh")) != -1) { switch (c) { case 'd': rawdump = true; break; + case 'h': + usage(argv[0]); + return EXIT_SUCCESS; default: abort(); } @@ -23,11 +33,8 @@ int main(int argc, char *argv[]) { int optind = 1; #endif if (optind >= argc) { - std::cerr << "Reads json in, out the result of the parsing. " << std::endl; - std::cerr << "Usage: " << argv[0] << " " << std::endl; - std::cerr << "The -d flag dumps the raw content of the tape." << std::endl; - - exit(1); + usage(argv[0]); + return EXIT_FAILURE; } const char *filename = argv[optind]; if (optind + 1 < argc) {