From 37bfe3d0cef97940023933b811334dda7ef6d454 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 2 Oct 2021 15:50:58 -0400 Subject: [PATCH] integrate platform sub-namespace into source code and documentation this updates function calls to functions that have been moved from the utils namepsace or the Info class to platform:: --- doc/doxygen/Doxyfile.in | 2 + doc/src/Developer.rst | 1 + doc/src/Developer_platform.rst | 140 ++++++++++++ doc/src/Developer_utils.rst | 19 +- doc/src/Howto_thermostat.rst | 2 +- doc/utils/sphinx-config/false_positives.txt | 3 + src/NETCDF/dump_netcdf.cpp | 2 +- src/NETCDF/dump_netcdf_mpiio.cpp | 2 +- src/bond.cpp | 2 +- src/info.cpp | 200 +----------------- src/info.h | 7 - src/lammps.cpp | 8 +- src/library.cpp | 6 +- src/pair.cpp | 2 +- src/platform.cpp | 8 +- src/platform.h | 10 +- src/pointers.h | 1 + src/read_data.cpp | 2 +- src/read_restart.cpp | 6 +- src/utils.cpp | 119 +---------- src/utils.h | 43 ---- tools/lammps-shell/lammps-shell.cpp | 5 +- unittest/commands/test_groups.cpp | 2 +- unittest/commands/test_kim_commands.cpp | 2 +- unittest/commands/test_lattice_region.cpp | 3 +- unittest/commands/test_reset_ids.cpp | 2 +- unittest/commands/test_simple_commands.cpp | 5 +- unittest/commands/test_variables.cpp | 2 +- unittest/cplusplus/test_error_class.cpp | 2 +- unittest/cplusplus/test_lammps_class.cpp | 2 +- unittest/formats/test_file_operations.cpp | 2 +- unittest/formats/test_molecule_file.cpp | 3 +- .../formats/test_potential_file_reader.cpp | 2 +- unittest/formats/test_text_file_reader.cpp | 2 +- unittest/testing/core.h | 3 +- unittest/utils/test_utils.cpp | 58 +---- 36 files changed, 207 insertions(+), 473 deletions(-) create mode 100644 doc/src/Developer_platform.rst diff --git a/doc/doxygen/Doxyfile.in b/doc/doxygen/Doxyfile.in index 49a271355f..d454898f4e 100644 --- a/doc/doxygen/Doxyfile.in +++ b/doc/doxygen/Doxyfile.in @@ -435,6 +435,8 @@ INPUT = @LAMMPS_SOURCE_DIR@/utils.cpp \ @LAMMPS_SOURCE_DIR@/my_pool_chunk.cpp \ @LAMMPS_SOURCE_DIR@/my_pool_chunk.h \ @LAMMPS_SOURCE_DIR@/math_eigen.h \ + @LAMMPS_SOURCE_DIR@/platform.h \ + @LAMMPS_SOURCE_DIR@/platform.cpp \ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded diff --git a/doc/src/Developer.rst b/doc/src/Developer.rst index f68007486d..fd4a44a8a0 100644 --- a/doc/src/Developer.rst +++ b/doc/src/Developer.rst @@ -18,4 +18,5 @@ of time and requests from the LAMMPS user community. Developer_plugins Developer_unittest Classes + Developer_platform Developer_utils diff --git a/doc/src/Developer_platform.rst b/doc/src/Developer_platform.rst new file mode 100644 index 0000000000..dc482cb27a --- /dev/null +++ b/doc/src/Developer_platform.rst @@ -0,0 +1,140 @@ +Platform abstraction functions +------------------------------ + +The ``platform`` sub-namespace inside the ``LAMMPS_NS`` namespace +provides a collection of wrapper and convenience functions and utilities +that perform common tasks for which platform specific code would be +required or for which a more high-level abstraction would be convenient +and reduce duplicated code. This reduces redundant implementations and +encourages consistent behavior and thus has some overlap with the +:doc:`"utils" sub-namespace `. + +Time functions +^^^^^^^^^^^^^^ + +.. doxygenfunction:: cputime + :project: progguide + +.. doxygenfunction:: walltime + :project: progguide + +Platform information functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: os_info + :project: progguide + +.. doxygenfunction:: compiler_info + :project: progguide + +.. doxygenfunction:: cxx_standard + :project: progguide + +.. doxygenfunction:: openmp_standard + :project: progguide + +.. doxygenfunction:: mpi_vendor + :project: progguide + +.. doxygenfunction:: mpi_info + :project: progguide + + +File and path functions and global constants +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenvariable:: filepathsep + :project: progguide + +.. doxygenvariable:: pathvarsep + :project: progguide + +.. doxygenfunction:: guesspath + :project: progguide + +.. doxygenfunction:: path_basename + :project: progguide + +.. doxygenfunction:: path_join + :project: progguide + +.. doxygenfunction:: file_is_readable + :project: progguide + +.. doxygenfunction:: is_console + :project: progguide + +.. doxygenfunction:: path_is_directory + :project: progguide + +.. doxygenfunction:: current_directory + :project: progguide + +.. doxygenfunction:: list_directory + :project: progguide + +.. doxygenfunction:: chdir + :project: progguide + +.. doxygenfunction:: mkdir + :project: progguide + +.. doxygenfunction:: rmdir + :project: progguide + +.. doxygenfunction:: unlink + :project: progguide + +Standard I/O function wrappers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: ftell + :project: progguide + +.. doxygenfunction:: fseek + :project: progguide + +.. doxygenfunction:: ftruncate + :project: progguide + +.. doxygenfunction:: popen + :project: progguide + +.. doxygenfunction:: pclose + :project: progguide + +Environment variable functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: putenv + :project: progguide + +.. doxygenfunction:: list_pathenv + :project: progguide + +.. doxygenfunction:: find_exe_path + :project: progguide + +Dynamically loaded object or library functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: dlopen + :project: progguide + +.. doxygenfunction:: dlclose + :project: progguide + +.. doxygenfunction:: dlsym + :project: progguide + +Compressed file I/O functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: has_zip_extension + :project: progguide + +.. doxygenfunction:: zip_read + :project: progguide + +.. doxygenfunction:: zip_write + :project: progguide diff --git a/doc/src/Developer_utils.rst b/doc/src/Developer_utils.rst index 041fce60b0..3cf059594b 100644 --- a/doc/src/Developer_utils.rst +++ b/doc/src/Developer_utils.rst @@ -7,7 +7,9 @@ a collection of convenience functions and utilities that perform common tasks that are required repeatedly throughout the LAMMPS code like reading or writing to files with error checking or translation of strings into specific types of numbers with checking for validity. This -reduces redundant implementations and encourages consistent behavior. +reduces redundant implementations and encourages consistent behavior and +thus has some overlap with the :doc:`"platform" sub-namespace +`. I/O with status check and similar functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -143,21 +145,6 @@ and parsing files or arguments. .. doxygenfunction:: is_double :project: progguide -File and path functions -^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. doxygenfunction:: guesspath - :project: progguide - -.. doxygenfunction:: path_basename - :project: progguide - -.. doxygenfunction:: path_join - :project: progguide - -.. doxygenfunction:: file_is_readable - :project: progguide - Potential file functions ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/src/Howto_thermostat.rst b/doc/src/Howto_thermostat.rst index 249af54b6e..fe53fff540 100644 --- a/doc/src/Howto_thermostat.rst +++ b/doc/src/Howto_thermostat.rst @@ -57,7 +57,7 @@ velocities. See the doc pages for the individual fixes and for the assign a temperature compute to a thermostatting fix. For example, you can apply a thermostat only to atoms in a spatial -region by using it in conjuction with :doc:`compute temp/region +region by using it in conjunction with :doc:`compute temp/region `. Or you can apply a thermostat to only the x and z components of velocity by using it with :doc:`compute temp/partial `. Of you could thermostat only diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index 5f64a4229c..76127104e0 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -1135,6 +1135,7 @@ Germann Germano gerolf Gerolf +getrusage Gershgorin getter gettimeofday @@ -1809,6 +1810,7 @@ lyon Lysogorskiy Lyulin lz +lzma Maaravi MACHDYN machdyn @@ -2762,6 +2764,7 @@ REAXFF ReaxFF reaxff rebo +recurse recursing Ree refactored diff --git a/src/NETCDF/dump_netcdf.cpp b/src/NETCDF/dump_netcdf.cpp index 5702c94499..b0bf57a41c 100644 --- a/src/NETCDF/dump_netcdf.cpp +++ b/src/NETCDF/dump_netcdf.cpp @@ -274,7 +274,7 @@ void DumpNetCDF::openfile() if (append_flag && !multifile) { // Fixme! Perform checks if dimensions and variables conform with // data structure standard. - if (not utils::file_is_readable(filecurrent)) + if (not platform::file_is_readable(filecurrent)) error->all(FLERR, "cannot append to non-existent file {}",filecurrent); if (singlefile_opened) return; diff --git a/src/NETCDF/dump_netcdf_mpiio.cpp b/src/NETCDF/dump_netcdf_mpiio.cpp index a6c3c535c9..b14cef4f68 100644 --- a/src/NETCDF/dump_netcdf_mpiio.cpp +++ b/src/NETCDF/dump_netcdf_mpiio.cpp @@ -272,7 +272,7 @@ void DumpNetCDFMPIIO::openfile() if (append_flag && !multifile) { // Fixme! Perform checks if dimensions and variables conform with // data structure standard. - if (not utils::file_is_readable(filecurrent)) + if (not platform::file_is_readable(filecurrent)) error->all(FLERR, "cannot append to non-existent file {}", filecurrent); MPI_Offset index[NC_MAX_VAR_DIMS], count[NC_MAX_VAR_DIMS]; diff --git a/src/bond.cpp b/src/bond.cpp index e636ae9bf8..fb313f0170 100644 --- a/src/bond.cpp +++ b/src/bond.cpp @@ -270,7 +270,7 @@ void Bond::write_file(int narg, char **arg) // write out a line with "DATE:" and "UNITS:" tags // - if the file already exists, print a message about appending // while printing the date and check that units are consistent. - if (utils::file_is_readable(table_file)) { + if (platform::file_is_readable(table_file)) { std::string units = utils::get_potential_units(table_file,"table"); if (!units.empty() && (units != update->unit_style)) { error->one(FLERR,"Trying to append to a table file with UNITS: {} while units are {}", diff --git a/src/info.cpp b/src/info.cpp index 137bf44b1a..340ba15b0f 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -282,7 +282,7 @@ void Info::command(int narg, char **arg) fmt::print(out,"Git info: {} / {} / {}\n", lmp->git_branch, lmp->git_descriptor,lmp->git_commit); - fmt::print(out,"\nOS information: {}\n\n",get_os_info()); + fmt::print(out,"\nOS information: {}\n\n",platform::os_info()); fmt::print(out,"sizeof(smallint): {}-bit\n" "sizeof(imageint): {}-bit\n" @@ -292,7 +292,7 @@ void Info::command(int narg, char **arg) sizeof(tagint)*8, sizeof(bigint)*8); fmt::print(out,"\nCompiler: {} with {}\nC++ standard: {}\n", - get_compiler_info(),get_openmp_info(),get_cxx_info()); + platform::compiler_info(),platform::openmp_standard(),platform::cxx_standard()); fputs("\nActive compile time flags:\n\n",out); if (has_gzip_support()) fputs("-DLAMMPS_GZIP\n",out); @@ -353,7 +353,7 @@ void Info::command(int narg, char **arg) if (flags & COMM) { int major,minor; - std::string version = get_mpi_info(major,minor); + std::string version = platform::mpi_info(major,minor); fmt::print(out,"\nCommunication information:\n" "MPI library level: MPI v{}.{}\n" @@ -1266,200 +1266,6 @@ bool Info::has_accelerator_feature(const std::string &package, return false; } -/* ---------------------------------------------------------------------- */ -#define _INFOBUF_SIZE 256 - -std::string Info::get_os_info() -{ - std::string buf; - -#if defined(_WIN32) - DWORD fullversion,majorv,minorv,buildv=0; - - fullversion = GetVersion(); - majorv = (DWORD) (LOBYTE(LOWORD(fullversion))); - minorv = (DWORD) (HIBYTE(LOWORD(fullversion))); - if (fullversion < 0x80000000) - buildv = (DWORD) (HIWORD(fullversion)); - - buf = fmt::format("Windows {}.{} ({}) on ",majorv,minorv,buildv); - - SYSTEM_INFO si; - GetSystemInfo(&si); - - switch (si.wProcessorArchitecture) { - case PROCESSOR_ARCHITECTURE_AMD64: - buf += "x86_64"; - break; - case PROCESSOR_ARCHITECTURE_ARM: - buf += "arm"; - break; - case PROCESSOR_ARCHITECTURE_IA64: - buf += "ia64"; - break; - case PROCESSOR_ARCHITECTURE_INTEL: - buf += "i386"; - break; - default: - buf += "(unknown)"; - } -#else - struct utsname ut; - uname(&ut); - - // try to get OS distribution name, if available - std::string distro = ut.sysname; - if (utils::file_is_readable("/etc/os-release")) { - try { - TextFileReader reader("/etc/os-release",""); - while (1) { - auto words = reader.next_values(0,"="); - if ((words.count() > 1) && (words.next_string() == "PRETTY_NAME")) { - distro += " " + utils::trim(words.next_string()); - break; - } - } - } catch (std::exception &e) { - ; // EOF but keyword not found - } - } - - buf = fmt::format("{} {} on {}", distro, ut.release, ut.machine); -#endif - return buf; -} - -std::string Info::get_compiler_info() -{ - std::string buf; -#if defined(__INTEL_LLVM_COMPILER) - constexpr double version = static_cast(__INTEL_LLVM_COMPILER)*0.01; - buf = fmt::format("Intel LLVM C++ {:.1f} / {}", version, __VERSION__); -#elif defined(__ibmxl__) - buf = fmt::format("IBM XL C/C++ (Clang) {}.{}.{}", - __ibmxl_version__, __ibmxl_release__, __ibmxl_modification__); -#elif defined(__clang__) - buf = fmt::format("Clang C++ {}", __VERSION__); -#elif defined(__PGI) - buf = fmt::format("PGI C++ {}.{}",__PGIC__, __PGIC_MINOR__); -#elif defined(__INTEL_COMPILER) - double version = static_cast(__INTEL_COMPILER)*0.01; - buf = fmt::format("Intel Classic C++ {:.2f}.{} / {}", version, - __INTEL_COMPILER_UPDATE, __VERSION__); -#elif defined(__MINGW64__) - buf = fmt::format("MinGW-w64 64bit {}.{} / GNU C++ {}", __MINGW64_VERSION_MAJOR, - __MINGW64_VERSION_MINOR, __VERSION__); -#elif defined(__MINGW32__) - buf = fmt::format("MinGW-w64 32bit {}.{} / GNU C++ {}", __MINGW32_MAJOR_VERSION, - __MINGW32_MINOR_VERSION, __VERSION__); -#elif defined(__GNUC__) - buf = fmt::format("GNU C++ {}", __VERSION__); -#elif defined(_MSC_VER) && (_MSC_VER > 1920) && (_MSC_VER < 2000) - constexpr int major = _MSC_VER / 100; - constexpr int minor = _MSC_VER - major *100; - buf = fmt::format("Microsoft Visual Studio 20{}, C/C++ {}.{}", major, major-5, minor); -#else - buf = "(Unknown)"; -#endif - return buf; -} - -std::string Info::get_openmp_info() -{ - -#if !defined(_OPENMP) - return "OpenMP not enabled"; -#else - -// Supported OpenMP version corresponds to the release date of the -// specifications as posted at https://www.openmp.org/specifications/ - -#if _OPENMP > 202011 - return "OpenMP newer than version 5.1"; -#elif _OPENMP == 202011 - return "OpenMP 5.1"; -#elif _OPENMP == 201811 - return "OpenMP 5.0"; -#elif _OPENMP == 201611 - return "OpenMP 5.0 preview 1"; -#elif _OPENMP == 201511 - return "OpenMP 4.5"; -#elif _OPENMP == 201307 - return "OpenMP 4.0"; -#elif _OPENMP == 201107 - return "OpenMP 3.1"; -#elif _OPENMP == 200805 - return "OpenMP 3.0"; -#elif _OPENMP == 200505 - return "OpenMP 2.5"; -#elif _OPENMP == 200203 - return "OpenMP 2.0"; -#else - return "unknown OpenMP version"; -#endif - -#endif -} - -std::string Info::get_mpi_vendor() { - #if defined(MPI_STUBS) - return "MPI STUBS"; - #elif defined(OPEN_MPI) - return "Open MPI"; - #elif defined(MPICH_NAME) - return "MPICH"; - #elif defined(I_MPI_VERSION) - return "Intel MPI"; - #elif defined(PLATFORM_MPI) - return "Platform MPI"; - #elif defined(HP_MPI) - return "HP MPI"; - #elif defined(MSMPI_VER) - return "Microsoft MPI"; - #else - return "Unknown MPI implementation"; - #endif -} - -std::string Info::get_mpi_info(int &major, int &minor) -{ - int len; -#if (defined(MPI_VERSION) && (MPI_VERSION > 2)) || defined(MPI_STUBS) - static char version[MPI_MAX_LIBRARY_VERSION_STRING]; - MPI_Get_library_version(version,&len); -#else - static char version[32]; - strcpy(version,get_mpi_vendor().c_str()); - len = strlen(version); -#endif - - MPI_Get_version(&major,&minor); - if (len > 80) { - char *ptr = strchr(version+80,'\n'); - if (ptr) *ptr = '\0'; - } - return std::string(version); -} - -std::string Info::get_cxx_info() -{ -#if __cplusplus > 202002L - return "newer than C++20"; -#elif __cplusplus == 202002L - return "C++20"; -#elif __cplusplus == 201703L - return "C++17"; -#elif __cplusplus == 201402L - return "C++14"; -#elif __cplusplus == 201103L - return "C++11"; -#elif __cplusplus == 199711L - return "C++98"; -#else - return "unknown"; -#endif -} - std::string Info::get_accelerator_info(const std::string &package) { std::string mesg(""); diff --git a/src/info.h b/src/info.h index d000b3c443..0e7bfb68f3 100644 --- a/src/info.h +++ b/src/info.h @@ -48,13 +48,6 @@ class Info : public Command { const std::string &); static bool has_gpu_device(); static std::string get_gpu_device_info(); - - static std::string get_os_info(); - static std::string get_compiler_info(); - static std::string get_openmp_info(); - static std::string get_mpi_vendor(); - static std::string get_mpi_info(int &, int &); - static std::string get_cxx_info(); static std::string get_accelerator_info(const std::string &pkg = ""); void get_memory_info(double *); diff --git a/src/lammps.cpp b/src/lammps.cpp index d9bb56d882..f6c4474cd5 100644 --- a/src/lammps.cpp +++ b/src/lammps.cpp @@ -1340,14 +1340,14 @@ void LAMMPS::print_config(FILE *fp) const char *pkg; int ncword, ncline = 0; - fmt::print(fp,"OS: {}\n\n",Info::get_os_info()); + fmt::print(fp,"OS: {}\n\n",platform::os_info()); fmt::print(fp,"Compiler: {} with {}\nC++ standard: {}\n", - Info::get_compiler_info(),Info::get_openmp_info(), - Info::get_cxx_info()); + platform::compiler_info(),platform::openmp_standard(), + platform::cxx_standard()); int major,minor; - std::string infobuf = Info::get_mpi_info(major,minor); + std::string infobuf = platform::mpi_info(major,minor); fmt::print(fp,"MPI v{}.{}: {}\n\n",major,minor,infobuf); fmt::print(fp,"Accelerator configuration:\n\n{}\n", diff --git a/src/library.cpp b/src/library.cpp index 13f480ed03..bf5ea50f58 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -4394,9 +4394,9 @@ void lammps_get_os_info(char *buffer, int buf_size) { if (buf_size <=0) return; buffer[0] = buffer[buf_size-1] = '\0'; - std::string txt = Info::get_os_info() + "\n"; - txt += Info::get_compiler_info(); - txt += " with " + Info::get_openmp_info() + "\n"; + std::string txt = platform::os_info() + "\n"; + txt += platform::compiler_info(); + txt += " with " + platform::openmp_standard() + "\n"; strncpy(buffer, txt.c_str(), buf_size-1); } diff --git a/src/pair.cpp b/src/pair.cpp index 6805166150..1039875718 100644 --- a/src/pair.cpp +++ b/src/pair.cpp @@ -1799,7 +1799,7 @@ void Pair::write_file(int narg, char **arg) // write out a line with "DATE:" and "UNITS:" tags // - if the file already exists, print a message about appending // while printing the date and check that units are consistent. - if (utils::file_is_readable(table_file)) { + if (platform::file_is_readable(table_file)) { std::string units = utils::get_potential_units(table_file,"table"); if (!units.empty() && (units != update->unit_style)) { error->one(FLERR,"Trying to append to a table file " diff --git a/src/platform.cpp b/src/platform.cpp index d457f85c98..3dd08d46ce 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -224,7 +224,7 @@ std::string platform::os_info() buf = ut.sysname; #if 0 // disable until this is integrated into LAMMPS and TextFileReader becomes available - if (utils::file_is_readable("/etc/os-release")) { + if (platform::file_is_readable("/etc/os-release")) { try { TextFileReader reader("/etc/os-release",""); while (1) { @@ -275,7 +275,6 @@ std::string platform::cxx_standard() std::string platform::compiler_info() { std::string buf = "(Unknown)"; -#if 0 // disable for now untile merged into LAMMPS and fmt:: becomes available #if defined(__INTEL_LLVM_COMPILER) double version = static_cast(__INTEL_LLVM_COMPILER)*0.01; buf = fmt::format("Intel LLVM C++ {:.1f} / {}", version, __VERSION__); @@ -304,7 +303,6 @@ std::string platform::compiler_info() buf = "Microsoft Visual Studio 20" + std::to_string(major) + ", C/C++ " + std::to_string(major-5) + "." + std::to_string(minor); #else buf = "(Unknown)"; -#endif #endif return buf; } @@ -543,9 +541,9 @@ void *platform::dlsym(void *handle, const std::string &symbol) /** On Linux the folder /proc/self/fd holds symbolic links to the actual * pathnames associated with each open file descriptor of the current process. - * On macOS the same kind of information can be obtained using ``fcntl(fd,F_GETPATH,buf)``. + * On MacOS the same kind of information can be obtained using ``fcntl(fd,F_GETPATH,buf)``. * On Windows we use ``GetFinalPathNameByHandleA()`` which is available with - * Windows Vista and later. If the buffer is to small (< 16 bytes) a null pointer is returned. + * Windows Vista and later. If the buffer is too small (< 16 bytes) a null pointer is returned. * * This function is used to provide a filename with error messages in functions * where the filename is not passed as an argument, but the FILE * pointer. */ diff --git a/src/platform.h b/src/platform.h index 5aeee1545e..1c4a659570 100644 --- a/src/platform.h +++ b/src/platform.h @@ -125,7 +125,7 @@ namespace platform { * after this call * * \param handle handle to an opened shared object - * \return 0 if succesful, non-zero of not */ + * \return 0 if successful, non-zero of not */ int dlclose(void *handle); @@ -158,7 +158,7 @@ namespace platform { /*! Try to detect pathname from FILE pointer. * - * Currently only supported on Linux and macOS, otherwise will report "(unknown)". + * Currently only supported on Linux and MacOS, otherwise will report "(unknown)". * * \param fp FILE pointer struct from STDIO library for which we want to detect the name * \param buf storage buffer for pathname. output will be truncated if not large enough @@ -193,7 +193,7 @@ namespace platform { * This provides a list of strings of the entries in the directory * without the leading path name while also skipping over ".." and ".". * - * \param path path to directory + * \param dir path to directory * \return vector with strings of all directory entries */ std::vector list_directory(const std::string &dir); @@ -203,7 +203,7 @@ namespace platform { * This function will traverse the list of directories in the PATH * environment variable and look for the executable *cmd*. If the * file exists and is executable the full path is returned as string, - * otherwise and emptry string is returned. + * otherwise and empty string is returned. * * On Windows the *cmd* string must not include and extension as * this function will automatically append the extensions ".exe", @@ -268,7 +268,7 @@ namespace platform { int fseek(FILE *fp, bigint pos); - /*! Truncate file to a given length and reposition file pointer + /*! Truncate file to a given length and re-position file pointer * * \param fp FILE pointer of the given file * \param length length to which the file is being truncated to diff --git a/src/pointers.h b/src/pointers.h index 4ae50715c1..55033aae3e 100644 --- a/src/pointers.h +++ b/src/pointers.h @@ -30,6 +30,7 @@ #include "lammps.h" // IWYU pragma: export #include "utils.h" // IWYU pragma: export #include "fmt/format.h" // IWYU pragma: export +#include "platform.h" // IWYU pragma: export namespace LAMMPS_NS { diff --git a/src/read_data.cpp b/src/read_data.cpp index 574117e93e..e9b222d6ef 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -308,7 +308,7 @@ void ReadData::command(int narg, char **arg) // check if data file is available and readable - if (!utils::file_is_readable(arg[0])) + if (!platform::file_is_readable(arg[0])) error->all(FLERR,fmt::format("Cannot open file {}: {}", arg[0], utils::getsyserror())); diff --git a/src/read_restart.cpp b/src/read_restart.cpp index bbd3bd3359..dd36175a90 100644 --- a/src/read_restart.cpp +++ b/src/read_restart.cpp @@ -540,8 +540,8 @@ std::string ReadRestart::file_search(const std::string &inpfile) { // separate inpfile into dir + filename - auto dirname = utils::path_dirname(inpfile); - auto filename = utils::path_basename(inpfile); + auto dirname = platform::path_dirname(inpfile); + auto filename = platform::path_basename(inpfile); // if filename contains "%" replace "%" with "base" @@ -574,7 +574,7 @@ std::string ReadRestart::file_search(const std::string &inpfile) if (maxnum < 0) error->one(FLERR,"Found no restart file matching pattern"); filename.replace(filename.find('*'),1,std::to_string(maxnum)); } - return utils::path_join(dirname,filename); + return platform::path_join(dirname,filename); } /* ---------------------------------------------------------------------- diff --git a/src/utils.cpp b/src/utils.cpp index 2feba5db97..55514fdd59 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -165,44 +165,6 @@ std::string utils::getsyserror() return std::string(strerror(errno)); } -/** On Linux the folder /proc/self/fd holds symbolic links to the actual - * pathnames associated with each open file descriptor of the current process. - * On MacOS the same kind of information can be obtained using ``fcntl(fd,F_GETPATH,buf)``. - * On Windows we use ``GetFinalPathNameByHandleA()`` which is available with - * Windows Vista and later. - * - * This function is used to provide a filename with error messages in functions - * where the filename is not passed as an argument, but the FILE * pointer. - */ -const char *utils::guesspath(char *buf, int len, FILE *fp) -{ - memset(buf, 0, len); - -#if defined(__linux__) - int fd = fileno(fp); - // get pathname from /proc or copy (unknown) - if (readlink(fmt::format("/proc/self/fd/{}", fd).c_str(), buf, len - 1) <= 0) - strncpy(buf, "(unknown)", len - 1); -#elif defined(__APPLE__) - int fd = fileno(fp); - char filepath[PATH_MAX]; - if (fcntl(fd, F_GETPATH, filepath) != -1) - strncpy(buf, filepath, len - 1); - else - strncpy(buf, "(unknown)", len - 1); -#elif defined(_WIN32) - char filepath[MAX_PATH]; - HANDLE h = (HANDLE) _get_osfhandle(_fileno(fp)); - if (GetFinalPathNameByHandleA(h, filepath, PATH_MAX, FILE_NAME_NORMALIZED) > 0) - strncpy(buf, filepath, len - 1); - else - strncpy(buf, "(unknown)", len - 1); -#else - strncpy(buf, "(unknown)", len - 1); -#endif - return buf; -} - // read line into buffer. if line is too long keep reading until EOL or EOF // but return only the first part with a newline at the end. @@ -256,7 +218,7 @@ void utils::sfgets(const char *srcname, int srcline, char *s, int size, FILE *fp std::string errmsg; // try to figure out the file name from the file pointer - if (!filename) filename = guesspath(buf, MAXPATHLENBUF, fp); + if (!filename) filename = platform::guesspath(fp, buf, MAXPATHLENBUF); if (feof(fp)) { errmsg = "Unexpected end of file while reading file '"; @@ -285,7 +247,7 @@ void utils::sfread(const char *srcname, int srcline, void *s, size_t size, size_ std::string errmsg; // try to figure out the file name from the file pointer - if (!filename) filename = guesspath(buf, MAXPATHLENBUF, fp); + if (!filename) filename = platform::guesspath(fp, buf, MAXPATHLENBUF); if (feof(fp)) { errmsg = "Unexpected end of file while reading file '"; @@ -920,7 +882,7 @@ size_t utils::count_words(const std::string &text, const std::string &separators size_t utils::trim_and_count_words(const std::string &text, const std::string &separators) { - return utils::count_words(utils::trim_comment(text), separators); + return utils::count_words(trim_comment(text), separators); } /* ---------------------------------------------------------------------- @@ -1065,71 +1027,6 @@ bool utils::is_id(const std::string &str) return true; } -/* ---------------------------------------------------------------------- - strip off leading part of path, return just the filename -------------------------------------------------------------------------- */ - -std::string utils::path_basename(const std::string &path) -{ -#if defined(_WIN32) - size_t start = path.find_last_of("/\\"); -#else - size_t start = path.find_last_of('/'); -#endif - - if (start == std::string::npos) { - start = 0; - } else { - start += 1; - } - - return path.substr(start); -} - -/* ---------------------------------------------------------------------- - Return only the leading part of a path, return just the directory -------------------------------------------------------------------------- */ - -std::string utils::path_dirname(const std::string &path) -{ -#if defined(_WIN32) - size_t start = path.find_last_of("/\\"); -#else - size_t start = path.find_last_of('/'); -#endif - - if (start == std::string::npos) return "."; - - return path.substr(0, start); -} - -/* ---------------------------------------------------------------------- - join two paths -------------------------------------------------------------------------- */ - -std::string utils::path_join(const std::string &a, const std::string &b) -{ -#if defined(_WIN32) - return fmt::format("{}\\{}", a, b); -#else - return fmt::format("{}/{}", a, b); -#endif -} - -/* ---------------------------------------------------------------------- - try to open file for reading -------------------------------------------------------------------------- */ - -bool utils::file_is_readable(const std::string &path) -{ - FILE *fp = fopen(path.c_str(), "r"); - if (fp) { - fclose(fp); - return true; - } - return false; -} - /* ---------------------------------------------------------------------- try to find potential file as specified by name search current directory and the LAMMPS_POTENTIALS directory if @@ -1139,9 +1036,9 @@ bool utils::file_is_readable(const std::string &path) std::string utils::get_potential_file_path(const std::string &path) { std::string filepath = path; - std::string filename = utils::path_basename(path); + std::string filename = platform::path_basename(path); - if (utils::file_is_readable(filepath)) { + if (platform::file_is_readable(filepath)) { return filepath; } else { // try the environment variable directory @@ -1154,11 +1051,11 @@ std::string utils::get_potential_file_path(const std::string &path) Tokenizer dirs(var, ":"); #endif while (dirs.has_next()) { - auto pot = utils::path_basename(filepath); + auto pot = platform::path_basename(filepath); auto dir = dirs.next(); - filepath = utils::path_join(dir, pot); + filepath = platform::path_join(dir, pot); - if (utils::file_is_readable(filepath)) { return filepath; } + if (platform::file_is_readable(filepath)) { return filepath; } } } } diff --git a/src/utils.h b/src/utils.h index 4dd4eea090..0437633ea6 100644 --- a/src/utils.h +++ b/src/utils.h @@ -417,49 +417,6 @@ namespace utils { bool is_id(const std::string &str); - /*! Try to detect pathname from FILE pointer. - * - * Currently supported on Linux, MacOS, and Windows, otherwise will report "(unknown)". - * - * \param buf storage buffer for pathname. output will be truncated if not large enough - * \param len size of storage buffer. output will be truncated to this length - 1 - * \param fp FILE pointer struct from STDIO library for which we want to detect the name - * \return pointer to the storage buffer, i.e. buf */ - - const char *guesspath(char *buf, int len, FILE *fp); - - /*! Strip off leading part of path, return just the filename - * - * \param path file path - * \return file name */ - - std::string path_basename(const std::string &path); - - /*! Return the directory part of a path. Return "." if empty - * - * \param path file path - * \return directory name */ - - std::string path_dirname(const std::string &path); - - /*! Join two pathname segments - * - * This uses the forward slash '/' character unless LAMMPS is compiled - * for Windows where it used the equivalent backward slash '\\'. - * - * \param a first path - * \param b second path - * \return combined path */ - - std::string path_join(const std::string &a, const std::string &b); - - /*! Check if file exists and is readable - * - * \param path file path - * \return true if file exists and is readable */ - - bool file_is_readable(const std::string &path); - /*! Determine full path of potential file. If file is not found in current directory, * search directories listed in LAMMPS_POTENTIALS environment variable * diff --git a/tools/lammps-shell/lammps-shell.cpp b/tools/lammps-shell/lammps-shell.cpp index 2ee62df920..76fa04d71a 100644 --- a/tools/lammps-shell/lammps-shell.cpp +++ b/tools/lammps-shell/lammps-shell.cpp @@ -6,6 +6,7 @@ // This software is distributed under the GNU General Public License. #include "library.h" +#include "platform.h" #include "utils.h" #include @@ -785,8 +786,8 @@ int main(int argc, char **argv) std::string input_file; if ((argc > 1) && (argv[1][0] != '-')) { --argc; - input_file = utils::path_basename(argv[1]); - chdir(utils::path_dirname(input_file).c_str()); + input_file = platform::path_basename(argv[1]); + chdir(platform::path_dirname(input_file).c_str()); for (int i = 1; i < argc; ++i) argv[i] = argv[i + 1]; } diff --git a/unittest/commands/test_groups.cpp b/unittest/commands/test_groups.cpp index e238e630d5..0c8a7cd83c 100644 --- a/unittest/commands/test_groups.cpp +++ b/unittest/commands/test_groups.cpp @@ -316,7 +316,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_kim_commands.cpp b/unittest/commands/test_kim_commands.cpp index a70176cc92..183d333ab4 100644 --- a/unittest/commands/test_kim_commands.cpp +++ b/unittest/commands/test_kim_commands.cpp @@ -684,7 +684,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_lattice_region.cpp b/unittest/commands/test_lattice_region.cpp index 5fbabcf173..47b69a15e0 100644 --- a/unittest/commands/test_lattice_region.cpp +++ b/unittest/commands/test_lattice_region.cpp @@ -20,7 +20,6 @@ #include "lammps.h" #include "lattice.h" #include "region.h" -#include "utils.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -631,7 +630,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_reset_ids.cpp b/unittest/commands/test_reset_ids.cpp index 221859e5c3..c67f90b341 100644 --- a/unittest/commands/test_reset_ids.cpp +++ b/unittest/commands/test_reset_ids.cpp @@ -686,7 +686,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_simple_commands.cpp b/unittest/commands/test_simple_commands.cpp index 31acf6d460..0ad47f4e96 100644 --- a/unittest/commands/test_simple_commands.cpp +++ b/unittest/commands/test_simple_commands.cpp @@ -20,7 +20,6 @@ #include "input.h" #include "output.h" #include "update.h" -#include "utils.h" #include "variable.h" #include "../testing/core.h" @@ -217,7 +216,7 @@ TEST_F(SimpleCommandsTest, Quit) TEST_FAILURE(".*ERROR: Expected integer .*", command("quit xxx");); // the following tests must be skipped with OpenMPI due to using threads - if (Info::get_mpi_vendor() == "Open MPI") GTEST_SKIP(); + if (platform::mpi_vendor() == "Open MPI") GTEST_SKIP(); ASSERT_EXIT(command("quit"), ExitedWithCode(0), ""); ASSERT_EXIT(command("quit 9"), ExitedWithCode(9), ""); } @@ -528,7 +527,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_variables.cpp b/unittest/commands/test_variables.cpp index 9d8932d0f0..4f603df5ac 100644 --- a/unittest/commands/test_variables.cpp +++ b/unittest/commands/test_variables.cpp @@ -517,7 +517,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/cplusplus/test_error_class.cpp b/unittest/cplusplus/test_error_class.cpp index 489b085b1b..f4f0d3b28b 100644 --- a/unittest/cplusplus/test_error_class.cpp +++ b/unittest/cplusplus/test_error_class.cpp @@ -128,7 +128,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/cplusplus/test_lammps_class.cpp b/unittest/cplusplus/test_lammps_class.cpp index d25b232fa7..fa7f6b30a9 100644 --- a/unittest/cplusplus/test_lammps_class.cpp +++ b/unittest/cplusplus/test_lammps_class.cpp @@ -325,7 +325,7 @@ TEST_F(LAMMPS_kokkos, InitMembers) TEST(LAMMPS_init, OpenMP) { if (!LAMMPS::is_installed_pkg("OPENMP")) GTEST_SKIP(); - if (Info::get_openmp_info() == "OpenMP not enabled") GTEST_SKIP(); + if (platform::openmp_standard() == "OpenMP not enabled") GTEST_SKIP(); FILE *fp = fopen("in.lammps_empty", "w"); fputs("\n", fp); diff --git a/unittest/formats/test_file_operations.cpp b/unittest/formats/test_file_operations.cpp index 08baed2e54..bb26dff391 100644 --- a/unittest/formats/test_file_operations.cpp +++ b/unittest/formats/test_file_operations.cpp @@ -491,7 +491,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/formats/test_molecule_file.cpp b/unittest/formats/test_molecule_file.cpp index 5a3e3ca750..2cca7a6832 100644 --- a/unittest/formats/test_molecule_file.cpp +++ b/unittest/formats/test_molecule_file.cpp @@ -17,7 +17,6 @@ #include "input.h" #include "lammps.h" #include "molecule.h" -#include "utils.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -257,7 +256,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/formats/test_potential_file_reader.cpp b/unittest/formats/test_potential_file_reader.cpp index 5f7148b7e4..7cd61d25a4 100644 --- a/unittest/formats/test_potential_file_reader.cpp +++ b/unittest/formats/test_potential_file_reader.cpp @@ -326,7 +326,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/formats/test_text_file_reader.cpp b/unittest/formats/test_text_file_reader.cpp index 4e1f608d25..f0f695ae54 100644 --- a/unittest/formats/test_text_file_reader.cpp +++ b/unittest/formats/test_text_file_reader.cpp @@ -160,7 +160,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/testing/core.h b/unittest/testing/core.h index 6867d88587..c922e96cc0 100644 --- a/unittest/testing/core.h +++ b/unittest/testing/core.h @@ -17,6 +17,7 @@ #include "info.h" #include "input.h" #include "lammps.h" +#include "platform.h" #include "variable.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -36,7 +37,7 @@ using ::testing::MatchesRegex; auto mesg = ::testing::internal::GetCapturedStdout(); \ ASSERT_THAT(mesg, MatchesRegex(errmsg)); \ } else { \ - if (Info::get_mpi_vendor() != "Open MPI") { \ + if (platform::mpi_vendor() != "Open MPI") { \ ::testing::internal::CaptureStdout(); \ ASSERT_DEATH({__VA_ARGS__}, ""); \ auto mesg = ::testing::internal::GetCapturedStdout(); \ diff --git a/unittest/utils/test_utils.cpp b/unittest/utils/test_utils.cpp index e0bc4984cc..b2c688cd59 100644 --- a/unittest/utils/test_utils.cpp +++ b/unittest/utils/test_utils.cpp @@ -13,14 +13,12 @@ #include "lmptype.h" #include "pointers.h" -#include "utils.h" #include "tokenizer.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include -#include #include #include @@ -721,54 +719,6 @@ TEST(Utils, boundsbig_case3) ASSERT_EQ(nhi, -1); } -TEST(Utils, guesspath) -{ - char buf[256]; - FILE *fp = fopen("test_guesspath.txt", "w"); -#if defined(__linux__) || defined(__APPLE__) || defined(_WIN32) - const char *path = utils::guesspath(buf, sizeof(buf), fp); - ASSERT_THAT(path, EndsWith("test_guesspath.txt")); -#else - const char *path = utils::guesspath(buf, sizeof(buf), fp); - ASSERT_THAT(path, EndsWith("(unknown)")); -#endif - fclose(fp); -} - -TEST(Utils, path_join) -{ -#if defined(_WIN32) - ASSERT_THAT(utils::path_join("c:\\parent\\folder", "filename"), - Eq("c:\\parent\\folder\\filename")); -#else - ASSERT_THAT(utils::path_join("/parent/folder", "filename"), Eq("/parent/folder/filename")); -#endif -} - -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__) @@ -792,16 +742,16 @@ TEST(Utils, potential_file) fputs("# CONTRIBUTOR: Pippo\n", fp); fclose(fp); - ASSERT_TRUE(utils::file_is_readable("ctest1.txt")); - ASSERT_TRUE(utils::file_is_readable("ctest2.txt")); - ASSERT_FALSE(utils::file_is_readable("no_such_file.txt")); + ASSERT_TRUE(platform::file_is_readable("ctest1.txt")); + ASSERT_TRUE(platform::file_is_readable("ctest2.txt")); + ASSERT_FALSE(platform::file_is_readable("no_such_file.txt")); ASSERT_THAT(utils::get_potential_file_path("ctest1.txt"), Eq("ctest1.txt")); ASSERT_THAT(utils::get_potential_file_path("no_such_file.txt"), Eq("")); const char *folder = getenv("LAMMPS_POTENTIALS"); if (folder != nullptr) { - std::string path = utils::path_join(folder, "Cu_u3.eam"); + std::string path = platform::path_join(folder, "Cu_u3.eam"); EXPECT_THAT(utils::get_potential_file_path("Cu_u3.eam"), Eq(path)); EXPECT_THAT(utils::get_potential_units(path, "EAM"), Eq("metal")); }