1 module tagion.testbench.dart.dart_mapping_two_archives;
2 // Default import list for bdd
3 import std.algorithm : filter, map;
4 import std.file : mkdirRecurse;
5 import std.format : format;
6 import std.path : buildPath, setExtension;
7 import std.range;
8 import std.stdio : writefln;
9 import std.typecons : Tuple;
10 import tagion.Keywords;
11 import tagion.basic.Types : Buffer, mut;
12 import tagion.basic.basic : forceRemove;
13 import tagion.behaviour;
14 import tagion.communication.HiRPC;
15 import tagion.crypto.SecureInterfaceNet : HashNet, SecureNet;
16 import tagion.crypto.Types : Fingerprint;
17 import tagion.dart.DART : DART;
18 import tagion.dart.DARTBasic : DARTIndex, binaryHash, dartIndex;
19 import tagion.dart.DARTFakeNet;
20 import tagion.dart.DARTFile : DARTFile;
21 import tagion.dart.DARTRim;
22 import tagion.dart.DARTcrud : dartRead, dartRim;
23 import tagion.dart.Recorder : Archive, RecordFactory;
24 import tagion.hibon.Document;
25 import tagion.hibon.HiBONJSON : toPretty;
26 import tagion.hibon.HiBONRecord;
27 import tagion.testbench.dart.dart_helper_functions : getFingerprints, getRead, getRim, goToSplit;
28 import tagion.testbench.dart.dartinfo;
29 import tagion.testbench.tools.Environment;
30 
31 enum feature = Feature(
32             "Dart mapping of two archives",
33             ["All test in this bdd should use dart fakenet."]);
34 
35 alias FeatureContext = Tuple!(
36         AddOneArchive, "AddOneArchive",
37         AddAnotherArchive, "AddAnotherArchive",
38         RemoveArchive, "RemoveArchive",
39         FeatureGroup*, "result"
40 );
41 
42 Fingerprint[] fingerprints;
43 DARTIndex[] dart_indices;
44 
45 @safe @Scenario("Add one archive.",
46         ["mark #one_archive"])
47 class AddOneArchive {
48     DART db;
49 
50     DARTIndex doc_dart_index;
51     Fingerprint doc_fingerprint;
52     Fingerprint bullseye;
53     const DartInfo info;
54 
55     this(const DartInfo info) {
56         this.info = info;
57     }
58 
59     @Given("I have a dartfile.")
60     Document dartfile() {
61         // create the directory to store the DART in.
62         mkdirRecurse(info.module_path);
63         // create the dartfile
64         info.dartfilename.forceRemove;
65         DART.create(info.dartfilename, info.net);
66 
67         Exception dart_exception;
68         db = new DART(info.net, info.dartfilename, dart_exception);
69         check(dart_exception is null, format("Failed to open DART %s", dart_exception.msg));
70 
71         return result_ok;
72     }
73 
74     @Given("I add one archive1 in sector A.")
75     Document a() {
76         auto recorder = db.recorder();
77         const doc = DARTFakeNet.fake_doc(info.table[0]);
78         recorder.add(doc);
79         doc_dart_index = recorder[].front.dart_index.mut;
80         doc_fingerprint = recorder[].front.fingerprint.mut;
81         bullseye = db.modify(recorder);
82         return result_ok;
83     }
84 
85     @Then("the archive should be read and checked.")
86     Document checked() {
87         check(doc_fingerprint == bullseye, "fingerprint and bullseyes not the same");
88         fingerprints ~= doc_fingerprint;
89         dart_indices ~= doc_dart_index;
90         db.close();
91         return result_ok;
92     }
93 }
94 
95 @safe @Scenario("Add another archive.",
96         ["mark #two_archives"])
97 class AddAnotherArchive {
98 
99     DART db;
100     // Fingerprint doc_fingerprint;
101     DARTIndex doc_dart_index;
102     Fingerprint doc_fingerprint;
103     Fingerprint bullseye;
104 
105     const DartInfo info;
106     this(const DartInfo info) {
107         this.info = info;
108     }
109 
110     @Given("#one_archive")
111     Document onearchive() {
112         Exception dart_exception;
113         db = new DART(info.net, info.dartfilename, dart_exception);
114         check(dart_exception is null, format("Failed to open DART %s", dart_exception.msg));
115 
116         const bullseye = db.bullseye();
117         const doc = DARTFakeNet.fake_doc(info.table[0]);
118         const doc_bullseye = dartIndex(info.net, doc);
119         check(bullseye == doc_bullseye, "Bullseye not equal to doc");
120 
121         return result_ok;
122     }
123 
124     @Given("i add another archive2 in sector A.")
125     Document inSectorA() {
126         auto recorder = db.recorder();
127         const doc = DARTFakeNet.fake_doc(info.table[1]);
128         recorder.add(doc);
129         doc_dart_index = recorder[].front.dart_index.mut;
130         doc_fingerprint = recorder[].front.fingerprint.mut;
131         bullseye = db.modify(recorder);
132 
133         check(doc_fingerprint != bullseye, "Bullseye not updated");
134 
135         fingerprints ~= doc_fingerprint;
136         dart_indices ~= doc_dart_index;
137         return result_ok;
138 
139     }
140 
141     @Then("both archives should be read and checked.")
142     Document readAndChecked() {
143 
144         const doc = getRead(dart_indices, info.hirpc, db);
145 
146         const recorder = db.recorder(doc);
147 
148         foreach (i, data; recorder[].enumerate) {
149             const(ulong) archive = data.filed[info.FAKE].get!ulong;
150             check(archive == info.table[i], "Retrieved data not the same");
151         }
152 
153         return result_ok;
154     }
155 
156     @Then("check the branch of sector A.")
157     Document ofSectorA() {
158 
159         const doc = goToSplit(Rims.root, info.hirpc, db);
160         const DARTIndex[] rim_fingerprints = getFingerprints(doc);
161 
162         const read_doc = getRead(rim_fingerprints, info.hirpc, db);
163 
164         const recorder = db.recorder(read_doc);
165 
166         foreach (i, data; recorder[].enumerate) {
167             const(ulong) archive = data.filed[info.FAKE].get!ulong;
168             check(archive == info.table[i], "Retrieved data not the same");
169         }
170         return result_ok;
171     }
172 
173     @Then("check the bullseye.")
174     Document checkTheBullseye() {
175         check(bullseye == binaryHash(info.net, fingerprints[0], fingerprints[1]),
176         "Bullseye not equal to the hash of the two archives");
177         db.close();
178         return result_ok;
179     }
180 }
181 
182 @safe @Scenario("Remove archive", [])
183 class RemoveArchive {
184     DART db;
185 
186     DARTIndex doc_fingerprint;
187     Fingerprint bullseye;
188 
189     const DartInfo info;
190 
191     this(const DartInfo info) {
192         this.info = info;
193     }
194 
195     @Given("#two_archives")
196     Document twoarchives() {
197         Exception dart_exception;
198         db = new DART(info.net, info.dartfilename, dart_exception);
199         check(dart_exception is null, format("Failed to open DART %s", dart_exception.msg));
200 
201         return result_ok;
202     }
203 
204     @Given("i remove archive1.")
205     Document archive1() {
206         auto recorder = db.recorder();
207         recorder.remove(dart_indices[0]);
208         bullseye = db.modify(recorder);
209         return result_ok;
210     }
211 
212     @Then("check that archive2 has been moved from the branch in sector A.")
213     Document a() {
214 
215         const doc = goToSplit(Rims.root, info.hirpc, db);
216         const DARTIndex[] rim_fingerprints = getFingerprints(doc, db);
217 
218         const read_doc = getRead(rim_fingerprints, info.hirpc, db);
219         const recorder = db.recorder(read_doc);
220 
221         check(recorder[].walkLength == 1, "fingerprint not removed");
222         auto data = recorder[].front;
223         const(ulong) archive = data.filed[info.FAKE].get!ulong;
224         check(archive == info.table[1], "Data is not correct");
225 
226         return result_ok;
227     }
228 
229     @Then("check the bullseye.")
230     Document _bullseye() {
231         check(bullseye == fingerprints[1], "Bullseye not updated correctly. Not equal to other element");
232         db.close();
233         return result_ok;
234     }
235 
236 }