blob: fc423a1efdb5c7d8557842df0f7e99604321dfa5 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yingdi Yuf50098d2014-02-26 14:26:29 -08002/**
Alexander Afanasyeve4f8c3b2016-06-23 16:03:48 -07003 * Copyright (c) 2013-2016 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Yingdi Yuf50098d2014-02-26 14:26:29 -080020 */
21
Yingdi Yuf50098d2014-02-26 14:26:29 -080022#include "util/io.hpp"
23#include "security/key-chain.hpp"
24
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070025#include "boost-test.hpp"
Junxiao Shic1779882016-08-17 01:59:23 +000026#include "identity-management-fixture.hpp"
27#include <boost/filesystem.hpp>
28#include <fstream>
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070029
Yingdi Yuf50098d2014-02-26 14:26:29 -080030namespace ndn {
Spyridon Mastorakis429634f2015-02-19 17:35:33 -080031namespace tests {
Yingdi Yuf50098d2014-02-26 14:26:29 -080032
Junxiao Shic1779882016-08-17 01:59:23 +000033class IoFixture
Yingdi Yuf50098d2014-02-26 14:26:29 -080034{
Junxiao Shic1779882016-08-17 01:59:23 +000035protected:
36 IoFixture()
37 : filepath(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) /= "TestIo")
38 , filename(filepath.string())
39 {
40 boost::filesystem::create_directories(filepath.parent_path());
41 }
42
43 ~IoFixture()
44 {
45 boost::system::error_code ec;
46 boost::filesystem::remove(filepath, ec); // ignore error
47 }
48
49 /** \brief create a directory at filename, so that it's neither readable nor writable as a file
50 */
51 void
52 mkdir() const
53 {
54 boost::filesystem::create_directory(filepath);
55 }
56
57 template<typename Container, typename CharT = typename Container::value_type>
58 Container
59 readFile() const
60 {
61 Container container;
62 std::ifstream fs(filename, std::ios_base::binary);
63 char ch;
64 while (fs.get(ch)) {
65 container.push_back(static_cast<CharT>(ch));
66 }
67 return container;
68 }
69
70 template<typename Container, typename CharT = typename Container::value_type>
71 void
72 writeFile(const Container& content) const
73 {
74 std::ofstream fs(filename, std::ios_base::binary);
75 for (CharT ch : content) {
76 fs.put(static_cast<char>(ch));
77 }
78 fs.close();
79 BOOST_REQUIRE_MESSAGE(fs, "error writing file");
80 }
81
82protected:
83 const boost::filesystem::path filepath;
84 const std::string filename;
85};
86
87BOOST_AUTO_TEST_SUITE(Util)
88BOOST_FIXTURE_TEST_SUITE(TestIo, IoFixture)
89
90class EncodableType
91{
92public:
93 class Error : public tlv::Error
94 {
95 public:
96 Error()
97 : tlv::Error("encode error")
98 {
99 }
100 };
101
102 Block
103 wireEncode() const
104 {
105 if (shouldThrow) {
106 BOOST_THROW_EXCEPTION(Error());
107 }
108
109 // block will be 0xAA, 0x01, 0xDD
110 return makeNonNegativeIntegerBlock(0xAA, 0xDD);
111 }
112
113public:
114 bool shouldThrow = false;
115};
116
117class DecodableType
118{
119public:
120 class Error : public tlv::Error
121 {
122 public:
123 Error()
124 : tlv::Error("decode error")
125 {
126 }
127 };
128
129 void
130 wireDecode(const Block& block) const
131 {
132 if (shouldThrow) {
133 BOOST_THROW_EXCEPTION(Error());
134 }
135
136 // block must be 0xBB, 0x01, 0xEE
137 BOOST_CHECK_EQUAL(block.type(), 0xBB);
138 BOOST_REQUIRE_EQUAL(block.value_size(), 1);
139 BOOST_CHECK_EQUAL(block.value()[0], 0xEE);
140 }
141
142public:
143 bool shouldThrow = false;
144};
145
146class DecodableTypeThrow : public DecodableType
147{
148public:
149 DecodableTypeThrow()
150 {
151 this->shouldThrow = true;
152 }
153};
154
155BOOST_AUTO_TEST_CASE(LoadNoEncoding)
156{
157 this->writeFile<std::vector<uint8_t>>({0xBB, 0x01, 0xEE});
158 shared_ptr<DecodableType> decoded = io::load<DecodableType>(filename, io::NO_ENCODING);
159 BOOST_CHECK(decoded != nullptr);
160}
161
162BOOST_AUTO_TEST_CASE(LoadBase64)
163{
164 this->writeFile<std::string>("uwHu\n"); // printf '\xBB\x01\xEE' | base64
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000165 shared_ptr<DecodableType> decoded = io::load<DecodableType>(filename, io::BASE64);
166 BOOST_CHECK(decoded != nullptr);
167}
168
169BOOST_AUTO_TEST_CASE(LoadBase64Newline64)
170{
171 this->writeFile<std::string>(
172 "CEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
173 "AAAAAAAAAAAA\n");
174 // printf '\x08\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
175 // \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
176 // \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
177 // \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | base64
178 shared_ptr<name::Component> decoded = io::load<name::Component>(filename, io::BASE64);
179 BOOST_CHECK(decoded != nullptr);
180}
181
182BOOST_AUTO_TEST_CASE(LoadBase64Newline32)
183{
184 this->writeFile<std::string>(
185 "CEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
186 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
187 "AAAAAAAAAAAA\n");
188 shared_ptr<name::Component> decoded = io::load<name::Component>(filename, io::BASE64);
189 BOOST_CHECK(decoded != nullptr);
190}
191
192BOOST_AUTO_TEST_CASE(LoadBase64NewlineEnd)
193{
194 this->writeFile<std::string>(
195 "CEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n");
196 shared_ptr<name::Component> decoded = io::load<name::Component>(filename, io::BASE64);
197 BOOST_CHECK(decoded != nullptr);
198}
199
200BOOST_AUTO_TEST_CASE(LoadBase64NoNewline)
201{
202 this->writeFile<std::string>(
203 "CEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
204 shared_ptr<name::Component> decoded = io::load<name::Component>(filename, io::BASE64);
Junxiao Shic1779882016-08-17 01:59:23 +0000205 BOOST_CHECK(decoded != nullptr);
206}
207
208BOOST_AUTO_TEST_CASE(LoadHex)
209{
210 this->writeFile<std::string>("BB01EE");
211 shared_ptr<DecodableType> decoded = io::load<DecodableType>(filename, io::HEX);
212 BOOST_CHECK(decoded != nullptr);
213}
214
215BOOST_AUTO_TEST_CASE(LoadException)
216{
217 this->writeFile<std::vector<uint8_t>>({0xBB, 0x01, 0xEE});
218 shared_ptr<DecodableTypeThrow> decoded;
219 BOOST_CHECK_NO_THROW(decoded = io::load<DecodableTypeThrow>(filename, io::NO_ENCODING));
220 BOOST_CHECK(decoded == nullptr);
221}
222
223BOOST_AUTO_TEST_CASE(LoadNotHex)
224{
225 this->writeFile<std::string>("not-hex");
226 shared_ptr<DecodableType> decoded;
227 BOOST_CHECK_NO_THROW(decoded = io::load<DecodableType>(filename, io::HEX));
228 BOOST_CHECK(decoded == nullptr);
229}
230
231BOOST_AUTO_TEST_CASE(LoadFileNotReadable)
232{
Junxiao Shic1779882016-08-17 01:59:23 +0000233 shared_ptr<DecodableType> decoded;
234 BOOST_CHECK_NO_THROW(decoded = io::load<DecodableType>(filename, io::NO_ENCODING));
235 BOOST_CHECK(decoded == nullptr);
236}
237
238BOOST_AUTO_TEST_CASE(SaveNoEncoding)
239{
240 EncodableType encoded;
241 BOOST_CHECK_NO_THROW(io::save(encoded, filename, io::NO_ENCODING));
242 auto content = this->readFile<std::vector<uint8_t>>();
243 uint8_t expected[] = {0xAA, 0x01, 0xDD};
244 BOOST_CHECK_EQUAL_COLLECTIONS(content.begin(), content.end(),
245 expected, expected + sizeof(expected));
246}
247
248BOOST_AUTO_TEST_CASE(SaveBase64)
249{
250 EncodableType encoded;
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000251 BOOST_CHECK_NO_THROW(io::save(encoded, filename, io::BASE64));
Junxiao Shic1779882016-08-17 01:59:23 +0000252 auto content = this->readFile<std::string>();
253 BOOST_CHECK_EQUAL(content, "qgHd\n"); // printf '\xAA\x01\xDD' | base64
254}
255
256BOOST_AUTO_TEST_CASE(SaveHex)
257{
258 EncodableType encoded;
259 BOOST_CHECK_NO_THROW(io::save(encoded, filename, io::HEX));
260 auto content = this->readFile<std::string>();
261 BOOST_CHECK_EQUAL(content, "AA01DD");
262}
263
264BOOST_AUTO_TEST_CASE(SaveException)
265{
266 EncodableType encoded;
267 encoded.shouldThrow = true;
268 BOOST_CHECK_THROW(io::save(encoded, filename, io::NO_ENCODING), io::Error);
269}
270
271BOOST_AUTO_TEST_CASE(SaveFileNotWritable)
272{
273 this->mkdir();
274 EncodableType encoded;
275 encoded.shouldThrow = true;
276 BOOST_CHECK_THROW(io::save(encoded, filename, io::NO_ENCODING), io::Error);
277}
278
279class IdCertFixture : public IoFixture
280 , public IdentityManagementFixture
281{
282};
283
284BOOST_FIXTURE_TEST_CASE(IdCert, IdCertFixture)
285{
286 Name identity("/TestIo/IdCert");
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700287 identity.appendVersion();
Yingdi Yu3ed09d02014-10-13 16:24:08 -0700288 BOOST_REQUIRE(addIdentity(identity, RsaKeyParams()));
289 Name certName = m_keyChain.getDefaultCertificateNameForIdentity(identity);
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700290 shared_ptr<security::v1::IdentityCertificate> idCert;
Yingdi Yu3ed09d02014-10-13 16:24:08 -0700291 BOOST_REQUIRE_NO_THROW(idCert = m_keyChain.getCertificate(certName));
Yingdi Yuf50098d2014-02-26 14:26:29 -0800292
Junxiao Shic1779882016-08-17 01:59:23 +0000293 io::save(*idCert, filename);
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700294 shared_ptr<security::v1::IdentityCertificate> readCert = io::load<security::v1::IdentityCertificate>(filename);
Yingdi Yuf50098d2014-02-26 14:26:29 -0800295
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000296 BOOST_REQUIRE(readCert != nullptr);
Junxiao Shic1779882016-08-17 01:59:23 +0000297 BOOST_CHECK_EQUAL(idCert->getName(), readCert->getName());
Yingdi Yuf50098d2014-02-26 14:26:29 -0800298}
299
Junxiao Shic1779882016-08-17 01:59:23 +0000300BOOST_AUTO_TEST_SUITE_END() // TestIo
301BOOST_AUTO_TEST_SUITE_END() // Util
Yingdi Yuf50098d2014-02-26 14:26:29 -0800302
Spyridon Mastorakis429634f2015-02-19 17:35:33 -0800303} // namespace tests
Yingdi Yuf50098d2014-02-26 14:26:29 -0800304} // namespace ndn