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 <fcntl.h>
8 #include <sys/stat.h>
9 #include <sys/types.h>
10 #include <unistd.h>
11 #include <typeinfo>
12 
13 #include "fileerror.hh"
14 #include "filehelper.hh"
15 #include "testpaths.h"
16 #include "yapet10file.hh"
17 #include "yapet20file.hh"
18 
19 constexpr auto TEST_FILE{BUILDDIR "/yapet-filehelper-test"};
20 
21 class FileHelperTest : public CppUnit::TestFixture {
22    public:
suite()23     static CppUnit::TestSuite *suite() {
24         CppUnit::TestSuite *suiteOfTests =
25             new CppUnit::TestSuite("File Helper Test");
26 
27         suiteOfTests->addTest(new CppUnit::TestCaller<FileHelperTest>{
28             "reading file identifier should fail on empty file",
29             &FileHelperTest::readEmptyFile});
30 
31         suiteOfTests->addTest(new CppUnit::TestCaller<FileHelperTest>{
32             "reading file identifier should fail on unknown file",
33             &FileHelperTest::failReadIdentifierUnknownFile});
34 
35         suiteOfTests->addTest(new CppUnit::TestCaller<FileHelperTest>{
36             "should read YAPET 1.0 file identifier",
37             &FileHelperTest::readYapet10FileIdentifier});
38 
39         suiteOfTests->addTest(new CppUnit::TestCaller<FileHelperTest>{
40             "should read YAPET 2.0 file identifier",
41             &FileHelperTest::readYapet20FileIdentifier});
42 
43         suiteOfTests->addTest(new CppUnit::TestCaller<FileHelperTest>{
44             "should get YAPET 1.0 file", &FileHelperTest::getYapet10File});
45         suiteOfTests->addTest(new CppUnit::TestCaller<FileHelperTest>{
46             "should get YAPET 2.0 file", &FileHelperTest::getYapet20File});
47 
48         suiteOfTests->addTest(new CppUnit::TestCaller<FileHelperTest>{
49             "should read YAPET 1.0 meta data",
50             &FileHelperTest::readYapet10MetaData});
51         suiteOfTests->addTest(new CppUnit::TestCaller<FileHelperTest>{
52             "should read YAPET 2.0 meta data",
53             &FileHelperTest::readYapet20MetaData});
54 
55         return suiteOfTests;
56     }
57 
openFile()58     int openFile() {
59         auto fd = ::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR,
60                          S_IRWXU | S_IRWXG | S_IRWXO);
61         if (fd < 0) {
62             throw std::runtime_error{"Error creating file"};
63         }
64 
65         return fd;
66     }
67 
createEmptyFile()68     void createEmptyFile() {
69         auto fd = openFile();
70 
71         ::close(fd);
72     }
73 
setUp()74     void setUp() { ::unlink(TEST_FILE); }
75 
tearDown()76     void tearDown() { ::unlink(TEST_FILE); }
77 
readEmptyFile()78     void readEmptyFile() {
79         createEmptyFile();
80 
81         CPPUNIT_ASSERT_THROW(yapet::readFileIdentifier(TEST_FILE),
82                              yapet::FileFormatError);
83     }
84 
failReadIdentifierUnknownFile()85     void failReadIdentifierUnknownFile() {
86         int fd{openFile()};
87 
88         write(fd, "bla", 3);
89         close(fd);
90 
91         CPPUNIT_ASSERT_THROW(yapet::readFileIdentifier(TEST_FILE),
92                              yapet::FileFormatError);
93     }
94 
makeYapet10File()95     void makeYapet10File() {
96         int fd{openFile()};
97 
98         write(fd, yapet::Yapet10File::RECOGNITION_STRING,
99               yapet::Yapet10File::RECOGNITION_STRING_SIZE);
100         close(fd);
101     }
102 
readYapet10FileIdentifier()103     void readYapet10FileIdentifier() {
104         makeYapet10File();
105 
106         auto actual{yapet::readFileIdentifier(TEST_FILE)};
107         auto expected{
108             yapet::toSecureArray(yapet::Yapet10File::RECOGNITION_STRING,
109                                  yapet::Yapet10File::RECOGNITION_STRING_SIZE)};
110 
111         CPPUNIT_ASSERT(actual == expected);
112 
113         CPPUNIT_ASSERT(yapet::isFileType(expected, TEST_FILE));
114 
115         auto unexpected{
116             yapet::toSecureArray(yapet::Yapet20File::RECOGNITION_STRING,
117                                  yapet::Yapet20File::RECOGNITION_STRING_SIZE)};
118         CPPUNIT_ASSERT(!yapet::isFileType(unexpected, TEST_FILE));
119     }
120 
makeYapet20File()121     void makeYapet20File() {
122         int fd{openFile()};
123 
124         write(fd, yapet::Yapet20File::RECOGNITION_STRING,
125               yapet::Yapet20File::RECOGNITION_STRING_SIZE);
126         close(fd);
127     }
128 
readYapet20FileIdentifier()129     void readYapet20FileIdentifier() {
130         makeYapet20File();
131 
132         auto actual{yapet::readFileIdentifier(TEST_FILE)};
133         auto expected{
134             yapet::toSecureArray(yapet::Yapet20File::RECOGNITION_STRING,
135                                  yapet::Yapet20File::RECOGNITION_STRING_SIZE)};
136 
137         CPPUNIT_ASSERT(actual == expected);
138 
139         CPPUNIT_ASSERT(yapet::isFileType(expected, TEST_FILE));
140 
141         auto unexpected{
142             yapet::toSecureArray(yapet::Yapet10File::RECOGNITION_STRING,
143                                  yapet::Yapet10File::RECOGNITION_STRING_SIZE)};
144 
145         CPPUNIT_ASSERT(!yapet::isFileType(unexpected, TEST_FILE));
146     }
147 
getYapet10File()148     void getYapet10File() {
149         yapet::SecureArray metaData{};
150         yapet::SecureArray header{yapet::toSecureArray("Header")};
151         try {
152             yapet::Yapet10File file{TEST_FILE, true, false};
153             file.open();
154             file.writeIdentifier();
155             file.writeUnencryptedMetaData(metaData);
156             file.writeHeader(header);
157         } catch (...) {
158             CPPUNIT_FAIL("Unexpected exception");
159         }
160 
161         auto file{yapet::getFile(TEST_FILE, false)};
162 #pragma clang diagnostic push
163 #pragma clang diagnostic ignored "-Wpotentially-evaluated-expression"
164         CPPUNIT_ASSERT(typeid(*file) == typeid(yapet::Yapet10File));
165 #pragma clang diagnostic pop
166     }
167 
getYapet20File()168     void getYapet20File() {
169         yapet::SecureArray metaData{yapet::toSecureArray("MetaData")};
170         yapet::SecureArray header{yapet::toSecureArray("Header")};
171         try {
172             yapet::Yapet20File file{TEST_FILE, true, false};
173             file.open();
174             file.writeIdentifier();
175             file.writeUnencryptedMetaData(metaData);
176             file.writeHeader(header);
177         } catch (...) {
178             CPPUNIT_FAIL("Unexpected exception");
179         }
180 
181         auto file{yapet::getFile(TEST_FILE, false)};
182 #pragma clang diagnostic push
183 #pragma clang diagnostic ignored "-Wpotentially-evaluated-expression"
184         CPPUNIT_ASSERT(typeid(*file) == typeid(yapet::Yapet20File));
185 #pragma clang diagnostic pop
186     }
187 
readYapet10MetaData()188     void readYapet10MetaData() {
189         yapet::MetaData metaData{};
190         yapet::SecureArray header{yapet::toSecureArray("Header")};
191         try {
192             yapet::Yapet10File file{TEST_FILE, true, false};
193             file.open();
194             file.writeIdentifier();
195             file.writeUnencryptedMetaData(metaData.serialize());
196             file.writeHeader(header);
197         } catch (...) {
198             CPPUNIT_FAIL("Unexpected exception");
199         }
200 
201         auto actual{yapet::readMetaData(TEST_FILE, false)};
202         CPPUNIT_ASSERT(actual.size() == metaData.size());
203     }
204 
readYapet20MetaData()205     void readYapet20MetaData() {
206         yapet::MetaData metaData{};
207         metaData.setValue("a", 42);
208         metaData.setValue("b", 84);
209 
210         yapet::SecureArray header{yapet::toSecureArray("Header")};
211         try {
212             yapet::Yapet20File file{TEST_FILE, true, false};
213             file.open();
214             file.writeIdentifier();
215             file.writeUnencryptedMetaData(metaData.serialize());
216             file.writeHeader(header);
217         } catch (...) {
218             CPPUNIT_FAIL("Unexpected exception");
219         }
220 
221         auto actual{yapet::readMetaData(TEST_FILE, false)};
222         CPPUNIT_ASSERT(actual.size() == metaData.size());
223         CPPUNIT_ASSERT(actual.getValue("a") == metaData.getValue("a"));
224         CPPUNIT_ASSERT(actual.getValue("b") == metaData.getValue("b"));
225     }
226 };
227 
main()228 int main() {
229     CppUnit::TextUi::TestRunner runner;
230     runner.addTest(FileHelperTest::suite());
231     return runner.run() ? 0 : 1;
232 }