blob: fcb1f2bf804142a66985334404b4e7afaa390876 [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 Afanasyev4c9a3d52017-01-03 17:45:19 -08003 * Copyright (c) 2013-2017 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"
Yingdi Yuf50098d2014-02-26 14:26:29 -080023
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070024#include "boost-test.hpp"
Junxiao Shic1779882016-08-17 01:59:23 +000025#include "identity-management-fixture.hpp"
26#include <boost/filesystem.hpp>
27#include <fstream>
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070028
Yingdi Yuf50098d2014-02-26 14:26:29 -080029namespace ndn {
Spyridon Mastorakis429634f2015-02-19 17:35:33 -080030namespace tests {
Yingdi Yuf50098d2014-02-26 14:26:29 -080031
Junxiao Shic1779882016-08-17 01:59:23 +000032class IoFixture
Yingdi Yuf50098d2014-02-26 14:26:29 -080033{
Junxiao Shic1779882016-08-17 01:59:23 +000034protected:
35 IoFixture()
36 : filepath(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) /= "TestIo")
37 , filename(filepath.string())
38 {
39 boost::filesystem::create_directories(filepath.parent_path());
40 }
41
42 ~IoFixture()
43 {
44 boost::system::error_code ec;
45 boost::filesystem::remove(filepath, ec); // ignore error
46 }
47
48 /** \brief create a directory at filename, so that it's neither readable nor writable as a file
49 */
50 void
51 mkdir() const
52 {
53 boost::filesystem::create_directory(filepath);
54 }
55
56 template<typename Container, typename CharT = typename Container::value_type>
57 Container
58 readFile() const
59 {
60 Container container;
61 std::ifstream fs(filename, std::ios_base::binary);
62 char ch;
63 while (fs.get(ch)) {
64 container.push_back(static_cast<CharT>(ch));
65 }
66 return container;
67 }
68
69 template<typename Container, typename CharT = typename Container::value_type>
70 void
71 writeFile(const Container& content) const
72 {
73 std::ofstream fs(filename, std::ios_base::binary);
74 for (CharT ch : content) {
75 fs.put(static_cast<char>(ch));
76 }
77 fs.close();
78 BOOST_REQUIRE_MESSAGE(fs, "error writing file");
79 }
80
81protected:
82 const boost::filesystem::path filepath;
83 const std::string filename;
84};
85
86BOOST_AUTO_TEST_SUITE(Util)
87BOOST_FIXTURE_TEST_SUITE(TestIo, IoFixture)
88
89class EncodableType
90{
91public:
Junxiao Shic1779882016-08-17 01:59:23 +000092 Block
93 wireEncode() const
94 {
95 if (shouldThrow) {
Junxiao Shi435bb552016-09-04 03:14:47 +000096 BOOST_THROW_EXCEPTION(tlv::Error("encode error"));
Junxiao Shic1779882016-08-17 01:59:23 +000097 }
98
99 // block will be 0xAA, 0x01, 0xDD
100 return makeNonNegativeIntegerBlock(0xAA, 0xDD);
101 }
102
103public:
104 bool shouldThrow = false;
105};
106
Junxiao Shi435bb552016-09-04 03:14:47 +0000107template<bool SHOULD_THROW = false>
108class DecodableTypeTpl
Junxiao Shic1779882016-08-17 01:59:23 +0000109{
110public:
Junxiao Shi435bb552016-09-04 03:14:47 +0000111 DecodableTypeTpl() = default;
112
113 explicit
114 DecodableTypeTpl(const Block& block)
Junxiao Shic1779882016-08-17 01:59:23 +0000115 {
Junxiao Shi435bb552016-09-04 03:14:47 +0000116 this->wireDecode(block);
117 }
Junxiao Shic1779882016-08-17 01:59:23 +0000118
119 void
Junxiao Shi435bb552016-09-04 03:14:47 +0000120 wireDecode(const Block& block)
Junxiao Shic1779882016-08-17 01:59:23 +0000121 {
Junxiao Shi435bb552016-09-04 03:14:47 +0000122 if (m_shouldThrow) {
123 BOOST_THROW_EXCEPTION(tlv::Error("decode error"));
Junxiao Shic1779882016-08-17 01:59:23 +0000124 }
125
126 // block must be 0xBB, 0x01, 0xEE
127 BOOST_CHECK_EQUAL(block.type(), 0xBB);
128 BOOST_REQUIRE_EQUAL(block.value_size(), 1);
129 BOOST_CHECK_EQUAL(block.value()[0], 0xEE);
130 }
131
Junxiao Shi435bb552016-09-04 03:14:47 +0000132private:
133 bool m_shouldThrow = SHOULD_THROW;
Junxiao Shic1779882016-08-17 01:59:23 +0000134};
135
Junxiao Shi435bb552016-09-04 03:14:47 +0000136typedef DecodableTypeTpl<false> DecodableType;
137typedef DecodableTypeTpl<true> DecodableTypeThrow;
Junxiao Shic1779882016-08-17 01:59:23 +0000138
139BOOST_AUTO_TEST_CASE(LoadNoEncoding)
140{
141 this->writeFile<std::vector<uint8_t>>({0xBB, 0x01, 0xEE});
142 shared_ptr<DecodableType> decoded = io::load<DecodableType>(filename, io::NO_ENCODING);
143 BOOST_CHECK(decoded != nullptr);
144}
145
146BOOST_AUTO_TEST_CASE(LoadBase64)
147{
148 this->writeFile<std::string>("uwHu\n"); // printf '\xBB\x01\xEE' | base64
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000149 shared_ptr<DecodableType> decoded = io::load<DecodableType>(filename, io::BASE64);
150 BOOST_CHECK(decoded != nullptr);
151}
152
153BOOST_AUTO_TEST_CASE(LoadBase64Newline64)
154{
155 this->writeFile<std::string>(
156 "CEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
157 "AAAAAAAAAAAA\n");
158 // printf '\x08\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
159 // \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
160 // \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
161 // \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | base64
162 shared_ptr<name::Component> decoded = io::load<name::Component>(filename, io::BASE64);
163 BOOST_CHECK(decoded != nullptr);
164}
165
166BOOST_AUTO_TEST_CASE(LoadBase64Newline32)
167{
168 this->writeFile<std::string>(
169 "CEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
170 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
171 "AAAAAAAAAAAA\n");
172 shared_ptr<name::Component> decoded = io::load<name::Component>(filename, io::BASE64);
173 BOOST_CHECK(decoded != nullptr);
174}
175
176BOOST_AUTO_TEST_CASE(LoadBase64NewlineEnd)
177{
178 this->writeFile<std::string>(
179 "CEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n");
180 shared_ptr<name::Component> decoded = io::load<name::Component>(filename, io::BASE64);
181 BOOST_CHECK(decoded != nullptr);
182}
183
184BOOST_AUTO_TEST_CASE(LoadBase64NoNewline)
185{
186 this->writeFile<std::string>(
187 "CEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
188 shared_ptr<name::Component> decoded = io::load<name::Component>(filename, io::BASE64);
Junxiao Shic1779882016-08-17 01:59:23 +0000189 BOOST_CHECK(decoded != nullptr);
190}
191
192BOOST_AUTO_TEST_CASE(LoadHex)
193{
194 this->writeFile<std::string>("BB01EE");
195 shared_ptr<DecodableType> decoded = io::load<DecodableType>(filename, io::HEX);
196 BOOST_CHECK(decoded != nullptr);
197}
198
199BOOST_AUTO_TEST_CASE(LoadException)
200{
201 this->writeFile<std::vector<uint8_t>>({0xBB, 0x01, 0xEE});
202 shared_ptr<DecodableTypeThrow> decoded;
203 BOOST_CHECK_NO_THROW(decoded = io::load<DecodableTypeThrow>(filename, io::NO_ENCODING));
204 BOOST_CHECK(decoded == nullptr);
205}
206
207BOOST_AUTO_TEST_CASE(LoadNotHex)
208{
209 this->writeFile<std::string>("not-hex");
210 shared_ptr<DecodableType> decoded;
211 BOOST_CHECK_NO_THROW(decoded = io::load<DecodableType>(filename, io::HEX));
212 BOOST_CHECK(decoded == nullptr);
213}
214
215BOOST_AUTO_TEST_CASE(LoadFileNotReadable)
216{
Junxiao Shic1779882016-08-17 01:59:23 +0000217 shared_ptr<DecodableType> decoded;
218 BOOST_CHECK_NO_THROW(decoded = io::load<DecodableType>(filename, io::NO_ENCODING));
219 BOOST_CHECK(decoded == nullptr);
220}
221
222BOOST_AUTO_TEST_CASE(SaveNoEncoding)
223{
224 EncodableType encoded;
225 BOOST_CHECK_NO_THROW(io::save(encoded, filename, io::NO_ENCODING));
226 auto content = this->readFile<std::vector<uint8_t>>();
227 uint8_t expected[] = {0xAA, 0x01, 0xDD};
228 BOOST_CHECK_EQUAL_COLLECTIONS(content.begin(), content.end(),
229 expected, expected + sizeof(expected));
230}
231
232BOOST_AUTO_TEST_CASE(SaveBase64)
233{
234 EncodableType encoded;
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000235 BOOST_CHECK_NO_THROW(io::save(encoded, filename, io::BASE64));
Junxiao Shic1779882016-08-17 01:59:23 +0000236 auto content = this->readFile<std::string>();
237 BOOST_CHECK_EQUAL(content, "qgHd\n"); // printf '\xAA\x01\xDD' | base64
238}
239
240BOOST_AUTO_TEST_CASE(SaveHex)
241{
242 EncodableType encoded;
243 BOOST_CHECK_NO_THROW(io::save(encoded, filename, io::HEX));
244 auto content = this->readFile<std::string>();
245 BOOST_CHECK_EQUAL(content, "AA01DD");
246}
247
248BOOST_AUTO_TEST_CASE(SaveException)
249{
250 EncodableType encoded;
251 encoded.shouldThrow = true;
252 BOOST_CHECK_THROW(io::save(encoded, filename, io::NO_ENCODING), io::Error);
253}
254
255BOOST_AUTO_TEST_CASE(SaveFileNotWritable)
256{
257 this->mkdir();
258 EncodableType encoded;
259 encoded.shouldThrow = true;
260 BOOST_CHECK_THROW(io::save(encoded, filename, io::NO_ENCODING), io::Error);
261}
262
263class IdCertFixture : public IoFixture
264 , public IdentityManagementFixture
265{
266};
267
268BOOST_FIXTURE_TEST_CASE(IdCert, IdCertFixture)
269{
270 Name identity("/TestIo/IdCert");
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700271 identity.appendVersion();
Yingdi Yu3ed09d02014-10-13 16:24:08 -0700272 BOOST_REQUIRE(addIdentity(identity, RsaKeyParams()));
273 Name certName = m_keyChain.getDefaultCertificateNameForIdentity(identity);
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700274 shared_ptr<security::v1::IdentityCertificate> idCert;
Yingdi Yu3ed09d02014-10-13 16:24:08 -0700275 BOOST_REQUIRE_NO_THROW(idCert = m_keyChain.getCertificate(certName));
Yingdi Yuf50098d2014-02-26 14:26:29 -0800276
Junxiao Shic1779882016-08-17 01:59:23 +0000277 io::save(*idCert, filename);
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700278 shared_ptr<security::v1::IdentityCertificate> readCert = io::load<security::v1::IdentityCertificate>(filename);
Yingdi Yuf50098d2014-02-26 14:26:29 -0800279
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000280 BOOST_REQUIRE(readCert != nullptr);
Junxiao Shic1779882016-08-17 01:59:23 +0000281 BOOST_CHECK_EQUAL(idCert->getName(), readCert->getName());
Yingdi Yuf50098d2014-02-26 14:26:29 -0800282}
283
Junxiao Shic1779882016-08-17 01:59:23 +0000284BOOST_AUTO_TEST_SUITE_END() // TestIo
285BOOST_AUTO_TEST_SUITE_END() // Util
Yingdi Yuf50098d2014-02-26 14:26:29 -0800286
Spyridon Mastorakis429634f2015-02-19 17:35:33 -0800287} // namespace tests
Yingdi Yuf50098d2014-02-26 14:26:29 -0800288} // namespace ndn