Merge branch 'master' into bond_gaussian

This commit is contained in:
Axel Kohlmeyer
2020-11-25 15:50:54 -05:00
303 changed files with 39068 additions and 5556 deletions

View File

@ -1,5 +1,21 @@
include(GTest)
if(BUILD_MPI)
function(add_mpi_test)
set(MPI_TEST_NUM_PROCS 1)
set(MPI_TEST_WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
cmake_parse_arguments(MPI_TEST "" "NAME;NUM_PROCS;WORKING_DIRECTORY" "COMMAND" ${ARGN})
list(GET MPI_TEST_COMMAND 0 EXECUTABLE)
list(REMOVE_AT MPI_TEST_COMMAND 0)
set(ARGS ${MPI_TEST_COMMAND})
add_test(NAME ${MPI_TEST_NAME}
WORKING_DIRECTORY ${MPI_TEST_WORKING_DIRECTORY}
COMMAND ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} ${MPI_TEST_NUM_PROCS} ${MPIEXEC_PREFLAGS}
${EXECUTABLE} ${MPIEXEC_POSTFLAGS} ${ARGS}
)
endfunction()
endif()
add_subdirectory(utils)
add_subdirectory(formats)
add_subdirectory(commands)

View File

@ -55,3 +55,10 @@ add_executable(test_library_config test_library_config.cpp test_main.cpp)
target_link_libraries(test_library_config PRIVATE lammps GTest::GTest GTest::GMock)
target_compile_definitions(test_library_config PRIVATE ${TEST_CONFIG_DEFS})
add_test(LibraryConfig test_library_config)
if (BUILD_MPI)
add_executable(test_library_mpi test_library_mpi.cpp)
target_link_libraries(test_library_mpi PRIVATE lammps GTest::GTest GTest::GMock)
target_compile_definitions(test_library_mpi PRIVATE ${TEST_CONFIG_DEFS})
add_mpi_test(NAME LibraryMPI NUM_PROCS 4 COMMAND $<TARGET_FILE:test_library_mpi>)
endif()

View File

