Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 188 additions & 56 deletions integrationtest/turtleenv/main.d
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -12,103 +12,235 @@

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;

Creates a fake node at the specified address/port.
/// Node instance to test.
private MyNode node;

/// Client instance to use for checking network availability of the node.
private Client client;

/***************************************************************************

Constructor.

Params:
node_item = address/port
node = node to test

***********************************************************************/
***************************************************************************/

override protected TurtleNode createNode ( AddrPort addrport )
public this ( MyNode node )
{
return new TurtleNode(addrport);
this.node = node;
}

/***********************************************************************
/***************************************************************************

Task entry point. Runs a series of tests on the node then shuts down the
scheduler.

***************************************************************************/

public override void run ( )
{
// 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, Const!(Client.Neo.Put.Args) ) { });
if ( !ok )
return false;

void[] value;
ok = client.blocking.get(1, value,
( Client.Neo.Get.Notification, Const!(Client.Neo.Get.Args) ) { });
if ( !ok || value != "hello" )
return false;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (value[] != "hello") 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 )
{
}
}

/***********************************************************************
/*******************************************************************************

Removes all data from the fake node service.
Test node implementing the protocol defined in integrationtest.neo.node.

***********************************************************************/
*******************************************************************************/

public class MyNode : TestNode!(ConnHandler)
{
import swarm.neo.AddrPort;

override public void clear ( )
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);
}

/***********************************************************************
/***************************************************************************

Returns:
identifier string for this node

Suppresses log output from the fake node if used version of proto
supports it.
***************************************************************************/

protected override cstring id ( )
{
return "testnode";
}

/***************************************************************************

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 () {}
}
7 changes: 7 additions & 0 deletions relnotes/stoplistener.deprecation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
### Neo node's `stopListener` method renamed to `stopListeners`

`swarm.node.model.NeoNode`

The `INodeBase` class' `stopListener` method has been renamed to
`stopListeners`, for accuracy (the neo node has three listening sockets).

6 changes: 6 additions & 0 deletions relnotes/turtlenode.deprecation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
### New turtle node env class

`turtle.env.model.Node`

Usage of this class should be replaced with the new `turtle.env.model.TestNode`.

10 changes: 10 additions & 0 deletions src/swarm/node/model/INode.d
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ public interface INode
public void stopListener ( EpollSelectDispatcher epoll );


/***************************************************************************

Restarts all listeners by reconstructing them. Assumed to be called
after the listeners have been shutdown via stopListener().

***************************************************************************/

public void restartListeners ( );


/***************************************************************************

Performs any required shutdown behaviour for the node.
Expand Down
Loading