1 /*
2 * LibrePCB - Professional EDA for everyone!
3 * Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
4 * https://librepcb.org/
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /*******************************************************************************
21 * Includes
22 ******************************************************************************/
23 #include <gtest/gtest.h>
24 #include <librepcb/common/fileio/fileutils.h>
25 #include <librepcb/common/fileio/transactionalfilesystem.h>
26 #include <librepcb/library/sym/symbol.h>
27 #include <librepcb/project/library/projectlibrary.h>
28
29 #include <QtCore>
30
31 /*******************************************************************************
32 * Namespace
33 ******************************************************************************/
34 namespace librepcb {
35 namespace project {
36 namespace tests {
37
38 /*******************************************************************************
39 * Test Class
40 ******************************************************************************/
41
42 class ProjectLibraryTest : public ::testing::Test {
43 protected:
44 FilePath mTempDir;
45 FilePath mLibDir;
46 std::shared_ptr<TransactionalFileSystem> mTempFs;
47 std::shared_ptr<TransactionalFileSystem> mLibFs;
48 QFileInfo mExistingSymbolFile;
49 qint64 mExistingSymbolCreationSize;
50 QScopedPointer<library::Symbol> mNewSymbol;
51 QFileInfo mNewSymbolFile;
52
ProjectLibraryTest()53 ProjectLibraryTest() {
54 mTempDir = FilePath::getRandomTempPath();
55 mLibDir = mTempDir.getPathTo("project library test");
56 mTempFs = TransactionalFileSystem::openRW(mTempDir);
57 mLibFs = TransactionalFileSystem::openRW(mLibDir);
58
59 // create symbol inside project library
60 library::Symbol sym(Uuid::createRandom(), Version::fromString("1"), "",
61 ElementName("Existing Symbol"), "", "");
62 TransactionalDirectory libSymDir(mLibFs, "sym");
63 sym.saveIntoParentDirectory(libSymDir);
64 mLibFs->save();
65 mExistingSymbolFile = QFileInfo(
66 mLibDir
67 .getPathTo(QString("sym/%1/symbol.lp").arg(sym.getUuid().toStr()))
68 .toStr());
69 modifyExistingSymbol(); // modify file to detect when it gets overwritten
70
71 // create symbol outside the project library (emulating workspace library)
72 mNewSymbol.reset(new library::Symbol(Uuid::createRandom(),
73 Version::fromString("1"), "",
74 ElementName("New Symbol"), "", ""));
75 TransactionalDirectory tempSymDir(mTempFs);
76 mNewSymbol->saveIntoParentDirectory(tempSymDir);
77 mTempFs->save();
78 mNewSymbolFile =
79 mLibDir
80 .getPathTo(
81 QString("sym/%1/symbol.lp").arg(mNewSymbol->getUuid().toStr()))
82 .toStr();
83
84 // disable caching to get correct results
85 mExistingSymbolFile.setCaching(false);
86 mNewSymbolFile.setCaching(false);
87 }
88
~ProjectLibraryTest()89 virtual ~ProjectLibraryTest() { QDir(mTempDir.toStr()).removeRecursively(); }
90
getFirstSymbol(ProjectLibrary & lib)91 library::Symbol* getFirstSymbol(ProjectLibrary& lib) {
92 if (lib.getSymbols().isEmpty()) throw LogicError(__FILE__, __LINE__);
93 return lib.getSymbols().values().first();
94 }
95
save(ProjectLibrary & lib)96 void save(ProjectLibrary& lib) {
97 lib.save();
98 mLibFs->save();
99 mTempFs->save();
100 }
101
modifyExistingSymbol()102 void modifyExistingSymbol() {
103 FilePath fp(mExistingSymbolFile.absoluteFilePath());
104 FileUtils::writeFile(fp, FileUtils::readFile(fp).append(" "));
105 mExistingSymbolCreationSize = mExistingSymbolFile.size();
106 }
107 };
108
109 /*******************************************************************************
110 * Test Methods
111 ******************************************************************************/
112
TEST_F(ProjectLibraryTest,testLoadSymbol)113 TEST_F(ProjectLibraryTest, testLoadSymbol) {
114 {
115 ProjectLibrary lib(std::unique_ptr<TransactionalDirectory>(
116 new TransactionalDirectory(mLibFs)));
117 EXPECT_EQ(1, lib.getSymbols().count());
118 EXPECT_TRUE(mExistingSymbolFile.exists());
119 }
120 EXPECT_TRUE(mExistingSymbolFile.exists());
121 EXPECT_EQ(mExistingSymbolCreationSize,
122 mExistingSymbolFile.size()); // not upgraded
123 }
124
TEST_F(ProjectLibraryTest,testAddSymbol)125 TEST_F(ProjectLibraryTest, testAddSymbol) {
126 {
127 ProjectLibrary lib(std::unique_ptr<TransactionalDirectory>(
128 new TransactionalDirectory(mLibFs)));
129 lib.addSymbol(*mNewSymbol.take());
130 EXPECT_EQ(2, lib.getSymbols().count());
131 EXPECT_TRUE(mExistingSymbolFile.exists());
132 EXPECT_FALSE(mNewSymbolFile.exists());
133 EXPECT_FALSE(mNewSymbolFile.dir().exists());
134 }
135 EXPECT_TRUE(mExistingSymbolFile.exists());
136 EXPECT_FALSE(mNewSymbolFile.exists());
137 EXPECT_FALSE(mNewSymbolFile.dir().exists());
138 EXPECT_EQ(mExistingSymbolCreationSize,
139 mExistingSymbolFile.size()); // not upgraded
140 }
141
TEST_F(ProjectLibraryTest,testAddSymbol_Save)142 TEST_F(ProjectLibraryTest, testAddSymbol_Save) {
143 {
144 ProjectLibrary lib(std::unique_ptr<TransactionalDirectory>(
145 new TransactionalDirectory(mLibFs)));
146 lib.addSymbol(*mNewSymbol.take());
147 save(lib);
148 EXPECT_EQ(2, lib.getSymbols().count());
149 EXPECT_TRUE(mExistingSymbolFile.exists());
150 EXPECT_TRUE(mNewSymbolFile.exists());
151 }
152 EXPECT_TRUE(mExistingSymbolFile.exists());
153 EXPECT_TRUE(mNewSymbolFile.exists());
154 EXPECT_NE(mExistingSymbolCreationSize,
155 mExistingSymbolFile.size()); // upgraded!
156 }
157
TEST_F(ProjectLibraryTest,testAddRemoveSymbol)158 TEST_F(ProjectLibraryTest, testAddRemoveSymbol) {
159 {
160 ProjectLibrary lib(std::unique_ptr<TransactionalDirectory>(
161 new TransactionalDirectory(mLibFs)));
162 lib.addSymbol(*mNewSymbol);
163 lib.removeSymbol(*mNewSymbol.take());
164 EXPECT_EQ(1, lib.getSymbols().count());
165 EXPECT_TRUE(mExistingSymbolFile.exists());
166 EXPECT_FALSE(mNewSymbolFile.exists());
167 EXPECT_FALSE(mNewSymbolFile.dir().exists());
168 }
169 EXPECT_TRUE(mExistingSymbolFile.exists());
170 EXPECT_FALSE(mNewSymbolFile.exists());
171 EXPECT_FALSE(mNewSymbolFile.dir().exists());
172 EXPECT_EQ(mExistingSymbolCreationSize,
173 mExistingSymbolFile.size()); // not upgraded
174 }
175
TEST_F(ProjectLibraryTest,testAddRemoveSymbol_Save)176 TEST_F(ProjectLibraryTest, testAddRemoveSymbol_Save) {
177 {
178 ProjectLibrary lib(std::unique_ptr<TransactionalDirectory>(
179 new TransactionalDirectory(mLibFs)));
180 lib.addSymbol(*mNewSymbol);
181 lib.removeSymbol(*mNewSymbol.take());
182 save(lib);
183 EXPECT_EQ(1, lib.getSymbols().count());
184 EXPECT_TRUE(mExistingSymbolFile.exists());
185 EXPECT_FALSE(mNewSymbolFile.exists());
186 EXPECT_FALSE(mNewSymbolFile.dir().exists());
187 }
188 EXPECT_TRUE(mExistingSymbolFile.exists());
189 EXPECT_FALSE(mNewSymbolFile.exists());
190 EXPECT_FALSE(mNewSymbolFile.dir().exists());
191 EXPECT_NE(mExistingSymbolCreationSize,
192 mExistingSymbolFile.size()); // upgraded!
193 }
194
TEST_F(ProjectLibraryTest,testRemoveSymbol)195 TEST_F(ProjectLibraryTest, testRemoveSymbol) {
196 {
197 ProjectLibrary lib(std::unique_ptr<TransactionalDirectory>(
198 new TransactionalDirectory(mLibFs)));
199 lib.removeSymbol(*getFirstSymbol(lib));
200 EXPECT_EQ(0, lib.getSymbols().count());
201 EXPECT_TRUE(mExistingSymbolFile.exists());
202 }
203 EXPECT_TRUE(mExistingSymbolFile.exists());
204 EXPECT_EQ(mExistingSymbolCreationSize,
205 mExistingSymbolFile.size()); // not upgraded
206 }
207
TEST_F(ProjectLibraryTest,testRemoveSymbol_Save)208 TEST_F(ProjectLibraryTest, testRemoveSymbol_Save) {
209 {
210 ProjectLibrary lib(std::unique_ptr<TransactionalDirectory>(
211 new TransactionalDirectory(mLibFs)));
212 lib.removeSymbol(*getFirstSymbol(lib));
213 save(lib);
214 EXPECT_EQ(0, lib.getSymbols().count());
215 EXPECT_FALSE(mExistingSymbolFile.exists());
216 EXPECT_FALSE(mExistingSymbolFile.dir().exists());
217 }
218 EXPECT_FALSE(mExistingSymbolFile.exists());
219 EXPECT_FALSE(mExistingSymbolFile.dir().exists());
220 }
221
TEST_F(ProjectLibraryTest,testRemoveAddSymbol)222 TEST_F(ProjectLibraryTest, testRemoveAddSymbol) {
223 {
224 ProjectLibrary lib(std::unique_ptr<TransactionalDirectory>(
225 new TransactionalDirectory(mLibFs)));
226 library::Symbol* sym = getFirstSymbol(lib);
227 lib.removeSymbol(*sym);
228 lib.addSymbol(*sym);
229 EXPECT_EQ(1, lib.getSymbols().count());
230 EXPECT_TRUE(mExistingSymbolFile.exists());
231 }
232 EXPECT_TRUE(mExistingSymbolFile.exists());
233 EXPECT_EQ(mExistingSymbolCreationSize,
234 mExistingSymbolFile.size()); // not upgraded
235 }
236
TEST_F(ProjectLibraryTest,testRemoveAddSymbol_Save)237 TEST_F(ProjectLibraryTest, testRemoveAddSymbol_Save) {
238 {
239 ProjectLibrary lib(std::unique_ptr<TransactionalDirectory>(
240 new TransactionalDirectory(mLibFs)));
241 library::Symbol* sym = getFirstSymbol(lib);
242 lib.removeSymbol(*sym);
243 lib.addSymbol(*sym);
244 save(lib);
245 EXPECT_EQ(1, lib.getSymbols().count());
246 EXPECT_TRUE(mExistingSymbolFile.exists());
247 }
248 EXPECT_TRUE(mExistingSymbolFile.exists());
249 EXPECT_NE(mExistingSymbolCreationSize,
250 mExistingSymbolFile.size()); // upgraded!
251 }
252
TEST_F(ProjectLibraryTest,testSavingToExistingEmptyDirectory)253 TEST_F(ProjectLibraryTest, testSavingToExistingEmptyDirectory) {
254 ProjectLibrary lib(std::unique_ptr<TransactionalDirectory>(
255 new TransactionalDirectory(mLibFs)));
256
257 // already create the destination directory to see if saving still works
258 EXPECT_FALSE(mNewSymbolFile.dir().exists());
259 FileUtils::makePath(FilePath(mNewSymbolFile.dir().absolutePath()));
260 EXPECT_TRUE(mNewSymbolFile.dir().exists());
261
262 lib.addSymbol(*mNewSymbol.take());
263 save(lib);
264 EXPECT_TRUE(mNewSymbolFile.exists());
265 }
266
TEST_F(ProjectLibraryTest,testIfExistingSymbolIsUpgradedOnlyOnce)267 TEST_F(ProjectLibraryTest, testIfExistingSymbolIsUpgradedOnlyOnce) {
268 ProjectLibrary lib(std::unique_ptr<TransactionalDirectory>(
269 new TransactionalDirectory(mLibFs)));
270 EXPECT_EQ(mExistingSymbolCreationSize,
271 mExistingSymbolFile.size()); // not upgraded
272 save(lib);
273 EXPECT_NE(mExistingSymbolCreationSize,
274 mExistingSymbolFile.size()); // upgraded!
275 modifyExistingSymbol();
276 EXPECT_EQ(mExistingSymbolCreationSize,
277 mExistingSymbolFile.size()); // not upgraded
278 save(lib);
279 EXPECT_EQ(mExistingSymbolCreationSize,
280 mExistingSymbolFile.size()); // not upgraded
281 }
282
283 /*******************************************************************************
284 * End of File
285 ******************************************************************************/
286
287 } // namespace tests
288 } // namespace project
289 } // namespace librepcb
290