DryChem 1.0.0
A generic, compile-time C++ toolbox with no dependencies for the modern computational chemistry project.
Loading...
Searching...
No Matches
testFileParsing.hpp
Go to the documentation of this file.
1// Copyright (c) 2020-2025 Cody R. Drisko. All rights reserved.
2// Licensed under the MIT License. See the LICENSE file in the project root for more information.
3//
4// Name: testFileParsing.hpp
5// Author: crdrisko
6// Date: 12/24/2020-07:55:29
7// Description: Provides ~100% unit test coverage over all file parsing functions
8
9#ifndef DRYCHEM_COMMON_UTILITIES_LIBS_FILES_TESTS_TESTFILEPARSING_TESTFILEPARSING_HPP
10#define DRYCHEM_COMMON_UTILITIES_LIBS_FILES_TESTS_TESTFILEPARSING_TESTFILEPARSING_HPP
11
12#include <filesystem>
13#include <sstream>
14#include <string>
15#include <vector>
16
20#include <gtest/gtest.h>
21
23
24namespace fs = std::filesystem;
25
26GTEST_TEST(testFileParsing, defaultParsingOfATSVFileGivesAVectorOfStrings)
27{
29
30 fs::path fileName {"test.tsv"};
31
32 if (!fs::is_regular_file(fileName))
33 createOutputFile(fileName, '\t');
34
35 DryChem::FileParser parser {fileName};
36
37 auto rows = parser.parseDataFile(DryChem::AsRows());
38 std::vector<std::string> expectedRows {"1\t2\t3", "4\t5\t6", "7\t8\t9", "10\t11\t12"};
39
40 auto columns = parser.parseDataFile(DryChem::AsColumns());
41 std::vector<std::string> expectedColumns {"1\t4\t7\t10", "2\t5\t8\t11", "3\t6\t9\t12"};
42
43 ASSERT_EQ(rows, expectedRows);
44 ASSERT_EQ(columns, expectedColumns);
45}
46
47GTEST_TEST(testFileParsing, defaultParsingOfACSVFileGivesAVectorOfStrings)
48{
50
51 fs::path fileName {"test.csv"};
52
53 if (!fs::is_regular_file(fileName))
54 createOutputFile(fileName, ',');
55
56 DryChem::FileParser parser {fileName};
57
58 auto rows = parser.parseDataFile(DryChem::AsRows());
59 std::vector<std::string> expectedRows {"1,2,3", "4,5,6", "7,8,9", "10,11,12"};
60
61 std::string csvDelimiter {","};
62
63 auto columns = parser.parseDataFile(DryChem::AsColumns(), csvDelimiter);
64 std::vector<std::string> expectedColumns {"1,4,7,10", "2,5,8,11", "3,6,9,12"};
65
66 ASSERT_EQ(rows, expectedRows);
67 ASSERT_EQ(columns, expectedColumns);
68}
69
70GTEST_TEST(testFileParsing, weCanDefineOurOwnNonDefaultParserUsingALambdaExpression)
71{
73
74 fs::path fileName {"test.csv"};
75
76 if (!fs::is_regular_file(fileName))
77 createOutputFile(fileName, ',');
78
79 DryChem::FileParser parser {fileName};
80
81 std::vector<std::string> rows;
82
83 parser.parseDataFile(
84 [&rows](const std::string& fileContents)
85 {
86 DryChem::Tokenizer tok {fileContents, "\n"};
87 rows = tok.split();
88 });
89
90 auto expectedRows = parser.parseDataFile(DryChem::AsRows());
91
92 ASSERT_EQ(rows, expectedRows);
93}
94
95GTEST_TEST(testFileParsing, onceAFileIsParsedOnceAllSubsequentTimesUseCaches)
96{
98
99 fs::path fileName {"test.tsv"};
100
101 if (!fs::is_regular_file(fileName))
102 createOutputFile(fileName, '\t');
103
104 DryChem::FileParser parser {fileName};
105
106 // Slowest
107 auto [columns1, timeFor1stColumns]
108 = DryChem::timeAndInvoke(&DryChem::FileParser::parseDataFile<DryChem::AsColumns>, parser, DryChem::AsColumns());
109
110 // Slow
111 auto [rows1, timeFor1stRows]
112 = DryChem::timeAndInvoke(&DryChem::FileParser::parseDataFile<DryChem::AsRows>, parser, DryChem::AsRows());
113
114 // Fast
115 auto [columns2, timeFor2ndColumns]
116 = DryChem::timeAndInvoke(&DryChem::FileParser::parseDataFile<DryChem::AsColumns>, parser, DryChem::AsColumns());
117
118 // Fast
119 auto [rows2, timeFor2ndRows]
120 = DryChem::timeAndInvoke(&DryChem::FileParser::parseDataFile<DryChem::AsRows>, parser, DryChem::AsRows());
121
122 ASSERT_EQ(rows1, rows2);
123 ASSERT_EQ(columns1, columns2);
124
125 ASSERT_TRUE(timeFor1stRows >= timeFor2ndRows && timeFor1stColumns > timeFor2ndColumns);
126}
127
128GTEST_TEST(testFileParsing, returningTheFileNameAllowsUsToUtilizeTheFileSystemLibrary)
129{
131
132 fs::path fileName {"test.tsv"};
133
134 if (!fs::is_regular_file(fileName))
135 createOutputFile(fileName, '\t');
136
137 DryChem::FileParser parser {fileName};
138
139 ASSERT_TRUE(fs::is_regular_file(parser.getFileName()));
140
141 ASSERT_EQ("test", parser.getFileName().stem());
142 ASSERT_EQ(".tsv", parser.getFileName().extension());
143}
144
145GTEST_TEST(testFileParsing, tryingToParseANonExistentFileResultsInFatalException)
146{
147 std::stringstream deathRegex;
148
149 deathRegex << "Common-Utilities Fatal Error: ";
150
151#if GTEST_USES_POSIX_RE
152 deathRegex << "[(]fileParser.hpp: *[0-9]*[)]\n\t";
153#elif GTEST_USES_SIMPLE_RE
154 deathRegex << "\\(fileParser.hpp: \\d*\\)\n\t";
155#endif
156
157 deathRegex << "Could not find the requested file.\n";
158
159 ASSERT_DEATH(
160 {
161 try
162 {
163 DryChem::FileParser parser {fs::path {"SomeNonExistentFile.txt"}};
164 auto rows = parser.parseDataFile(DryChem::AsRows());
165 }
166 catch (const DryChem::FileNotFound& except)
167 {
168 except.handleErrorWithMessage();
169 }
170 },
171 deathRegex.str());
172}
173
174#endif
void createOutputFile(const fs::path &fileName)
Definition markupParsingExample.cpp:88
void createOutputFile(const fs::path &fileName, char separator)
Definition fileDetails.hpp:20
GTEST_TEST(testFileParsing, defaultParsingOfATSVFileGivesAVectorOfStrings)
Definition testFileParsing.hpp:26