1 module tagion.testbench.dart.basic_dart_partial_sync;
2 // Default import list for bdd
3 import std.algorithm : each, equal, filter, map, sort;
4 import std.file : mkdirRecurse;
5 import std.format : format;
6 import std.path : buildPath, setExtension;
7 import std.random : MinstdRand0, randomSample, randomShuffle;
8 import std.range;
9 import std.stdio;
10 import std.typecons : Tuple;
11 import tagion.Keywords;
12 import tagion.basic.basic : tempfile;
13 import tagion.behaviour;
14 import tagion.communication.HiRPC;
15 import tagion.crypto.SecureInterfaceNet : HashNet, SecureNet;
16 import tagion.dart.BlockFile : BlockFile;
17 import tagion.dart.DART : DART;
18 import tagion.dart.DARTBasic : DARTIndex, dartIndex;
19 import tagion.dart.DARTFakeNet;
20 import tagion.dart.DARTFile : DARTFile;
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;
26 import tagion.testbench.dart.dartinfo;
27 import tagion.testbench.tools.Environment;
28 import tagion.utils.Random;
29 
30 enum feature = Feature(
31             "DARTSynchronization partial sync.",
32             ["All test in this bdd should use dart fakenet."]);
33 
34 alias FeatureContext = Tuple!(
35         PartialSync, "PartialSync",
36         FeatureGroup*, "result"
37 );
38 
39 @safe @Scenario("Partial sync.",
40         [])
41 class PartialSync {
42     DART db1;
43     DART db2;
44 
45     DARTIndex[] db1_fingerprints;
46     DARTIndex[] db2_fingerprints;
47 
48     const ushort angle = 0;
49     const ushort size = 10;
50 
51     ulong[][] sector_states;
52 
53     DartInfo info;
54 
55     this(DartInfo info) {
56         this.info = info;
57     }
58 
59     @Given("I have a dartfile1 with pseudo random data.")
60     Document randomData() {
61         check(!info.states.empty, "Pseudo random sequence not generated");
62 
63         mkdirRecurse(info.module_path);
64         // create the dartfile
65         DART.create(info.dartfilename, info.net);
66 
67         Exception dart_exception;
68         db1 = 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         sector_states = info.states
72             .map!(state => state.list
73                     .map!(archive => putInSector(archive, angle, size)).array).array;
74 
75         db1_fingerprints = randomAdd(sector_states, MinstdRand0(65), db1);
76 
77         return result_ok;
78     }
79 
80     @Given("I have added some of the pseudo random data to dartfile2.")
81     Document toDartfile2() {
82         DART.create(info.dartfilename2, info.net);
83 
84         Exception dart_exception;
85         db2 = new DART(info.net, info.dartfilename2, dart_exception);
86         check(dart_exception is null, format("Failed to open DART %s", dart_exception.msg));
87 
88         auto partial_sector_states = sector_states.randomSample(sector_states.length / 2, MinstdRand0(423)).array;
89 
90         db2_fingerprints = randomAdd(partial_sector_states, MinstdRand0(314), db2);
91 
92         check(db1.bullseye != db2.bullseye, "Bullseyes should not be the same");
93 
94         return result_ok;
95     }
96 
97     @Given("I synchronize dartfile1 with dartfile2.")
98     Document withDartfile2() {
99         syncDarts(db1, db2, angle, size);
100         return result_ok;
101     }
102 
103     @Then("the bullseyes should be the same.")
104     Document theSame() {
105         check(db1.bullseye == db2.bullseye, "Bullseyes not the same");
106 
107         db1.close();
108         db2.close();
109         return result_ok;
110     }
111 
112 }