Introduce SimulatorBuilder
[gromacs.git] / src / gromacs / topology / tests / symtab.cpp
bloba65ba0c4060ad65d160887cef727017c7c0918f1
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2019, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
35 /*! \internal \file
36 * \brief
37 * Tests for legacy symbol table
39 * \author Paul Bauer <paul.bauer.q@gmail.com>
41 #include "gmxpre.h"
43 #include "gromacs/topology/symtab.h"
45 #include <memory>
47 #include <gtest/gtest.h>
49 #include "gromacs/utility/strconvert.h"
50 #include "gromacs/utility/stringutil.h"
52 #include "testutils/refdata.h"
54 namespace gmx
57 namespace test
60 namespace
63 class SymtabTest : public ::testing::Test
65 public:
66 SymtabTest()
68 open_symtab(&symtab_);
70 ~SymtabTest() override
72 done_symtab(&symtab_);
73 EXPECT_EQ(symtab_.nr, 0);
74 EXPECT_EQ(symtab_.symbuf, nullptr);
77 //! Get handle to symbol table.
78 t_symtab *symtab() { return &symtab_; }
79 //! Dump symtab. Similar to pr_symtab function.
80 void dumpSymtab();
82 private:
83 //! Get reference checker using lazy initialization
84 TestReferenceChecker *checker()
86 if (!checker_)
88 checker_ = std::make_unique<TestReferenceChecker>(data_.rootChecker());
90 return checker_.get();
92 //! The symbol table being tested.
93 t_symtab symtab_;
94 //! Handler for reference data.
95 TestReferenceData data_;
96 //! Handler for checking reference data.
97 std::unique_ptr<TestReferenceChecker> checker_;
100 void SymtabTest::dumpSymtab()
102 int nr = symtab_.nr;
103 t_symbuf *symbuf = symtab_.symbuf;
104 std::vector<std::string> symtabDump;
105 int pos = 0;
106 while (symbuf != nullptr)
108 int i;
109 for (i = 0; (i < symbuf->bufsize) && (i < nr); i++)
111 symtabDump.emplace_back(formatString("Symtab[%d]=\"%s\"", pos++, symbuf->buf[i]));
113 nr -= i;
114 symbuf = symbuf->next;
116 checker()->checkSequence(symtabDump.begin(), symtabDump.end(), "Complete dump of SymbolTable");
119 /*! \brief
120 * Helper that compares an input to a handle obtained from symtab lookup.
122 * \param[in] symtab Symbol table that contains the entries.
123 * \param[in] symbol The entry obtained from placing a string in the symbol table.
124 * \param[in] index Index into symtab corresponding to an entry.
125 * \returns Whether to \p symbol and the entry returned by \p index are the same pointer.
127 bool entriesAreEqual(t_symtab *symtab, char **symbol, int index)
129 return symbol == get_symtab_handle(symtab, index);
132 /*! \brief
133 * Helper function to check internal consistency of symtab lookup.
135 * Checks that placing an entry resulted in valid symbol table, and that
136 * the index obtained from a call to lookup_symtab returns the correct entry.
138 * \param[in] symtab Symbol table that contains the entries.
139 * \param[in] symbol The entry obtained from placing a string in the symbol table.
141 void compareSymtabLookupAndHandle(t_symtab *symtab, char **symbol)
143 ASSERT_NE(symtab->symbuf, nullptr);
144 auto index = lookup_symtab(symtab, symbol);
145 EXPECT_TRUE(entriesAreEqual(symtab, symbol, index));
147 /*! \brief
148 * Check that symbols obtained from symtab compare correctly.
150 * Helper function to find out if two entries obtained by a symtab lookup
151 * are equivalent or not, according to testing criteria.
153 * \param[in] symtab Symbol table that contains the entries.
154 * \param[in] firstSymbol Handle into symtab obtained from placing string in symtab.
155 * \param[in] otherSymbol Other handle from obtained from separate string deposit.
156 * \param[in] expectedOutcome If the handles should result in equal entries or not.
158 void compareDifferentHandles(t_symtab *symtab,
159 char **firstSymbol,
160 char **otherSymbol,
161 bool expectedOutcome)
163 ASSERT_NE(symtab->symbuf, nullptr);
164 auto firstIndex = lookup_symtab(symtab, firstSymbol);
165 auto otherIndex = lookup_symtab(symtab, otherSymbol);
166 EXPECT_EQ(expectedOutcome, entriesAreEqual(symtab, firstSymbol, otherIndex));
167 EXPECT_EQ(expectedOutcome, entriesAreEqual(symtab, otherSymbol, firstIndex));
170 TEST_F(SymtabTest, EmptyOnOpen)
172 ASSERT_EQ(0, symtab()->nr);
173 ASSERT_EQ(nullptr, symtab()->symbuf);
176 TEST_F(SymtabTest, AddSingleEntry)
178 auto fooSymbol = put_symtab(symtab(), "Foo");
179 ASSERT_EQ(1, symtab()->nr);
180 compareSymtabLookupAndHandle(symtab(), fooSymbol);
181 EXPECT_STREQ("Foo", *fooSymbol);
184 TEST_F(SymtabTest, AddTwoDistinctEntries)
186 auto fooSymbol = put_symtab(symtab(), "Foo");
187 auto barSymbol = put_symtab(symtab(), "Bar");
188 ASSERT_EQ(2, symtab()->nr);
190 compareSymtabLookupAndHandle(symtab(), fooSymbol);
191 compareSymtabLookupAndHandle(symtab(), barSymbol);
193 EXPECT_NE(fooSymbol, barSymbol);
194 compareDifferentHandles(symtab(), fooSymbol, barSymbol, false);
195 EXPECT_STREQ("Foo", *fooSymbol);
196 EXPECT_STREQ("Bar", *barSymbol);
199 TEST_F(SymtabTest, TryToAddDuplicates)
201 auto fooSymbol = put_symtab(symtab(), "Foo");
202 auto barSymbol = put_symtab(symtab(), "Bar");
203 ASSERT_EQ(2, symtab()->nr);
205 compareSymtabLookupAndHandle(symtab(), fooSymbol);
206 compareSymtabLookupAndHandle(symtab(), barSymbol);
208 EXPECT_NE(fooSymbol, barSymbol);
209 compareDifferentHandles(symtab(), fooSymbol, barSymbol, false);
210 EXPECT_STREQ("Foo", *fooSymbol);
211 EXPECT_STREQ("Bar", *barSymbol);
213 // Insert a duplicate element
214 auto anotherFooSymbol = put_symtab(symtab(), "Foo");
215 ASSERT_EQ(2, symtab()->nr);
217 // Check for correct post-conditions
218 EXPECT_EQ(fooSymbol, anotherFooSymbol);
219 EXPECT_STREQ("Foo", *anotherFooSymbol);
220 EXPECT_STREQ("Foo", *fooSymbol);
221 EXPECT_STREQ("Bar", *barSymbol);
223 // Check for correct behaviours with new and old symbols
224 compareDifferentHandles(symtab(), fooSymbol, anotherFooSymbol, true);
225 compareDifferentHandles(symtab(), barSymbol, anotherFooSymbol, false);
226 compareDifferentHandles(symtab(), fooSymbol, barSymbol, false);
229 TEST_F(SymtabTest, AddLargeNumberOfEntries)
231 int numStringsToAdd = 7; // Larger than c_maxBufSize limit for size of symbuf.
232 std::vector<char **> symbolsAdded;
233 symbolsAdded.reserve(numStringsToAdd);
234 for (int i = 0; i < numStringsToAdd; ++i)
236 symbolsAdded.push_back(put_symtab(symtab(), toString(i).c_str()));
238 ASSERT_EQ(numStringsToAdd, symtab()->nr);
239 for (int i = 0; i < numStringsToAdd; ++i)
241 EXPECT_STREQ(toString(i).c_str(), *symbolsAdded[i]);
242 compareSymtabLookupAndHandle(symtab(), symbolsAdded[i]);
244 // Add something unrelated and check that indices still work afterward.
245 auto foobarSymbol = put_symtab(symtab(), "foobar");
246 ASSERT_EQ(numStringsToAdd+1, symtab()->nr);
247 for (int i = 0; i < numStringsToAdd; ++i)
249 EXPECT_STREQ(toString(i).c_str(), *symbolsAdded[i]);
250 compareSymtabLookupAndHandle(symtab(), symbolsAdded[i]);
252 compareSymtabLookupAndHandle(symtab(), foobarSymbol);
254 // Now dump the symtab to see that we can reproduce it if needed.
255 dumpSymtab();
258 TEST_F(SymtabTest, NoDuplicatesInLargeTable)
260 int halfOfStringsToAdd = 7; // Larger than c_maxBufSize limit for size of symbuf.
261 int totalNumStringsToAdd = 2*halfOfStringsToAdd;
262 std::vector<char **> symbolsAdded;
263 symbolsAdded.reserve(halfOfStringsToAdd);
264 for (int i = 0; i < halfOfStringsToAdd; ++i)
266 symbolsAdded.push_back(put_symtab(symtab(), toString(i).c_str()));
268 ASSERT_EQ(halfOfStringsToAdd, symtab()->nr);
270 // We now try to mess around in the symtab.
271 auto bazSymbol = put_symtab(symtab(), "baz");
272 ASSERT_EQ(halfOfStringsToAdd+1, symtab()->nr);
273 compareSymtabLookupAndHandle(symtab(), bazSymbol);
275 // Now try to add more symbols, also including those that are already there.
276 for (int i = 0; i < totalNumStringsToAdd; i++)
278 symbolsAdded.push_back(put_symtab(symtab(), toString(i).c_str()));
280 ASSERT_EQ(totalNumStringsToAdd+1, symtab()->nr);
282 //! Check that entries that should be equal are, and new ones are not.
283 for (int i = 0; i < halfOfStringsToAdd; i++)
285 compareDifferentHandles(symtab(), symbolsAdded[i], symbolsAdded[halfOfStringsToAdd+i], true);
286 compareDifferentHandles(symtab(), symbolsAdded[i], symbolsAdded[2*halfOfStringsToAdd+i], false);
287 compareDifferentHandles(symtab(), symbolsAdded[i], bazSymbol, false);
289 compareSymtabLookupAndHandle(symtab(), bazSymbol);
290 EXPECT_STREQ("baz", *bazSymbol);
291 dumpSymtab();
294 } // namespace
296 } // namespace test
298 } // namespace gmx