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 }