@ -0,0 +1,341 @@
// unit tests for checking LAMMPS configuration settings through the library interface
#define LAMMPS_LIB_MPI 1
#include "lammps.h"
#include "library.h"
#include "timer.h"
#include <string>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "../testing/test_mpi_main.h"
using ::testing::ExitedWithCode;
using ::testing::HasSubstr;
using ::testing::StartsWith;
using ::testing::StrEq;
TEST(MPI, global_box)
{
int nprocs, me;
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &me);
EXPECT_EQ(nprocs, 4);
EXPECT_GT(me, -1);
EXPECT_LT(me, 5);
double boxlo[3];
double boxhi[3];
double xy = 0.0;
double yz = 0.0;
double xz = 0.0;
int pflags[3];
int boxflag;
::testing::internal::CaptureStdout();
const char *args[] = {"LAMMPS_test", "-log", "none", "-echo", "screen", "-nocite"};
char **argv = (char **)args;
int argc = sizeof(args) / sizeof(char *);
void *lmp = lammps_open(argc, argv, MPI_COMM_WORLD, nullptr);
lammps_command(lmp, "units lj");
lammps_command(lmp, "atom_style atomic");
lammps_command(lmp, "region box block 0 2 0 2 0 2");
lammps_command(lmp, "create_box 1 box");
lammps_extract_box(lmp, boxlo, boxhi, &xy, &yz, &xz, pflags, &boxflag);
::testing::internal::GetCapturedStdout();
EXPECT_EQ(boxlo[0], 0.0);
EXPECT_EQ(boxlo[1], 0.0);
EXPECT_EQ(boxlo[2], 0.0);
EXPECT_EQ(boxhi[0], 2.0);
EXPECT_EQ(boxhi[1], 2.0);
EXPECT_EQ(boxhi[2], 2.0);
::testing::internal::CaptureStdout();
lammps_close(lmp);
::testing::internal::GetCapturedStdout();
};
TEST(MPI, sub_box)
{
int nprocs, me;
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &me);
EXPECT_EQ(nprocs, 4);
EXPECT_GT(me, -1);
EXPECT_LT(me, 5);
double boxlo[3];
double boxhi[3];
double xy = 0.0;
double yz = 0.0;
double xz = 0.0;
int pflags[3];
int boxflag;
::testing::internal::CaptureStdout();
const char *args[] = {"LAMMPS_test", "-log", "none", "-echo", "screen", "-nocite"};
char **argv = (char **)args;
int argc = sizeof(args) / sizeof(char *);
void *lmp = lammps_open(argc, argv, MPI_COMM_WORLD, nullptr);
lammps_command(lmp, "units lj");
lammps_command(lmp, "atom_style atomic");
lammps_command(lmp, "region box block 0 2 0 2 0 2");
lammps_command(lmp, "create_box 1 box");
lammps_extract_box(lmp, boxlo, boxhi, &xy, &yz, &xz, pflags, &boxflag);
::testing::internal::GetCapturedStdout();
EXPECT_EQ(boxlo[0], 0.0);
EXPECT_EQ(boxlo[1], 0.0);
EXPECT_EQ(boxlo[2], 0.0);
EXPECT_EQ(boxhi[0], 2.0);
EXPECT_EQ(boxhi[1], 2.0);
EXPECT_EQ(boxhi[2], 2.0);
double *sublo = (double *)lammps_extract_global(lmp, "sublo");
double *subhi = (double *)lammps_extract_global(lmp, "subhi");
ASSERT_NE(sublo, nullptr);
ASSERT_NE(subhi, nullptr);
EXPECT_GE(sublo[0], boxlo[0]);
EXPECT_GE(sublo[1], boxlo[1]);
EXPECT_GE(sublo[2], boxlo[2]);
EXPECT_LE(subhi[0], boxhi[0]);
EXPECT_LE(subhi[1], boxhi[1]);
EXPECT_LE(subhi[2], boxhi[2]);
::testing::internal::CaptureStdout();
lammps_command(lmp, "change_box all triclinic");
::testing::internal::GetCapturedStdout();
sublo = (double *)lammps_extract_global(lmp, "sublo_lambda");
subhi = (double *)lammps_extract_global(lmp, "subhi_lambda");
ASSERT_NE(sublo, nullptr);
ASSERT_NE(subhi, nullptr);
EXPECT_GE(sublo[0], 0.0);
EXPECT_GE(sublo[1], 0.0);
EXPECT_GE(sublo[2], 0.0);
EXPECT_LE(subhi[0], 1.0);
EXPECT_LE(subhi[1], 1.0);
EXPECT_LE(subhi[2], 1.0);
::testing::internal::CaptureStdout();
lammps_close(lmp);
::testing::internal::GetCapturedStdout();
};
TEST(MPI, split_comm)
{
int nprocs, me, color, key;
MPI_Comm newcomm;
lammps_mpi_init();
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &me);
color = me % 2;
key = me;
MPI_Comm_split(MPI_COMM_WORLD, color, key, &newcomm);
const char *args[] = {"LAMMPS_test", "-log", "none", "-echo", "screen", "-nocite"};
char **argv = (char **)args;
int argc = sizeof(args) / sizeof(char *);
void *lmp = lammps_open(argc, argv, newcomm, nullptr);
lammps_command(lmp, "units lj");
lammps_command(lmp, "atom_style atomic");
lammps_command(lmp, "region box block 0 2 0 2 0 2");
lammps_command(lmp, "create_box 1 box");
MPI_Comm_size(newcomm, &nprocs);
MPI_Comm_rank(newcomm, &me);
EXPECT_EQ(nprocs, 2);
EXPECT_GT(me, -1);
EXPECT_LT(me, 2);
EXPECT_EQ(lammps_extract_setting(lmp, "universe_size"), nprocs);
EXPECT_EQ(lammps_extract_setting(lmp, "universe_rank"), me);
EXPECT_EQ(lammps_extract_setting(lmp, "world_size"), nprocs);
EXPECT_EQ(lammps_extract_setting(lmp, "world_rank"), me);
lammps_close(lmp);
};
TEST(MPI, multi_partition)
{
FILE *fp;
int nprocs, me;
lammps_mpi_init();
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &me);
const char *args[] = {"LAMMPS_test", "-log", "none", "-partition", "2x2",
"-echo", "screen", "-nocite", "-in", "none"};
char **argv = (char **)args;
int argc = sizeof(args) / sizeof(char *);
void *lmp = lammps_open(argc, argv, MPI_COMM_WORLD, nullptr);
lammps_command(lmp, "units lj");
lammps_command(lmp, "atom_style atomic");
lammps_command(lmp, "region box block 0 2 0 2 0 2");
lammps_command(lmp, "create_box 1 box");
lammps_command(lmp, "variable partition universe 1 2");
EXPECT_EQ(lammps_extract_setting(lmp, "universe_size"), nprocs);
EXPECT_EQ(lammps_extract_setting(lmp, "universe_rank"), me);
EXPECT_EQ(lammps_extract_setting(lmp, "world_size"), nprocs / 2);
EXPECT_EQ(lammps_extract_setting(lmp, "world_rank"), me % 2);
char *part_id = (char *)lammps_extract_variable(lmp, "partition", nullptr);
if (me < 2) {
ASSERT_THAT(part_id, StrEq("1"));
} else {
ASSERT_THAT(part_id, StrEq("2"));
}
lammps_close(lmp);
};
class MPITest : public ::testing::Test {
public:
void command(const std::string &line) { lammps_command(lmp, line.c_str()); }
protected:
const char *testbinary = "LAMMPSTest";
void *lmp;
void SetUp() override
{
const char *args[] = {testbinary, "-log", "none", "-echo", "screen", "-nocite"};
char **argv = (char **)args;
int argc = sizeof(args) / sizeof(char *);
if (!verbose) ::testing::internal::CaptureStdout();
lmp = lammps_open(argc, argv, MPI_COMM_WORLD, nullptr);
InitSystem();
if (!verbose) ::testing::internal::GetCapturedStdout();
}
virtual void InitSystem()
{
command("units lj");
command("atom_style atomic");
command("atom_modify map yes");
command("lattice fcc 0.8442");
command("region box block 0 2 0 2 0 2");
command("create_box 1 box");
command("create_atoms 1 box");
command("mass 1 1.0");
command("velocity all create 3.0 87287");
command("pair_style lj/cut 2.5");
command("pair_coeff 1 1 1.0 1.0 2.5");
command("neighbor 0.3 bin");
command("neigh_modify every 20 delay 0 check no");
}
void TearDown() override
{
if (!verbose) ::testing::internal::CaptureStdout();
lammps_close(lmp);
lmp = nullptr;
if (!verbose) ::testing::internal::GetCapturedStdout();
}
};
TEST_F(MPITest, size_rank)
{
int nprocs, me;
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &me);
EXPECT_EQ(nprocs, lammps_extract_setting(lmp, "world_size"));
EXPECT_EQ(me, lammps_extract_setting(lmp, "world_rank"));
}
#if !defined(LAMMPS_BIGBIG)
TEST_F(MPITest, gather)
{
int64_t natoms = (int64_t)lammps_get_natoms(lmp);
ASSERT_EQ(natoms, 32);
int *p_nlocal = (int *)lammps_extract_global(lmp, "nlocal");
int nlocal = *p_nlocal;
EXPECT_LT(nlocal, 32);
EXPECT_EQ(nlocal, 8);
// get the entire x on all procs
double *x = new double[natoms * 3];
lammps_gather(lmp, (char *)"x", 1, 3, x);
int *tag = (int *)lammps_extract_atom(lmp, "id");
double **x_local = (double **)lammps_extract_atom(lmp, "x");
// each proc checks its local atoms
for (int i = 0; i < nlocal; i++) {
int64_t j = tag[i] - 1;
double *x_i = x_local[i];
double *x_g = &x[j * 3];
EXPECT_DOUBLE_EQ(x_g[0], x_i[0]);
EXPECT_DOUBLE_EQ(x_g[1], x_i[1]);
EXPECT_DOUBLE_EQ(x_g[2], x_i[2]);
}
delete[] x;
}
TEST_F(MPITest, scatter)
{
int *p_nlocal = (int *)lammps_extract_global(lmp, "nlocal");
int nlocal = *p_nlocal;
double *x_orig = new double[3 * nlocal];
double **x_local = (double **)lammps_extract_atom(lmp, "x");
// make copy of original local x vector
for (int i = 0; i < nlocal; i++) {
int j = 3 * i;
x_orig[j] = x_local[i][0];
x_orig[j + 1] = x_local[i][1];
x_orig[j + 2] = x_local[i][2];
}
// get the entire x on all procs
int64_t natoms = (int64_t)lammps_get_natoms(lmp);
double *x = new double[natoms * 3];
lammps_gather(lmp, (char *)"x", 1, 3, x);
// shift all coordinates by 0.001
const double delta = 0.001;
for (int64_t i = 0; i < 3 * natoms; i++)
x[i] += delta;
// update positions of all atoms
lammps_scatter(lmp, (char *)"x", 1, 3, x);
delete[] x;
x = nullptr;
// get new nlocal and x_local
p_nlocal = (int *)lammps_extract_global(lmp, "nlocal");
nlocal = *p_nlocal;
x_local = (double **)lammps_extract_atom(lmp, "x");
ASSERT_EQ(nlocal, 8);
// each proc checks its local atoms for shift
for (int i = 0; i < nlocal; i++) {
double *x_a = x_local[i];
double *x_b = &x_orig[i * 3];
EXPECT_DOUBLE_EQ(x_a[0], x_b[0] + delta);
EXPECT_DOUBLE_EQ(x_a[1], x_b[1] + delta);
EXPECT_DOUBLE_EQ(x_a[2], x_b[2] + delta);
}
delete[] x_orig;
}
#endif

