1 #include <cppunit/CompilerOutputter.h>
2 #include <cppunit/TestCaller.h>
3 #include <cppunit/TestFixture.h>
4 #include <cppunit/extensions/TestFactoryRegistry.h>
5 #include <cppunit/ui/text/TestRunner.h>
6 
7 #include <cstring>
8 
9 #include <fcntl.h>
10 #include <sys/stat.h>
11 #include <sys/types.h>
12 #include <unistd.h>
13 
14 #include "fileerror.hh"
15 #include "fileutils.hh"
16 #include "testpaths.h"
17 #include "yapet10file.hh"
18 
19 constexpr auto TEST_FILE{BUILDDIR "/yapet-yapet10file-test"};
20 
21 class Yapet10FileTest : public CppUnit::TestFixture {
22    public:
suite()23     static CppUnit::TestSuite* suite() {
24         CppUnit::TestSuite* suiteOfTests =
25             new CppUnit::TestSuite("Yapet 1.0 File test");
26         suiteOfTests->addTest(new CppUnit::TestCaller<Yapet10FileTest>{
27             "should not fail opening a new file",
28             &Yapet10FileTest::openNewFile});
29         suiteOfTests->addTest(new CppUnit::TestCaller<Yapet10FileTest>{
30             "should fail reading empty identifier",
31             &Yapet10FileTest::failOpeningEmptyFile});
32 
33         suiteOfTests->addTest(new CppUnit::TestCaller<Yapet10FileTest>{
34             "should fail opening a file with wrong identifier",
35             &Yapet10FileTest::failOpeningFileWithWrongIdentifier});
36         suiteOfTests->addTest(new CppUnit::TestCaller<Yapet10FileTest>{
37             "should read identifier", &Yapet10FileTest::readIdentifier});
38         suiteOfTests->addTest(new CppUnit::TestCaller<Yapet10FileTest>{
39             "should return zero SecureArray on readUnencryptedMetaData",
40             &Yapet10FileTest::readUnencryptedMetaData});
41 
42         suiteOfTests->addTest(new CppUnit::TestCaller<Yapet10FileTest>{
43             "should fail reading empty header",
44             &Yapet10FileTest::failReadingEmptyHeader});
45         suiteOfTests->addTest(new CppUnit::TestCaller<Yapet10FileTest>{
46             "should read header", &Yapet10FileTest::readHeader});
47         suiteOfTests->addTest(new CppUnit::TestCaller<Yapet10FileTest>{
48             "should return empty password list",
49             &Yapet10FileTest::readNoPasswords});
50         suiteOfTests->addTest(new CppUnit::TestCaller<Yapet10FileTest>{
51             "should read password records",
52             &Yapet10FileTest::readPasswordRecords});
53         suiteOfTests->addTest(new CppUnit::TestCaller<Yapet10FileTest>{
54             "should move", &Yapet10FileTest::moveConstructor});
55         suiteOfTests->addTest(new CppUnit::TestCaller<Yapet10FileTest>{
56             "should move assign", &Yapet10FileTest::moveAssignment});
57 
58         return suiteOfTests;
59     }
60 
setUp()61     void setUp() { ::unlink(TEST_FILE); }
62 
tearDown()63     void tearDown() { ::unlink(TEST_FILE); }
64 
openNewFile()65     void openNewFile() {
66         yapet::Yapet10File newFile{TEST_FILE, true, false};
67         newFile.open();
68     }
69 
failOpeningEmptyFile()70     void failOpeningEmptyFile() {
71         int fd = ::open(TEST_FILE, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR);
72         CPPUNIT_ASSERT(fd > -1);
73         ::close(fd);
74 
75         yapet::Yapet10File yapet10File{TEST_FILE, false, false};
76         CPPUNIT_ASSERT_THROW(yapet10File.open(), yapet::FileFormatError);
77     }
78 
failOpeningFileWithWrongIdentifier()79     void failOpeningFileWithWrongIdentifier() {
80         yapet::Yapet10File yapet10File{
81             BUILDDIR "/yapet10file-corrupt-identifier.pet", false, false};
82         CPPUNIT_ASSERT_THROW(yapet10File.open(), yapet::FileFormatError);
83     }
84 
readIdentifier()85     void readIdentifier() {
86         // try/catch block to close file when yapet10File goes out of scope
87         try {
88             yapet::Yapet10File yapet10File{TEST_FILE, true, false};
89             yapet10File.open();
90             yapet10File.writeIdentifier();
91         } catch (...) {
92             CPPUNIT_FAIL("No exception expected");
93         }
94 
95         yapet::Yapet10File yapet10File2{TEST_FILE, false, false};
96         yapet10File2.open();
97         CPPUNIT_ASSERT(
98             std::memcmp(*yapet10File2.readIdentifier(), "YAPET1.0", 8) == 0);
99     }
100 
readUnencryptedMetaData()101     void readUnencryptedMetaData() {
102         yapet::Yapet10File yapet10File{TEST_FILE, true, false};
103         yapet10File.open();
104         auto emptyMetaData{yapet10File.readUnencryptedMetaData()};
105 
106         CPPUNIT_ASSERT(emptyMetaData == yapet::SecureArray{});
107     }
108 
failReadingEmptyHeader()109     void failReadingEmptyHeader() {
110         yapet::Yapet10File yapet10File{TEST_FILE, true, false};
111         yapet10File.open();
112         yapet10File.writeIdentifier();
113 
114         CPPUNIT_ASSERT_THROW(yapet10File.readHeader(), yapet::FileFormatError);
115     }
116 
readHeader()117     void readHeader() {
118         // try/catch block to close file when yapet10File goes out of scope
119         try {
120             yapet::Yapet10File yapet10File{TEST_FILE, true, false};
121             yapet10File.open();
122             yapet10File.writeIdentifier();
123 
124             yapet::SecureArray headerData(2);
125             (*headerData)[0] = 'A';
126             (*headerData)[1] = 'B';
127             yapet10File.writeHeader(headerData);
128         } catch (...) {
129             CPPUNIT_FAIL("No exception expected");
130         }
131 
132         yapet::Yapet10File yapet10File{TEST_FILE, false, false};
133         yapet10File.open();
134         auto headerData = yapet10File.readHeader();
135 
136         CPPUNIT_ASSERT((*headerData)[0] == 'A' && (*headerData)[1] == 'B');
137     }
138 
readNoPasswords()139     void readNoPasswords() {
140         // try/catch block to close file when yapet10File goes out of scope
141         try {
142             yapet::Yapet10File yapet10File{TEST_FILE, true, false};
143             yapet10File.open();
144             yapet10File.writeIdentifier();
145 
146             yapet::SecureArray headerData(1);
147             (*headerData)[0] = 'M';
148             yapet10File.writeHeader(headerData);
149         } catch (...) {
150             CPPUNIT_FAIL("No exception expected");
151         }
152 
153         yapet::Yapet10File yapet10File{TEST_FILE, false, false};
154         yapet10File.open();
155 
156         auto passwords = yapet10File.readPasswordRecords();
157         CPPUNIT_ASSERT(passwords.size() == 0);
158     }
159 
writeTestPasswords()160     void writeTestPasswords() {
161         yapet::Yapet10File yapet10File{TEST_FILE, true, false};
162         yapet10File.open();
163         yapet10File.writeIdentifier();
164 
165         yapet::SecureArray headerData(1);
166         (*headerData)[0] = 'M';
167         yapet10File.writeHeader(headerData);
168 
169         std::list<yapet::SecureArray> passwords;
170         for (auto i = 0; i < 5; i++) {
171             yapet::SecureArray password(1);
172             **password = i;
173             passwords.push_back(password);
174         }
175 
176         yapet10File.writePasswordRecords(passwords);
177     }
178 
testPasswordRecords(std::list<yapet::SecureArray> passwords)179     void testPasswordRecords(std::list<yapet::SecureArray> passwords) {
180         CPPUNIT_ASSERT(passwords.size() == 5);
181 
182         auto expectedValue{0};
183         for (auto password : passwords) {
184             CPPUNIT_ASSERT(password.size() == 1);
185             CPPUNIT_ASSERT(**password == expectedValue++);
186         }
187     }
188 
readPasswordRecords()189     void readPasswordRecords() {
190         writeTestPasswords();
191 
192         yapet::Yapet10File yapet10File{TEST_FILE, false, false};
193         yapet10File.open();
194         auto passwords = yapet10File.readPasswordRecords();
195 
196         testPasswordRecords(passwords);
197     }
198 
moveConstructor()199     void moveConstructor() {
200         writeTestPasswords();
201 
202         yapet::Yapet10File yapet10File{TEST_FILE, false, false};
203         yapet10File.open();
204 
205         yapet::Yapet10File yapet10FileMoved{std::move(yapet10File)};
206 
207         CPPUNIT_ASSERT(yapet10FileMoved.isSecure() == false);
208         CPPUNIT_ASSERT(yapet10FileMoved.isCreate() == false);
209 
210         auto passwords = yapet10FileMoved.readPasswordRecords();
211         testPasswordRecords(passwords);
212     }
213 
moveAssignment()214     void moveAssignment() {
215         writeTestPasswords();
216 
217         yapet::Yapet10File yapet10File{TEST_FILE, false, false};
218         yapet10File.open();
219 
220         yapet::Yapet10File yapet10FileMoved = std::move(yapet10File);
221 
222         CPPUNIT_ASSERT(yapet10FileMoved.isSecure() == false);
223         CPPUNIT_ASSERT(yapet10FileMoved.isCreate() == false);
224 
225         auto passwords = yapet10FileMoved.readPasswordRecords();
226         testPasswordRecords(passwords);
227     }
228 };
229 
main()230 int main() {
231     CppUnit::TextUi::TestRunner runner;
232     runner.addTest(Yapet10FileTest::suite());
233     return runner.run() ? 0 : 1;
234 }