1 /// Test for [tagion.services.hirpc_verifier]_ 2 module tagion.testbench.services.hirpc_verifier; 3 // Default import list for bdd 4 import core.time; 5 import std.stdio; 6 import std.typecons : Tuple; 7 import tagion.actor; 8 import tagion.actor.exceptions; 9 import tagion.behaviour; 10 import tagion.communication.HiRPC; 11 import tagion.crypto.SecureNet; 12 import tagion.hibon.Document; 13 import tagion.hibon.HiBON; 14 import tagion.services.hirpc_verifier; 15 import tagion.services.messages; 16 import tagion.testbench.actor.util; 17 import tagion.testbench.tools.Environment; 18 import tagion.utils.pretend_safe_concurrency; 19 20 enum feature = Feature( 21 "HiRPCInterfaceService.", 22 [ 23 "The transaction service should be able to receive HiRPC, validate data format and protocol rules before it sends to and send to the Collector services.", 24 "The HiRPC is package into a HiBON-Document in the following called doc." 25 ]); 26 27 alias FeatureContext = Tuple!( 28 TheDocumentIsNotAHiRPC, "TheDocumentIsNotAHiRPC", 29 CorrectHiRPCFormatAndPermission, "CorrectHiRPCFormatAndPermission", 30 CorrectHiRPCWithPermissionDenied, "CorrectHiRPCWithPermissionDenied", 31 HIRPCWithIllegalMethod, "HIRPCWithIllegalMethod", 32 FeatureGroup*, "result" 33 ); 34 35 @safe @Scenario("The Document is not a HiRPC", 36 []) 37 class TheDocumentIsNotAHiRPC { 38 ActorHandle hirpc_verifier_handle; 39 string hirpc_verifier_success; 40 string hirpc_verifier_reject; 41 this(ActorHandle _hirpc_verifier_handle, string _success, string _reject) { 42 hirpc_verifier_handle = _hirpc_verifier_handle; 43 hirpc_verifier_success = _success; // The name of the service which successfull documents are sent to 44 hirpc_verifier_reject = _reject; // The name of the service which rejected documents are sent to 45 } 46 47 Document doc; 48 49 @Given("a doc with a correct document format but which is incorrect HiRPC format.") 50 Document format() { 51 writeln(thisTid); 52 check(waitforChildren(Ctrl.ALIVE), "hirpc_verifierService never alived"); 53 check(hirpc_verifier_handle.tid !is Tid.init, "hirpc_verifier thread is not running"); 54 55 auto hibon = new HiBON(); 56 hibon["$test"] = 5; 57 doc = Document(hibon); 58 hirpc_verifier_handle.send(inputDoc(), doc); 59 60 return result_ok; 61 } 62 63 @When("the doc should be received by the this services.") 64 Document services() { 65 return result_ok; 66 } 67 68 @Then("the doc should be checked that it is a correct HiRPC and if it is not it should be rejected.") 69 Document rejected() { 70 const receiveTuple = receiveOnlyTimeout!(RejectReason, Document); 71 check(receiveTuple[0] == RejectReason.notAHiRPC, "Did not reject for the correct reason"); 72 check(receiveTuple[1] == doc, "The rejected doc was not the same as was sent"); 73 return result_ok; 74 } 75 76 @But("the doc should not be sent to the Collector Service") 77 Document collectorService() { 78 return result_ok; 79 } 80 81 } 82 83 @safe @Scenario("Correct HiRPC format and permission.", 84 [ 85 "The #permission scenario can be executed with and without correct permission." 86 ]) 87 class CorrectHiRPCFormatAndPermission { 88 ActorHandle hirpc_verifier_handle; 89 string contract_success; 90 string contract_reject; 91 HiRPC hirpc; 92 this(ActorHandle _hirpc_verifier_handle, string _success, string _reject) { 93 hirpc_verifier_handle = _hirpc_verifier_handle; 94 contract_success = _success; // The name of the service which successfull documents are sent to 95 contract_reject = _reject; // The name of the service which rejected documents are sent to 96 hirpc = HiRPC(new HiRPCNet("someObscurePassphrase")); 97 } 98 99 class HiRPCNet : StdSecureNet { 100 this(string passphrase) { 101 super(); 102 generateKeyPair(passphrase); 103 } 104 } 105 106 Document doc; 107 108 @Given("a correctly formatted transaction.") 109 Document transaction() { 110 import std.algorithm : map; 111 import std.array; 112 import std.range : iota; 113 import tagion.basic.Types : Buffer; 114 import tagion.crypto.Types; 115 import tagion.script.TagionCurrency; 116 import tagion.script.common; 117 import tagion.utils.StdTime; 118 119 writeln(thisTid); 120 check(waitforChildren(Ctrl.ALIVE), "ContractService never alived"); 121 check(hirpc_verifier_handle.tid !is Tid.init, "Contract thread is not running"); 122 123 Document[] in_bills; 124 in_bills ~= iota(0, 10).map!(_ => TagionBill(10.TGN, sdt_t.init, Pubkey.init, Buffer.init).toDoc).array; 125 immutable(TagionBill)[] out_bills; 126 out_bills ~= iota(0, 10).map!(_ => TagionBill(5.TGN, sdt_t.init, Pubkey.init, Buffer.init)).array; 127 auto contract = immutable(Contract)(null, null, PayScript(out_bills).toDoc); 128 SignedContract signed_contract = SignedContract(null, contract); 129 130 const sender = hirpc.submit(signed_contract); 131 doc = sender.toDoc; 132 hirpc_verifier_handle.send(inputDoc(), doc); 133 134 return result_ok; 135 } 136 137 // All of these are invisible to the user, 138 // The test specification should be changed to reflect this 139 @When("the doc package has been verified that it is correct Document.") 140 Document document() { 141 return result_ok; 142 } 143 144 @When("the doc package has been verified that it is correct HiRPC.") 145 Document hiRPC() { 146 return result_ok; 147 } 148 149 @Then("the method of HiRPC should be checked that it is \'submit\'.") 150 Document submit() { 151 return result_ok; 152 } 153 154 @Then("the parameter for the send to the Collector service.") 155 Document service() { 156 return result_ok; 157 } 158 159 @Then("if check that the Collector services received the contract.") 160 Document contract() { 161 const receiver = receiveOnlyTimeout!(inputHiRPC, immutable(HiRPC.Receiver))()[1]; 162 check(receiver.method.name == ContractMethods.submit, "The incorrect method name was sent back"); 163 check(receiver.toDoc == doc, "The received sender was not the same as was sent"); 164 165 return result_ok; 166 } 167 } 168 169 @safe @Scenario("Correct HiRPC with permission denied.", 170 []) 171 class CorrectHiRPCWithPermissionDenied { 172 173 ActorHandle hirpc_verifier_handle; 174 string hirpc_verifier_success; 175 string hirpc_verifier_reject; 176 HiRPC bad_hirpc; 177 this(ActorHandle _hirpc_verifier_handle, string _success, string _reject) { 178 hirpc_verifier_handle = _hirpc_verifier_handle; 179 hirpc_verifier_success = _success; // The name of the service which successfull documents are sent to 180 hirpc_verifier_reject = _reject; // The name of the service which rejected documents are sent to 181 bad_hirpc = HiRPC(new BadSecureNet("someLessObscurePassphrase")); 182 } 183 184 Document invalid_doc; 185 @Given("a HiPRC with incorrect permission") 186 Document incorrectPermission() { 187 check(waitforChildren(Ctrl.ALIVE), "hirpc_verifierService never alived"); 188 check(hirpc_verifier_handle.tid !is Tid.init, "hirpc_verifier thread is not running"); 189 auto params = new HiBON; 190 params["test"] = 42; 191 const invalid_sender = bad_hirpc.action(ContractMethods.submit, params); 192 invalid_doc = invalid_sender.toDoc; 193 hirpc_verifier_handle.send(inputDoc(), invalid_doc); 194 return result_ok; 195 } 196 197 @When("do scenario \'#permission\'") 198 Document scenarioPermission() { 199 const receiveTuple = receiveOnlyTimeout!(RejectReason, Document); 200 check(receiveTuple[0] == RejectReason.invalidType, "The docuemnt was not rejected for the correct reason"); 201 check(receiveTuple[1] == invalid_doc, "The rejected doc was not the same as was sent"); 202 203 return result_ok; 204 } 205 206 @Then("check that the contract is not send to the Collector.") 207 Document theCollector() { 208 receiveTimeout( 209 Duration.zero, 210 (inputHiRPC _, HiRPC.Sender __) { check(false, "Should not have received a doc"); }, 211 ); 212 213 return result_ok; 214 } 215 216 } 217 218 @safe @Scenario("A hirpc with an illegal type", []) 219 class HIRPCWithIllegalMethod { 220 ActorHandle hirpc_verifier_handle; 221 string contract_success; 222 string contract_reject; 223 HiRPC hirpc; 224 SecureNet net; 225 this(ActorHandle _hirpc_verifier_handle, string _success, string _reject) { 226 hirpc_verifier_handle = _hirpc_verifier_handle; 227 contract_success = _success; // The name of the service which successfull documents are sent to 228 contract_reject = _reject; // The name of the service which rejected documents are sent to 229 230 net = new HiRPCNet("someObscurePassphrase"); 231 hirpc = HiRPC(net); 232 } 233 234 class HiRPCNet : StdSecureNet { 235 this(string passphrase) { 236 super(); 237 generateKeyPair(passphrase); 238 } 239 } 240 241 Document invalid_doc; 242 243 @Given("i send HiRPC receiver") 244 Document transaction() { 245 import std.algorithm : map; 246 import std.array; 247 import std.range : iota; 248 import tagion.basic.Types : Buffer; 249 import tagion.crypto.Types; 250 import tagion.script.TagionCurrency; 251 import tagion.script.common; 252 import tagion.utils.StdTime; 253 254 writeln(thisTid); 255 check(waitforChildren(Ctrl.ALIVE), "ContractService never alived"); 256 check(hirpc_verifier_handle.tid !is Tid.init, "Contract thread is not running"); 257 258 Document[] in_bills; 259 in_bills ~= iota(0, 10).map!(_ => TagionBill(10.TGN, sdt_t.init, Pubkey.init, Buffer.init).toDoc).array; 260 TagionBill[] out_bills; 261 out_bills ~= iota(0, 10).map!(_ => TagionBill(5.TGN, sdt_t.init, Pubkey.init, Buffer.init)).array; 262 auto contract = Contract(null, null, PayScript(out_bills).toDoc); 263 SignedContract signed_contract = SignedContract(null, contract); 264 265 const sender = hirpc.submit(signed_contract); 266 267 HiRPC.Response message; 268 message.id = sender.method.id; 269 message.result = sender.toDoc; 270 const result = HiRPC.Sender(net, message); 271 invalid_doc = result.toDoc; 272 273 hirpc_verifier_handle.send(inputDoc(), invalid_doc); 274 275 return result_ok; 276 } 277 278 @Then("Then it should be rejected") 279 Document contract() { 280 receiveTimeout( 281 Duration.zero, 282 (inputHiRPC _, HiRPC.Sender __) { check(false, "Should not have received a doc"); }, 283 ); 284 285 const receiveTuple = receiveOnlyTimeout!(RejectReason, Document); 286 check(receiveTuple[0] == RejectReason.invalidType, "The docuemnt was not rejected for the correct reason"); 287 check(receiveTuple[1] == invalid_doc, "The rejected doc was not the same as was sent"); 288 289 hirpc_verifier_handle.send(Sig.STOP); 290 check(waitforChildren(Ctrl.END), "hirpc verifier service Never ended"); 291 292 return result_ok; 293 } 294 }