View File

@ -199,6 +199,12 @@ TEST_F(LibraryProperties, setting)
lammps_command(lmp, "dimension 3");
if (!verbose) ::testing::internal::GetCapturedStdout();
EXPECT_EQ(lammps_extract_setting(lmp, "world_size"), 1);
EXPECT_EQ(lammps_extract_setting(lmp, "world_rank"), 0);
EXPECT_EQ(lammps_extract_setting(lmp, "universe_size"), 1);
EXPECT_EQ(lammps_extract_setting(lmp, "universe_rank"), 0);
EXPECT_GT(lammps_extract_setting(lmp, "nthreads"), 0);
EXPECT_EQ(lammps_extract_setting(lmp, "ntypes"), 0);
EXPECT_EQ(lammps_extract_setting(lmp, "nbondtypes"), 0);
EXPECT_EQ(lammps_extract_setting(lmp, "nangletypes"), 0);

View File

@ -1,8 +1,8 @@
find_package(YAML)
if(NOT YAML_FOUND)
message(STATUS "Skipping tests because libyaml is not found")
return()
# download and build a local copy of libyaml
include(YAML)
endif()
if(CMAKE_VERSION VERSION_LESS 3.12)

View File

@ -26,7 +26,7 @@ TEST(ErrorStats, test)
std::stringstream out;
out << stats;
ASSERT_EQ(out.str(), "Average: 5.800e-01 StdDev: 7.305e-01 MaxErr: 2.000e+00 @ item: 3.0");
ASSERT_EQ(out.str(), "Average: 5.800e-01 StdDev: 7.305e-01 MaxErr: 2.000e+00 @ item: 3");
stats.reset();
ASSERT_EQ(stats.has_data(), false);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,228 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <deque>
#include <mpi.h>
using ::testing::TestEventListener;
using ::testing::TestCase;
using ::testing::TestSuite;
using ::testing::UnitTest;
using ::testing::TestPartResult;
using ::testing::TestInfo;
class MPIPrinter : public TestEventListener {
MPI_Comm comm;
TestEventListener * default_listener;
int me;
int nprocs;
char * buffer;
size_t buffer_size;
std::deque<TestPartResult> results;
bool finalize_test;
public:
MPIPrinter(TestEventListener * default_listener) : default_listener(default_listener) {
comm = MPI_COMM_WORLD;
MPI_Comm_rank(comm, &me);
MPI_Comm_size(comm, &nprocs);
buffer_size = 1024;
buffer = new char[buffer_size];
finalize_test = false;
}
~MPIPrinter() override {
delete default_listener;
default_listener = nullptr;
delete [] buffer;
buffer = nullptr;
buffer_size = 0;
}
virtual void OnTestProgramStart(const UnitTest& unit_test) override {
if(me == 0) default_listener->OnTestProgramStart(unit_test);
}
virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration) override {
if(me == 0) default_listener->OnTestIterationStart(unit_test, iteration);
}
virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) override {
if(me == 0) default_listener->OnEnvironmentsSetUpStart(unit_test);
}
virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) override {
if(me == 0) default_listener->OnEnvironmentsSetUpEnd(unit_test);
}
virtual void OnTestSuiteStart(const TestSuite& test_suite) override {
if(me == 0) default_listener->OnTestSuiteStart(test_suite);
}
// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
virtual void OnTestCaseStart(const TestCase& test_case) override {
if(me == 0) default_listener->OnTestSuiteStart(test_case);
}
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
virtual void OnTestStart(const TestInfo& test_info) override {
// Called before a test starts.
if(me == 0) default_listener->OnTestStart(test_info);
results.clear();
finalize_test = false;
}
virtual void OnTestPartResult(const TestPartResult& test_part_result) override {
// Called after a failed assertion or a SUCCESS().
// test_part_result()
if (me == 0 && finalize_test) {
default_listener->OnTestPartResult(test_part_result);
} else {
std::stringstream proc_message;
std::istringstream msg(test_part_result.message());
std::string line;
while(std::getline(msg, line)) {
proc_message << "[Rank " << me << "] " << line << std::endl;
}
results.push_back(TestPartResult(test_part_result.type(), test_part_result.file_name(), test_part_result.line_number(), proc_message.str().c_str()));
}
}
virtual void OnTestEnd(const TestInfo& test_info) override {
// Called after a test ends.
MPI_Barrier(comm);
// other procs send their test part results
if(me != 0) {
int nresults = results.size();
MPI_Send(&nresults, 1, MPI_INT, 0, 0, comm);
for(auto& test_part_result : results) {
int type = test_part_result.type();
MPI_Send(&type, 1, MPI_INT, 0, 0, comm);
const char * str = test_part_result.file_name();
int length = 0;
if(str) length = strlen(str)+1;
MPI_Send(&length, 1, MPI_INT, 0, 0, comm);
if(str) MPI_Send(str, length, MPI_CHAR, 0, 0, comm);
int lineno = test_part_result.line_number();
MPI_Send(&lineno, 1, MPI_INT, 0, 0, comm);
str = test_part_result.message();
length = 0;
if(str) length = strlen(str)+1;
MPI_Send(&length, 1, MPI_INT, 0, 0, comm);
if(str) MPI_Send(str, length, MPI_CHAR, 0, 0, comm);
}
}
if(me == 0) {
// collect results from other procs
for(int p = 1; p < nprocs; p++) {
int nresults = 0;
MPI_Recv(&nresults, 1, MPI_INT, p, 0, comm, MPI_STATUS_IGNORE);
for(int r = 0; r < nresults; r++) {
int type;
MPI_Recv(&type, 1, MPI_INT, p, 0, comm, MPI_STATUS_IGNORE);
int length = 0;
MPI_Recv(&length, 1, MPI_INT, p, 0, comm, MPI_STATUS_IGNORE);
std::string file_name;
if (length > 0) {
if (length > buffer_size) {
delete [] buffer;
buffer = new char[length];
buffer_size = length;
}
MPI_Recv(buffer, length, MPI_CHAR, p, 0, comm, MPI_STATUS_IGNORE);
file_name = buffer;
}
int lineno;
MPI_Recv(&lineno, 1, MPI_INT, p, 0, comm, MPI_STATUS_IGNORE);
MPI_Recv(&length, 1, MPI_INT, p, 0, comm, MPI_STATUS_IGNORE);
std::string message;
if (length > 0) {
if (length > buffer_size) {
delete [] buffer;
buffer = new char[length];
buffer_size = length;
}
MPI_Recv(buffer, length, MPI_CHAR, p, 0, comm, MPI_STATUS_IGNORE);
message = std::string(buffer);
}
results.push_back(TestPartResult((TestPartResult::Type)type, file_name.c_str(), lineno, message.c_str()));
}
}
// ensure failures are reported
finalize_test = true;
// add all failures
while(!results.empty()) {
auto result = results.front();
if(result.failed()) {
ADD_FAILURE_AT(result.file_name(), result.line_number()) << result.message();
} else {
default_listener->OnTestPartResult(result);
}
results.pop_front();
}
default_listener->OnTestEnd(test_info);
}
}
virtual void OnTestSuiteEnd(const TestSuite& test_suite) override {
if(me == 0) default_listener->OnTestSuiteEnd(test_suite);
}
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
virtual void OnTestCaseEnd(const TestCase& test_case) override {
if(me == 0) default_listener->OnTestCaseEnd(test_case);
}
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) override {
if(me == 0) default_listener->OnEnvironmentsTearDownStart(unit_test);
}
virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) override {
if(me == 0) default_listener->OnEnvironmentsTearDownEnd(unit_test);
}
virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override {
if(me == 0) default_listener->OnTestIterationEnd(unit_test, iteration);
}
virtual void OnTestProgramEnd(const UnitTest& unit_test) override {
if(me == 0) default_listener->OnTestProgramEnd(unit_test);
}
};

