From c159506d1ae3c307acdf951f7b26d0b465886254 Mon Sep 17 00:00:00 2001 From: Gavin Norman Date: Tue, 14 Aug 2018 11:28:28 +0200 Subject: [PATCH] Adapt the turtle env node test to use the new TestNode --- integrationtest/turtleenv/main.d | 251 ++++++++++++++++++++++++------- 1 file changed, 197 insertions(+), 54 deletions(-) diff --git a/integrationtest/turtleenv/main.d b/integrationtest/turtleenv/main.d index ca7c38d3..45d9f295 100644 --- a/integrationtest/turtleenv/main.d +++ b/integrationtest/turtleenv/main.d @@ -1,6 +1,6 @@ /******************************************************************************* - Test of the abstract turtle node extension. + Test of the turtle swarm node extension. Copyright: Copyright (c) 2018 dunnhumby Germany GmbH. All rights reserved. @@ -12,103 +12,246 @@ module integrationtest.turtleenv.main; -import swarm.neo.AddrPort; -import turtle.env.model.Node; +import ocean.transition; +import ocean.task.Scheduler; +import ocean.task.Task; import ocean.util.test.DirectorySandbox; -import ocean.core.Test; -import ocean.io.device.File; +import swarm.Const : ICommandCodes, NodeItem; +import swarm.node.connection.ConnectionHandler; +import turtle.env.model.TestNode; -/// Node used to the turtle test -private class TurtleNode +version (UnitTest){} +else +void main() { - /// Address and the port of the node - AddrPort addrport; - AddrPort neo_address; + auto sandbox = DirectorySandbox.create(); + scope (success) + sandbox.remove(); - this (AddrPort addrport) - { - this.addrport = addrport; - this.neo_address = AddrPort(this.addrport.address()); - this.neo_address.port = cast(ushort)(this.addrport.port() + 100); - } + initScheduler(Scheduler.Configuration.init); + + auto node = new MyNode("127.0.0.1", 10000); + node.start(); + + theScheduler.schedule(new Tests(node)); + theScheduler.eventLoop(); } -/// The turlte TurtleNode class -private class TestNode : Node!(TurtleNode, "turtleNode") +/******************************************************************************* + + Task that performs tests on the test node passed to the ctor. + +*******************************************************************************/ + +class Tests : Task { - /*********************************************************************** + import integrationtest.neo.client.Client; + import ocean.core.Test; + import ocean.io.device.File; + + /// Node instance to test. + private MyNode node; + + /// Client instance to use for checking network availability of the node. + private Client client; - Creates a fake node at the specified address/port. + /*************************************************************************** + + Constructor. Params: - node_item = address/port + node = node to test + + ***************************************************************************/ + + public this ( MyNode node ) + { + this.node = node; + } + + /*************************************************************************** - ***********************************************************************/ + Task entry point. Runs a series of tests on the node then shuts down the + scheduler. - override protected TurtleNode createNode ( AddrPort addrport ) + ***************************************************************************/ + + public override void run ( ) { - return new TurtleNode(addrport); + // Test config file generation. + this.node.genConfigFiles("."); + test!("==")(File.get("testnode.nodes"), "127.0.0.1:9999\n"); + test!("==")(File.get("testnode.neo.nodes"), "127.0.0.1:10000\n"); + + // Initialise client and connect. + this.client = new Client(theScheduler.epoll, "127.0.0.1", 10000, + &this.connNotifier); + client.blocking.waitAllNodesConnected(); + + // Try to talk to the node. + auto ok = this.talkToNode(); + test(ok); + + // Stop the node, then try to talk to it (failure expected). + this.node.stop(); + ok = this.talkToNode(); + test(!ok); + + // Restart the node, reconnect the client, then try to talk to the node. + this.node.restart(); + client.blocking.waitAllNodesConnected(); + ok = this.talkToNode(); + test(ok); + + // Finished. + theScheduler.shutdown(); } - /*********************************************************************** + /*************************************************************************** + + Uses the client to put a record to the node, then read it back. Returns: - address/port on which node is listening + true if everything succeeded, false on error - ***********************************************************************/ + ***************************************************************************/ - override public AddrPort node_addrport ( ) + private bool talkToNode ( ) { - assert(this.node); - return this.node.addrport; + auto ok = client.blocking.put(1, "hello", + ( Client.Neo.Put.Notification, Client.Neo.Put.Args ) { }); + if ( !ok ) + return false; + + void[] value; + ok = client.blocking.get(1, value, + ( Client.Neo.Get.Notification, Client.Neo.Get.Args ) { }); + if ( !ok ) + return false; + + return true; } - /*********************************************************************** + /*************************************************************************** - Fake node service stop implementation. + Dummy connection notifier. Required by the client, but unused. - ***********************************************************************/ + ***************************************************************************/ - protected override void stopImpl ( ) + private void connNotifier ( Client.Neo.ConnNotification info ) { } +} + +/******************************************************************************* + + Test node implementing the protocol defined in integrationtest.neo.node. + +*******************************************************************************/ + +public class MyNode : TestNode!(ConnHandler) +{ + import swarm.neo.AddrPort; - /*********************************************************************** + import integrationtest.neo.node.Node; + import integrationtest.neo.node.Storage; + import integrationtest.neo.node.request.Get; + import integrationtest.neo.node.request.Put; + + /*************************************************************************** + + Constructor. + + Params: + addr = address to bind to + neo_port = port to bind to for neo protocol (legacy protocol binds + to a port one lower) + + ***************************************************************************/ + + public this ( cstring addr, ushort neo_port ) + { + // In this simple example node implementation, we don't need any shared + // resources except the reference to the storage. + this.shared_resources = new Storage; + + Options options; + options.epoll = theScheduler.epoll; + options.requests.addHandler!(GetImpl_v0)(); + options.credentials_map["dummy"] = Key.init; + options.shared_resources = this.shared_resources; + + options.requests.addHandler!(GetImpl_v0)(); + options.requests.addHandler!(PutImpl_v0)(); + + const backlog = 1_000; + AddrPort legacy_addr_port; + legacy_addr_port.setAddress(addr); + legacy_addr_port.port = cast(ushort)(neo_port - 1); + super(legacy_addr_port, neo_port, new ConnectionSetupParams, + options, backlog); + } + + /*************************************************************************** Removes all data from the fake node service. - ***********************************************************************/ + ***************************************************************************/ override public void clear ( ) { + // Unused in this test. + } + + /*************************************************************************** + + Returns: + identifier string for this node + + ***************************************************************************/ + + protected override cstring id ( ) + { + return "testnode"; } - /*********************************************************************** + /*************************************************************************** - Suppresses log output from the fake node if used version of proto - supports it. + Scope allocates a request resource acquirer backed by the protected + `shared_resources`. (Passed as a generic Object to avoid templatising + this class and others that depend on it.) - ***********************************************************************/ + Params: + handle_request_dg = delegate that receives a resources acquirer and + initiates handling of a request + + ***************************************************************************/ - override public void log_errors ( bool log_errors ) + override protected void getResourceAcquirer ( + void delegate ( Object resource_acquirer ) handle_request_dg ) { - static if (is(typeof(this.node.log_errors(log_errors)))) - this.node.log_errors(log_errors); + handle_request_dg(this.shared_resources); } } -version (UnitTest){} -else -void main() +/******************************************************************************* + + Legacy protocol connection handler. Required by NodeBase but unused in this + example. + +*******************************************************************************/ + +private class ConnHandler : ConnectionHandlerTemplate!(ICommandCodes) { - auto sandbox = DirectorySandbox.create(); - scope (success) - sandbox.remove(); + import ocean.net.server.connection.IConnectionHandler; + + public this ( void delegate(IConnectionHandler) finaliser, + ConnectionSetupParams params ) + { + super(finaliser, params); + } - auto node = new TestNode(); - node.start("127.0.0.1", 10000); - node.genConfigFiles("."); + override protected void handleCommand () {} - test!("==")(File.get("turtleNode.nodes"), "127.0.0.1:10000\n"); - test!("==")(File.get("turtleNode.neo.nodes"), "127.0.0.1:10100\n"); + override protected void handleNone () {} }