blob: 93a5f77132f07e64247e469c6be32668a743da6a [file] [log] [blame]
Yukai Tu40f184f2017-01-26 09:00:43 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2017, Regents of the University of California.
4 *
5 * This file is part of ChronoShare, a decentralized file sharing application over NDN.
6 *
7 * ChronoShare is free software: you can redistribute it and/or modify it under the terms
8 * of the GNU General Public License as published by the Free Software Foundation, either
9 * version 3 of the License, or (at your option) any later version.
10 *
11 * ChronoShare 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 General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License along with
16 * ChronoShare, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * See AUTHORS.md for complete list of ChronoShare authors and contributors.
19 */
20
21#include "state-server.hpp"
22#include "sync-core.hpp"
23#include "object-manager.hpp"
24#include "action-log.hpp"
25
26#include "test-common.hpp"
27#include <ndn-cxx/util/dummy-client-face.hpp>
28#include <boost/property_tree/ptree.hpp>
29#include <boost/property_tree/json_parser.hpp>
30
31using boost::property_tree::ptree;
32using boost::property_tree::read_json;
33
34namespace ndn {
35namespace chronoshare {
36namespace tests {
37
38namespace fs = boost::filesystem;
39
40_LOG_INIT(Test.StateServer);
41
42class TestStateServerFixture : public IdentityManagementTimeFixture
43{
44public:
45 TestStateServerFixture()
46 //: face(m_io, m_keyChain, {true, true})
47 : localName("/yukai")
48 , tmpdir(fs::unique_path(UNIT_TEST_CONFIG_PATH))
49 , shareFolderName("sharefolder")
50 , root("test-server-and-fetch")
51 , filename("file.txt")
52 , abf(root / filename)
53 , face(m_io, m_keyChain, {true, true})
54 {
55 if (exists(root)) {
56 remove_all(root);
57 }
58
59 syncLog = make_shared<SyncLog>(root, localName);
60
61 std::string words = "this is the test msg";
62
63
64 manager = make_unique<ObjectManager>(face, m_keyChain, root, "test-chronoshare");
65 actionLog = std::make_shared<ActionLog>(face, root, syncLog,
66 "top-secret", name::Component("test-chronoshare"),
67 ActionLog::OnFileAddedOrChangedCallback(),
68 bind([&] { remove(abf); }));
69
70 server = std::make_shared<StateServer>(face, actionLog, root, localName,
71 shareFolderName, name::Component("test-chronoshare"),
72 *manager, m_keyChain, time::seconds(5));
73
74 std::ofstream ofs;
75 ofs.open(abf.string().c_str());
76 ofs << words;
77 ofs.close();
78
79 fileSize = fs::file_size(abf);
80
81 _LOG_DEBUG("absolutePath: " << abf << " localUserName: " << localName);
82 tie(hash, seg_num) = manager->localFileToObjects(abf, localName);
83
84 BOOST_REQUIRE_MESSAGE(fs::exists(abf), " failed to create the file");
85
86 actionLog->AddLocalActionUpdate(filename.generic_string(), *hash,
87 std::time(nullptr), 0644, seg_num);
88
89 actionLog->AddLocalActionUpdate("sharefolder/file.txt",
90 *fromHex("2ff3ab223a23c2435519eef13daabf8576dceffc62618a431715aaf6eea2bf1c"),
91 std::time(nullptr), 0755, 10);
92
93 syncLog->RememberStateInStateLog();
94
95 actionLog->AddLocalActionDelete("file.txt");
96
97 BOOST_REQUIRE_MESSAGE(!fs::exists(abf), " failed to delete the file");
98
99 syncLog->RememberStateInStateLog();
100 }
101
102 ~TestStateServerFixture()
103 {
104 if (exists(root)) {
105 remove_all(root);
106 }
107 }
108
109public:
110 //util::DummyClientFace& face;
111 Name localName;
112 fs::path tmpdir;
113
114 std::string shareFolderName;
115 fs::path root;
116 fs::path filename;
117 fs::path abf;
118
119 util::DummyClientFace face;
120
121 shared_ptr<SyncLog> syncLog;
122 shared_ptr<ActionLog> actionLog;
123 shared_ptr<StateServer> server;
124 unique_ptr<ObjectManager> manager;
125
126 int seg_num;
127 ConstBufferPtr hash;
128
129 uintmax_t fileSize;
130};
131
132BOOST_FIXTURE_TEST_SUITE(TestStateServer, TestStateServerFixture)
133
134BOOST_AUTO_TEST_CASE(TestStateServer)
135{
136 Interest interest1(
137 Name("/localhop").append(localName).append("test-chronoshare").append(shareFolderName)
138 .append("info").append("files").append("folder").appendNumber(0));
139
140 _LOG_DEBUG("interest1:"<<interest1.toUri());
141
142 advanceClocks(time::milliseconds(10), 1000);
143
144 BOOST_CHECK_EQUAL(dynamic_cast<util::DummyClientFace*>(&face)->sentData.size(),1);
145 dynamic_cast<util::DummyClientFace*>(&face)->receive(interest1);
146
147 advanceClocks(time::milliseconds(10), 1000);
148
149 BOOST_CHECK_EQUAL(dynamic_cast<util::DummyClientFace*>(&face)->sentData.size(),2);
150
151 Data data1 = dynamic_cast<util::DummyClientFace*>(&face)->sentData.at(1);
152
153 BOOST_CHECK_EQUAL(data1.getName(),
154 "/localhop/yukai/test-chronoshare/sharefolder/info/files/folder/%00");
155
156 // Read json.
157 ptree pt1;
158 std::istringstream is1(std::string(data1.getContent().value(),
159 data1.getContent().value() + data1.getContent().value_size()));
160 read_json(is1, pt1);
161 for (ptree::value_type &file : pt1.get_child("files"))
162 {
163 BOOST_CHECK_EQUAL(file.second.get<std::string>("filename"), "sharefolder/file.txt");
164 BOOST_CHECK_EQUAL(file.second.get<std::string>("version"), "0");
165 BOOST_CHECK_EQUAL(file.second.get<std::string>("owner.userName"), "/yukai");
166 BOOST_CHECK_EQUAL(file.second.get<std::string>("owner.seqNo"), "2");
167 BOOST_CHECK_EQUAL(file.second.get<std::string>("hash"),
168 "2FF3AB223A23C2435519EEF13DAABF8576DCEFFC62618A431715AAF6EEA2BF1C");
169 BOOST_CHECK_EQUAL(file.second.get<std::string>("chmod"), "0755");
170 BOOST_CHECK_EQUAL(file.second.get<std::string>("segNum"), "10");
171 }
172
173 // <PREFIX_INFO>/"actions"/"folder|file"/<folder|file>/<offset> get list of all actions
174 Interest interest2(
175 Name("/localhop").append(localName).append("test-chronoshare")
176 .append(shareFolderName).append("info").append("actions")
177 .append("file").append("file.txt").appendNumber(0));
178
179 _LOG_DEBUG("interest2:"<<interest2.toUri());
180 dynamic_cast<util::DummyClientFace*>(&face)->receive(interest2);
181
182 advanceClocks(time::milliseconds(10), 1000);
183
184 BOOST_CHECK_EQUAL(dynamic_cast<util::DummyClientFace*>(&face)->sentData.size(),3);
185
186 Data data2 = dynamic_cast<util::DummyClientFace*>(&face)->sentData.at(2);
187
188 BOOST_CHECK_EQUAL(data2.getName(),
189 "/localhop/yukai/test-chronoshare/sharefolder/info/actions/file/file.txt/%00");
190
191 // Read json.
192 ptree pt2;
193 std::istringstream is2(std::string(data2.getContent().value(),
194 data2.getContent().value() + data2.getContent().value_size()));
195 read_json(is2, pt2);
196 for (ptree::value_type &action : pt2.get_child("actions"))
197 {
198 BOOST_CHECK_EQUAL(action.second.get<std::string>("id.userName"), "/yukai");
199 BOOST_CHECK_EQUAL(action.second.get<std::string>("filename"), "file.txt");
200 if(action.second.get<std::string>("version") == "1")
201 {
202 BOOST_CHECK_EQUAL(action.second.get<std::string>("id.seqNo"), "3");
203 BOOST_CHECK_EQUAL(action.second.get<std::string>("version"), "1");
204 BOOST_CHECK_EQUAL(action.second.get<std::string>("action"), "DELETE");
205 }
206 else {
207 BOOST_CHECK_EQUAL(action.second.get<std::string>("id.seqNo"), "1");
208 BOOST_CHECK_EQUAL(action.second.get<std::string>("version"), "0");
209 BOOST_CHECK_EQUAL(action.second.get<std::string>("action"), "UPDATE");
210 BOOST_CHECK_EQUAL(action.second.get<std::string>("update.hash"),
211 "FC0D526AF0BA965EA6BCD5E5BE281B0F5497BBAC2850DFA7C04D31D383E02D0B");
212 BOOST_CHECK_EQUAL(action.second.get<std::string>("update.chmod"), "0644");
213 BOOST_CHECK_EQUAL(action.second.get<std::string>("update.segNum"), "1");
214
215 }
216 }
217
218 Interest interest3(
219 Name("/localhop").append(localName).append("test-chronoshare")
220 .append(shareFolderName).append("info").append("actions")
221 .append("folder").append("sharefolder").appendNumber(0));
222
223 _LOG_DEBUG("interest3:"<<interest3.toUri());
224 dynamic_cast<util::DummyClientFace*>(&face)->receive(interest3);
225
226 advanceClocks(time::milliseconds(10), 1000);
227
228 BOOST_CHECK_EQUAL(dynamic_cast<util::DummyClientFace*>(&face)->sentData.size(),4);
229
230 Data data3 = dynamic_cast<util::DummyClientFace*>(&face)->sentData.at(3);
231
232 BOOST_CHECK_EQUAL(data3.getName(),
233 "/localhop/yukai/test-chronoshare/sharefolder/info/actions/folder/sharefolder/%00");
234
235 ptree pt3;
236 std::istringstream is3(std::string(data3.getContent().value(),
237 data3.getContent().value() + data3.getContent().value_size()));
238 read_json(is3, pt3);
239 //std::cout<<"get files"<<pt2.get<std::string>("files..")<<std::endl;
240 for (ptree::value_type &action : pt3.get_child("actions"))
241 {
242 BOOST_CHECK_EQUAL(action.second.get<std::string>("id.userName"), "/yukai");
243 BOOST_CHECK_EQUAL(action.second.get<std::string>("id.seqNo"), "2");
244 BOOST_CHECK_EQUAL(action.second.get<std::string>("filename"), "sharefolder/file.txt");
245 BOOST_CHECK_EQUAL(action.second.get<std::string>("version"), "0");
246 BOOST_CHECK_EQUAL(action.second.get<std::string>("action"), "UPDATE");
247 BOOST_CHECK_EQUAL(action.second.get<std::string>("update.hash"),
248 "2FF3AB223A23C2435519EEF13DAABF8576DCEFFC62618A431715AAF6EEA2BF1C");
249 BOOST_CHECK_EQUAL(action.second.get<std::string>("update.chmod"), "0755");
250 BOOST_CHECK_EQUAL(action.second.get<std::string>("update.segNum"), "10");
251 }
252
253 Interest interest4(
254 Name("/localhop").append(localName).append("test-chronoshare").append(shareFolderName)
255 .append("cmd").append("restore").append("file").append("file.txt")
256 .appendNumber(0).append(name::Component(hash)));
257
258 dynamic_cast<util::DummyClientFace*>(&face)->receive(interest4);
259
260 advanceClocks(time::milliseconds(10), 1000);
261
262 BOOST_CHECK_EQUAL(dynamic_cast<util::DummyClientFace*>(&face)->sentData.size(),5);
263
264 Data data4 = dynamic_cast<util::DummyClientFace*>(&face)->sentData.at(4);
265
266 _LOG_DEBUG(std::string(data4.getContent().value(),
267 data4.getContent().value()+data4.getContent().value_size()));
268
269 BOOST_REQUIRE_MESSAGE(fs::exists(abf), " failed to restore the file");
270 BOOST_CHECK_EQUAL(fileSize, fs::file_size(abf));
271}
272
273BOOST_AUTO_TEST_SUITE_END()
274
275} // namespace tests
276} // namespace chronoshare
277} // namespace ndn