Merge branch 'master' into bond_gaussian
This commit is contained in:
@ -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)
|
||||
|
||||
@ -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()
|
||||
|
||||
341
unittest/c-library/test_library_mpi.cpp
Normal file
341
unittest/c-library/test_library_mpi.cpp
Normal 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
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
228
unittest/testing/mpitesting.h
Normal file
228
unittest/testing/mpitesting.h
Normal 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);
|
||||
}
|
||||
};
|
||||
67
unittest/testing/test_mpi_main.h
Normal file
67
unittest/testing/test_mpi_main.h
Normal 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;
|
||||
}
|
||||
@ -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__":
|
||||
|
||||
@ -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__)
|
||||
|
||||
Reference in New Issue
Block a user