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