avoid having to use external test runner script by parsing environment variables directly
This commit is contained in:
@ -430,6 +430,86 @@ size_t utils::trim_and_count_words(const std::string & text, const std::string &
|
||||
return utils::count_words(utils::trim_comment(text), separators);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Convert string into words on whitespace while handling single and
|
||||
double quotes.
|
||||
------------------------------------------------------------------------- */
|
||||
std::vector<std::string> utils::split_words(const std::string &text)
|
||||
{
|
||||
std::vector<std::string> list;
|
||||
const char *buf = text.c_str();
|
||||
std::size_t beg = 0;
|
||||
std::size_t len = 0;
|
||||
char c = *buf;
|
||||
|
||||
while (c) {
|
||||
// leading whitespace
|
||||
if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f') {
|
||||
c = *++buf;
|
||||
++beg;
|
||||
continue;
|
||||
};
|
||||
len = 0;
|
||||
|
||||
// handle escaped/quoted text.
|
||||
quoted:
|
||||
|
||||
// handle single quote
|
||||
if (c == '\'') {
|
||||
c = *++buf;
|
||||
++len;
|
||||
while (((c != '\'') && (c != '\0'))
|
||||
|| ((c == '\\') && (buf[1] == '\''))) {
|
||||
if ((c == '\\') && (buf[1] == '\'')) {
|
||||
++buf;
|
||||
++len;
|
||||
}
|
||||
c = *++buf;
|
||||
++len;
|
||||
}
|
||||
c = *++buf;
|
||||
++len;
|
||||
|
||||
// handle double quote
|
||||
} else if (c == '"') {
|
||||
c = *++buf;
|
||||
++len;
|
||||
while (((c != '"') && (c != '\0'))
|
||||
|| ((c == '\\') && (buf[1] == '"'))) {
|
||||
if ((c == '\\') && (buf[1] == '"')) {
|
||||
++buf;
|
||||
++len;
|
||||
}
|
||||
c = *++buf;
|
||||
++len;
|
||||
}
|
||||
c = *++buf;
|
||||
++len;
|
||||
}
|
||||
|
||||
// unquoted
|
||||
while (1) {
|
||||
if ((c == '\'') || (c == '"')) goto quoted;
|
||||
// skip escaped quote
|
||||
if ((c == '\\') && ((buf[1] == '\'') || (buf[1] == '"'))) {
|
||||
++buf;
|
||||
++len;
|
||||
c = *++buf;
|
||||
++len;
|
||||
}
|
||||
if ((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n')
|
||||
|| (c == '\f') || (c == '\0')) {
|
||||
list.push_back(text.substr(beg,len));
|
||||
beg += len;
|
||||
break;
|
||||
}
|
||||
c = *++buf;
|
||||
++len;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Return whether string is a valid integer number
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
15
src/utils.h
15
src/utils.h
@ -18,6 +18,7 @@
|
||||
|
||||
#include "lmptype.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
@ -181,6 +182,20 @@ namespace LAMMPS_NS {
|
||||
*/
|
||||
size_t trim_and_count_words(const std::string & text, const std::string & separators = " \t\r\n\f");
|
||||
|
||||
/**
|
||||
* \brief Take text and split into non-whitespace words.
|
||||
*
|
||||
* This can handle single and double quotes, escaped quotes,
|
||||
* and escaped codes within quotes, but due to using an STL
|
||||
* container and STL strings is rather slow because of making
|
||||
* copies. Designed for parsing command lines and similar text
|
||||
* and not for time critical processing. Use a tokenizer for that.
|
||||
*
|
||||
* \param text string that should be split
|
||||
* \return STL vector with the words
|
||||
*/
|
||||
std::vector<std::string> split_words(const std::string &text);
|
||||
|
||||
/**
|
||||
* \brief Check if string can be converted to valid integer
|
||||
* \param text string that should be checked
|
||||
|
||||
@ -37,20 +37,15 @@ target_link_libraries(pair_style PRIVATE lammps style_tests)
|
||||
file(GLOB MOL_PAIR_TESTS LIST_DIRECTORIES false ${TEST_INPUT_FOLDER}/mol-pair-*.yaml)
|
||||
foreach(TEST ${MOL_PAIR_TESTS})
|
||||
string(REGEX REPLACE "^.*mol-pair-(.*)\.yaml" "MolPairStyle:\\1" TNAME ${TEST})
|
||||
add_test(NAME ${TNAME}
|
||||
COMMAND ${CMAKE_COMMAND} -DTEST_EXECUTABLE=$<TARGET_FILE:pair_style>
|
||||
-DTEST_INPUT=${TEST} -DTEST_NAME=${TNAME} -P ${CMAKE_CURRENT_SOURCE_DIR}/TestRunner.cmake
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
add_test(NAME ${TNAME} COMMAND pair_style ${TEST} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_tests_properties(${TNAME} PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}")
|
||||
endforeach()
|
||||
|
||||
# tests for metal-like atomic systems and related pair styles
|
||||
file(GLOB ATOMIC_PAIR_TESTS LIST_DIRECTORIES false ${TEST_INPUT_FOLDER}/atomic-pair-*.yaml)
|
||||
foreach(TEST ${ATOMIC_PAIR_TESTS})
|
||||
string(REGEX REPLACE "^.*atomic-pair-(.*)\.yaml" "AtomicPairStyle:\\1" TNAME ${TEST})
|
||||
add_test(NAME ${TNAME}
|
||||
COMMAND ${CMAKE_COMMAND} -DTEST_EXECUTABLE=$<TARGET_FILE:pair_style>
|
||||
-DTEST_INPUT=${TEST} -DTEST_NAME=${TNAME} -P ${CMAKE_CURRENT_SOURCE_DIR}/TestRunner.cmake
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
add_test(NAME ${TNAME} COMMAND pair_style ${TEST} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_tests_properties(${TNAME} PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}")
|
||||
endforeach()
|
||||
|
||||
@ -58,10 +53,7 @@ endforeach()
|
||||
file(GLOB MANYBODY_PAIR_TESTS LIST_DIRECTORIES false ${TEST_INPUT_FOLDER}/manybody-pair-*.yaml)
|
||||
foreach(TEST ${MANYBODY_PAIR_TESTS})
|
||||
string(REGEX REPLACE "^.*manybody-pair-(.*)\.yaml" "ManybodyPairStyle:\\1" TNAME ${TEST})
|
||||
add_test(NAME ${TNAME}
|
||||
COMMAND ${CMAKE_COMMAND} -DTEST_EXECUTABLE=$<TARGET_FILE:pair_style>
|
||||
-DTEST_INPUT=${TEST} -DTEST_NAME=${TNAME} -P ${CMAKE_CURRENT_SOURCE_DIR}/TestRunner.cmake
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
add_test(NAME ${TNAME} COMMAND pair_style ${TEST} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_tests_properties(${TNAME} PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}")
|
||||
endforeach()
|
||||
|
||||
@ -72,10 +64,8 @@ target_link_libraries(bond_style PRIVATE lammps style_tests)
|
||||
file(GLOB BOND_TESTS LIST_DIRECTORIES false ${TEST_INPUT_FOLDER}/bond-*.yaml)
|
||||
foreach(TEST ${BOND_TESTS})
|
||||
string(REGEX REPLACE "^.*bond-(.*)\.yaml" "BondStyle:\\1" TNAME ${TEST})
|
||||
add_test(NAME ${TNAME}
|
||||
COMMAND ${CMAKE_COMMAND} -DTEST_EXECUTABLE=$<TARGET_FILE:bond_style>
|
||||
-DTEST_INPUT=${TEST} -DTEST_NAME=${TNAME} -P ${CMAKE_CURRENT_SOURCE_DIR}/TestRunner.cmake
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
add_test(NAME ${TNAME} COMMAND bond_style ${TEST} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_tests_properties(${TNAME} PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}")
|
||||
endforeach()
|
||||
|
||||
# angle style tester
|
||||
@ -85,8 +75,6 @@ target_link_libraries(angle_style PRIVATE lammps style_tests)
|
||||
file(GLOB ANGLE_TESTS LIST_DIRECTORIES false ${TEST_INPUT_FOLDER}/angle-*.yaml)
|
||||
foreach(TEST ${ANGLE_TESTS})
|
||||
string(REGEX REPLACE "^.*angle-(.*)\.yaml" "AngleStyle:\\1" TNAME ${TEST})
|
||||
add_test(NAME ${TNAME}
|
||||
COMMAND ${CMAKE_COMMAND} -DTEST_EXECUTABLE=$<TARGET_FILE:angle_style>
|
||||
-DTEST_INPUT=${TEST} -DTEST_NAME=${TNAME} -P ${CMAKE_CURRENT_SOURCE_DIR}/TestRunner.cmake
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
add_test(NAME ${TNAME} COMMAND angle_style ${TEST} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_tests_properties(${TNAME} PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}")
|
||||
endforeach()
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
# workaround to allow passing extra arguments to test runs
|
||||
# through ctest via a TEST_ARGS environment variable
|
||||
# This can be used to, e.g. reset reference data for individual
|
||||
# tests from the build folder with "env TEST_ARGS=-u ctest -R sometest"
|
||||
execute_process(COMMAND ${TEST_EXECUTABLE} ${TEST_INPUT} $ENV{TEST_ARGS} RESULT_VARIABLE rv)
|
||||
if(NOT "${rv}" STREQUAL "0")
|
||||
message(FATAL_ERROR "Test ${TEST_NAME} failed with status ${rv}")
|
||||
endif()
|
||||
@ -17,9 +17,11 @@
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <mpi.h>
|
||||
#include <vector>
|
||||
|
||||
// common read_yaml_file function
|
||||
bool read_yaml_file(const char *infile, TestConfig &config)
|
||||
@ -76,6 +78,19 @@ int main(int argc, char **argv)
|
||||
return 2;
|
||||
}
|
||||
|
||||
// handle arguments passed via environment variable
|
||||
std::vector<std::string> env = utils::split_words(getenv("TEST_ARGS"));
|
||||
for (auto arg : env) {
|
||||
if (arg == "-u") {
|
||||
generate_yaml_file(argv[1], test_config);
|
||||
return 0;
|
||||
} else if (arg == "-s") {
|
||||
print_stats = true;
|
||||
} else if (arg == "-v") {
|
||||
verbose = true;
|
||||
}
|
||||
}
|
||||
|
||||
int iarg = 2;
|
||||
while (iarg < argc) {
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using ::testing::Eq;
|
||||
@ -48,6 +49,24 @@ TEST(Utils, count_words_with_extra_spaces)
|
||||
ASSERT_EQ(utils::count_words(" some text # comment "), 4);
|
||||
}
|
||||
|
||||
TEST(Utils, split_words_simple)
|
||||
{
|
||||
std::vector<std::string> list = utils::split_words("one two three");
|
||||
ASSERT_EQ(list.size(), 3);
|
||||
}
|
||||
|
||||
TEST(Utils, split_words_quoted)
|
||||
{
|
||||
std::vector<std::string> list = utils::split_words("one 'two' \"three\"");
|
||||
ASSERT_EQ(list.size(), 3);
|
||||
}
|
||||
|
||||
TEST(Utils, split_words_escaped)
|
||||
{
|
||||
std::vector<std::string> list = utils::split_words("1\\' '\"two\"' 3\\\"");
|
||||
ASSERT_EQ(list.size(), 3);
|
||||
}
|
||||
|
||||
TEST(Utils, valid_integer1)
|
||||
{
|
||||
ASSERT_TRUE(utils::is_integer("10"));
|
||||
|
||||
Reference in New Issue
Block a user