1 module tagion.testbench.dart.dart_pseudo_random;
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.basic.basic : forceRemove;
12 import tagion.behaviour;
13 import tagion.communication.HiRPC;
14 import tagion.crypto.SecureInterfaceNet : HashNet, SecureNet;
15 import tagion.dart.DART : DART;
16 import tagion.dart.DARTBasic : DARTIndex, dartIndex;
17 import tagion.dart.DARTFakeNet;
18 import tagion.dart.DARTFile : DARTFile;
19 import tagion.dart.Recorder : Archive, RecordFactory;
20 import tagion.hibon.Document;
21 import tagion.hibon.HiBONJSON : toPretty;
22 import tagion.hibon.HiBONRecord;
23 import tagion.testbench.dart.dart_helper_functions;
24 import tagion.testbench.dart.dartinfo;
25 import tagion.testbench.tools.Environment;
26 import tagion.utils.Random;
27 
28 enum feature = Feature(
29             "Dart pseudo random test",
30             ["All test in this bdd should use dart fakenet."]);
31 
32 alias FeatureContext = Tuple!(
33         AddPseudoRandomData, "AddPseudoRandomData",
34         RemovePseudoRandomData, "RemovePseudoRandomData",
35         FeatureGroup*, "result"
36 );
37 
38 DARTIndex[] db1_fingerprints;
39 DARTIndex[] db2_fingerprints;
40 
41 @safe @Scenario("Add pseudo random data.",
42         [])
43 class AddPseudoRandomData {
44     DART db1;
45     DART db2;
46 
47     DartInfo info;
48 
49     this(DartInfo info) {
50         this.info = info;
51     }
52 
53     @Given("I have two dartfiles.")
54     Document dartfiles() {
55         // create the directory to store the DART in.
56         mkdirRecurse(info.module_path);
57         // create the dartfile
58         info.dartfilename.forceRemove;
59         info.dartfilename2.forceRemove;
60         DART.create(info.dartfilename, info.net);
61         DART.create(info.dartfilename2, info.net);
62 
63         Exception dart_exception;
64         db1 = new DART(info.net, info.dartfilename, dart_exception);
65         check(dart_exception is null, format("Failed to open DART %s", dart_exception.msg));
66         db2 = new DART(info.net, info.dartfilename2, dart_exception);
67         check(dart_exception is null, format("Failed to open DART %s", dart_exception.msg));
68 
69         return result_ok;
70     }
71 
72     @Given("I have a pseudo random sequence of data stored in a table with a seed.")
73     Document seed() {
74         check(!info.states.empty, "Pseudo random sequence not generated");
75         return result_ok;
76     }
77 
78     @When("I randomly add all the data stored in the table to the two darts.")
79     Document darts() {
80         // shufflerandom seems to be modifying and saving the state. Research tommorow.
81 
82         // writefln("%s", typeof(info.states));
83 
84         db1_fingerprints = randomAdd(info.states, MinstdRand0(40), db1);
85         db2_fingerprints = randomAdd(info.states, MinstdRand0(42), db2);
86 
87         return result_ok;
88 
89     }
90 
91     @Then("the bullseyes of the two darts should be the same.")
92     Document same() {
93 
94         check(db1.bullseye == db2.bullseye, "Bullseyes not the same");
95         check(equal(db1_fingerprints.sort, db2_fingerprints.sort), "Fingerprints not the same");
96         db1.close();
97         db2.close();
98         return result_ok;
99     }
100 
101 }
102 
103 @safe @Scenario("Remove pseudo random data.",
104         [])
105 class RemovePseudoRandomData {
106     DART db1;
107     DART db2;
108     DartInfo info;
109     DARTIndex[] remove_fingerprints;
110 
111     this(DartInfo info) {
112         this.info = info;
113     }
114 
115     @Given("two pseudo random darts and fingerprints")
116     Document fingerprints() {
117         Exception dart_exception;
118         db1 = new DART(info.net, info.dartfilename, dart_exception);
119         check(dart_exception is null, format("Failed to open DART %s", dart_exception.msg));
120         db2 = new DART(info.net, info.dartfilename2, dart_exception);
121         check(dart_exception is null, format("Failed to open DART %s", dart_exception.msg));
122 
123         // since the finger
124         remove_fingerprints = db1_fingerprints.randomSample(db1_fingerprints.length / 2, MinstdRand0(40)).array;
125         return result_ok;
126     }
127 
128     @When("i randomly go through n fingerprints and remove them from both darts.")
129     Document darts() {
130 
131         randomRemove(remove_fingerprints, MinstdRand0(100), db1);
132         randomRemove(remove_fingerprints, MinstdRand0(32), db2);
133 
134         return result_ok;
135     }
136 
137     @Then("the bullseyes of the two darts should be the same.")
138     Document same() {
139         check(db1.bullseye == db2.bullseye, "Bullseyes not the same");
140 
141         db1.close();
142         db2.close();
143         return result_ok;
144     }
145 
146 }