View File

@ -0,0 +1,67 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "utils.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "mpitesting.h"
#include <iostream>
#include <mpi.h>
// whether to print verbose output (i.e. not capturing LAMMPS screen output).
bool verbose = false;
int main(int argc, char **argv)
{
MPI_Init(&argc, &argv);
::testing::InitGoogleMock(&argc, argv);
if (argc < 1) {
return 1;
}
// handle arguments passed via environment variable
if (const char *var = getenv("TEST_ARGS")) {
std::vector<std::string> env = LAMMPS_NS::utils::split_words(var);
for (auto arg : env) {
if (arg == "-v") {
verbose = true;
}
}
}
int iarg = 1;
while (iarg < argc) {
if (strcmp(argv[iarg], "-v") == 0) {
verbose = true;
++iarg;
} else {
std::cerr << "unknown option: " << argv[iarg] << "\n\n";
MPI_Finalize();
return 1;
}
}
auto & listeners = UnitTest::GetInstance()->listeners();
// Remove default listener
auto default_listener = listeners.Release(listeners.default_result_printer());
// Adds a listener to the end. googletest takes the ownership.
listeners.Append(new MPIPrinter(default_listener));
int rv = RUN_ALL_TESTS();
MPI_Finalize();
return rv;
}

View File

@ -5,6 +5,7 @@ import os, re, subprocess, unittest
os.putenv('LAMMPS_SHELL_TESTING','1')
shell_prompt_re = r"([^>]*LAMMPS Shell> ([a-z0-9_]+) *([a-z0-9_\.]+)?.*\n)+"
cmd_group_re = r"([^>]*LAMMPS Shell> ([a-z0-9_]+) +([a-z0-9]+) +([a-z0-9]+)? *([a-z/0-9]+)?.*\n)+"
#
class LammpsShell(unittest.TestCase):
@ -21,17 +22,97 @@ class LammpsShell(unittest.TestCase):
def InputRunner(self,text):
"""Test tab expansions"""
try:
[outs,errs] = self.proc.communicate(input=text, timeout=1)
except TimeoutExpired:
proc.kill()
[outs,errs] = proc.communicate()
[outs,errs] = self.proc.communicate(input=text, timeout=10)
self.timeout = 0
except subprocess.TimeoutExpired:
self.proc.kill()
[outs,errs] = self.proc.communicate()
self.timeout = 1
return outs.decode('UTF-8')
def testExpandClear(self):
def testExpandClearHistory(self):
"""Test expansion of a shell specific command"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'cle\t\n'), re.MULTILINE)
self.assertEqual(matches[0][1],"clear")
matches = re.findall(shell_prompt_re, self.InputRunner(b'clear_his\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"clear_history")
def testExpandDimension(self):
"""Test expansion of a LAMMPS command"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'dimens\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"dimension")
def testExpandPairStyle(self):
"""Test expansion of a pair style"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'pair_st\t zer\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"pair_style")
self.assertEqual(matches[0][2],"zero")
def testExpandBondStyle(self):
"""Test expansion of a bond style"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'bond_st\t zer\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"bond_style")
self.assertEqual(matches[0][2],"zero")
def testExpandAngleStyle(self):
"""Test expansion of a angle style"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'angle_st\t zer\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"angle_style")
self.assertEqual(matches[0][2],"zero")
def testExpandDihedralStyle(self):
"""Test expansion of a dihedral style"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'dihedral_st\t zer\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"dihedral_style")
self.assertEqual(matches[0][2],"zero")
def testExpandImproperStyle(self):
"""Test expansion of a improper style"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'improper_st\t zer\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"improper_style")
self.assertEqual(matches[0][2],"zero")
def testExpandComputeGroup(self):
"""Test expansion of a group-ID and a compute command"""
matches = re.findall(cmd_group_re, self.InputRunner(b'compute test al\tcentro/at\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"compute")
self.assertEqual(matches[0][2],"test")
self.assertEqual(matches[0][3],"all")
self.assertEqual(matches[0][4],"centro/atom")
def testExpandFixGroup(self):
"""Test expansion of a group-ID and a fix command"""
matches = re.findall(cmd_group_re, self.InputRunner(b'fix test al\tcontroll\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"fix")
self.assertEqual(matches[0][2],"test")
self.assertEqual(matches[0][3],"all")
self.assertEqual(matches[0][4],"controller")
def testExpandSource(self):
"""Test expansion of a shell command and a file name"""
@ -40,24 +121,30 @@ class LammpsShell(unittest.TestCase):
out.close()
matches = re.findall(shell_prompt_re, self.InputRunner(b'sour\t.tmp.in.sou\t\n'), re.MULTILINE)
os.remove('.tmp.in.source')
self.assertEqual(matches[0][1],"source")
self.assertEqual(matches[0][2],".tmp.in.source")
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"source")
self.assertEqual(matches[0][2],".tmp.in.source")
def testHistory(self):
"""Test history expansion"""
out = self.InputRunner(b'clear_history\nunits real\ndimension 2\n!!:p\n!-3:p\n!dim:p\n!uni:p\nprint !!:$\nprint !dim:1\n')
idx = 0
lines = out.splitlines()
for line in lines:
if line.startswith('LAMMPS Shell>'): break
idx += 1
self.assertEqual(lines[idx+4],"dimension 2")
self.assertEqual(lines[idx+6],"units real")
self.assertEqual(lines[idx+8],"dimension 2")
self.assertEqual(lines[idx+10],"units real")
self.assertEqual(lines[idx+12],"real")
self.assertEqual(lines[idx+14],"2")
if self.timeout:
self.fail("Timeout")
else:
lines = out.splitlines()
for line in lines:
if line.startswith('LAMMPS Shell>'): break
idx += 1
self.assertEqual(lines[idx+4],"dimension 2")
self.assertEqual(lines[idx+6],"units real")
self.assertEqual(lines[idx+8],"dimension 2")
self.assertEqual(lines[idx+10],"units real")
self.assertEqual(lines[idx+12],"real")
self.assertEqual(lines[idx+14],"2")
###########################
if __name__ == "__main__":

View File

@ -525,11 +525,26 @@ TEST(Utils, path_basename)
{
#if defined(_WIN32)
ASSERT_THAT(utils::path_basename("c:\\parent\\folder\\filename"), Eq("filename"));
ASSERT_THAT(utils::path_basename("folder\\"), Eq(""));
ASSERT_THAT(utils::path_basename("c:/parent/folder/filename"), Eq("filename"));
#else
ASSERT_THAT(utils::path_basename("/parent/folder/filename"), Eq("filename"));
ASSERT_THAT(utils::path_basename("/parent/folder/"), Eq(""));
#endif
}
TEST(Utils, path_dirname)
{
#if defined(_WIN32)
ASSERT_THAT(utils::path_dirname("c:/parent/folder/filename"), Eq("c:/parent/folder"));
ASSERT_THAT(utils::path_dirname("c:\\parent\\folder\\filename"), Eq("c:\\parent\\folder"));
ASSERT_THAT(utils::path_dirname("c:filename"), Eq("."));
#else
ASSERT_THAT(utils::path_dirname("/parent/folder/filename"), Eq("/parent/folder"));
#endif
ASSERT_THAT(utils::path_dirname("filename"), Eq("."));
}
TEST(Utils, getsyserror)
{
#if defined(__linux__)