/*
* The MIT License
*
* Copyright 2014 sorrge.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.nyan.dch.communication.simulator;
import org.nyan.dch.communication.simulator.RemoteNode;
import org.nyan.dch.communication.simulator.MeshNetwork;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.Set;
import static org.junit.Assert.*;
import org.junit.Test;
import org.nyan.dch.crypto.SHA256Hash;
import org.nyan.dch.node.IRemoteNode;
import org.nyan.dch.node.Node;
import org.nyan.dch.posts.Post;
import org.nyan.dch.posts.PostData;
import org.nyan.dch.posts.StorageTest;
/**
*
* @author sorrge
*/
public class MeshNetworkTest
{
/**
* Test of network construction
*/
@Test
public void testNetBuilding()
{
final int numNodes = 100;
MeshNetwork net = new MeshNetwork(numNodes, new Random(12), "b", "e", "d");
assert(net.nodes.size() == numNodes);
for(Node n : net.nodes)
{
assert(net.net.get(n).size() >= MeshNetwork.TargetNodeConnections);
for(RemoteNode n1 : net.net.get(n))
{
assert(n1.node != n);
boolean found = false;
for(RemoteNode n2 : net.net.get(n1.node))
if(n2.node == n)
{
found = true;
break;
}
assert(found);
}
}
System.out.printf("Connections per node: %1f\n", net.net.size() / (float)numNodes);
System.out.printf("Messages during network build: %1d\n", net.stats.messagesPassed);
}
/**
* Test propagation of a post
*/
@Test
public void testPostPropagation()
{
final int numNodes = 100;
Random rand = new Random(12);
MeshNetwork net = new MeshNetwork(numNodes, rand, "b", "e", "d");
net.stats.messagesPassed = 0;
Node source = net.nodes.get(rand.nextInt(numNodes));
Post post = new Post(new PostData("b", null, "asdf", "jkl;", new Date()));
source.AddLocalPost(post);
for(Node n : net.nodes)
{
assert(n.storage.Contains(post));
assert(n.storage.GetChan().GetBoard("b").GetThread(post.GetId()).GetPosts().contains(post));
}
System.out.printf("Messages to propagate 1 post: %1d\n", net.stats.messagesPassed);
}
/**
* Test propagation of a thread
*/
@Test
public void testThreadPropagation()
{
final int numNodes = 100;
final int numPosts = 200;
Random rand = new Random(12);
MeshNetwork net = new MeshNetwork(numNodes, rand, "b", "e", "d");
net.stats.messagesPassed = 0;
ArrayList<Post> allPosts = StorageTest.GenerateThread(numPosts, rand, "b", 111);
Post OP = allPosts.get(0);
for(Post p : allPosts)
net.nodes.get(rand.nextInt(numNodes)).AddLocalPost(p);
for(Node n : net.nodes)
{
assert(n.storage.GetChan().GetBoard("b").GetThread(OP.GetId()).GetPosts().size() == numPosts);
for(Post p : allPosts)
{
assert(n.storage.Contains(p));
assert(n.storage.GetChan().GetBoard("b").GetThread(OP.GetId()).GetPosts().contains(p));
}
}
System.out.printf("Messages to propagate %d posts: %d\n", numPosts, net.stats.messagesPassed);
System.out.printf("Messages per post: %f\n", net.stats.messagesPassed / (float)numPosts);
System.out.printf("Messages per post-node: %f\n", net.stats.messagesPassed / (float)numPosts / numNodes);
}
/**
* Test synchronization of a node
*/
@Test
public void testSync()
{
final int numNodes = 100;
final int numPosts = 1000;
Random rand = new Random(12);
String[] boards = new String[] { "b", "e", "d" };
MeshNetwork net = new MeshNetwork(numNodes, rand, boards);
net.stats.messagesPassed = 0;
ArrayList<Post> allPosts = StorageTest.GenerateStream(numPosts, rand, 111, boards);
for(int i = 0; i < numPosts; ++i)
net.nodes.get(rand.nextInt(numNodes)).AddLocalPost(allPosts.get(i));
System.out.printf("Messages to propagate %d posts: %d\n", numPosts, net.stats.messagesPassed);
System.out.printf("Messages per post: %f\n", net.stats.messagesPassed / (float)numPosts);
System.out.printf("Messages per post-node: %f\n", net.stats.messagesPassed / (float)numPosts / numNodes);
Node oldNode = net.nodes.get(0);
Node newNode = net.AddNode(rand);
StorageTest.AssertSynced(newNode.storage, oldNode.storage);
}
/**
* Test propagation of a stream
*/
@Test
public void testStream()
{
final int numNodes = 100;
final int numPosts = 1000;
Random rand = new Random(12);
String[] boards = new String[] { "b", "e", "d" };
MeshNetwork net = new MeshNetwork(numNodes, rand, boards);
net.stats.messagesPassed = 0;
ArrayList<Post> allPosts = StorageTest.GenerateStream(numPosts, rand, 111, boards);
for(int i = 0; i < numPosts; ++i)
net.nodes.get(rand.nextInt(numNodes)).AddLocalPost(allPosts.get(i));
for(int i = 1; i < numNodes; ++i)
StorageTest.AssertSynced(net.nodes.get(0).storage, net.nodes.get(i).storage);
System.out.printf("Messages to propagate %d posts: %d\n", numPosts, net.stats.messagesPassed);
System.out.printf("Messages per post: %f\n", net.stats.messagesPassed / (float)numPosts);
System.out.printf("Messages per post-node: %f\n", net.stats.messagesPassed / (float)numPosts / numNodes);
}
/**
* Test resynchronization of a node
*/
@Test
public void testReSync()
{
final int numNodes = 100;
final int numPosts = 1000;
Random rand = new Random(12);
String[] boards = new String[] { "b", "e", "d" };
MeshNetwork net = new MeshNetwork(numNodes, rand, boards);
net.stats.messagesPassed = 0;
ArrayList<Post> allPosts = StorageTest.GenerateStream(numPosts, rand, 111, boards);
for(int i = 0; i < numPosts; ++i)
net.nodes.get(rand.nextInt(numNodes)).AddLocalPost(allPosts.get(i));
Node n = net.RemoveNode(rand.nextInt(numNodes));
allPosts = StorageTest.GenerateStream(numPosts, rand, 11000, boards);
for(int i = 0; i < numPosts; ++i)
net.nodes.get(rand.nextInt(numNodes - 1)).AddLocalPost(allPosts.get(i));
Node oldNode = net.nodes.get(0);
Set<SHA256Hash> postsOnBoard1 = StorageTest.GatherPosts(n.storage), postsOnBoard2 = StorageTest.GatherPosts(oldNode.storage);
assert(!postsOnBoard1.equals(postsOnBoard2));
net.AddNode(n, rand);
StorageTest.AssertSynced(n.storage, oldNode.storage);
postsOnBoard1 = StorageTest.GatherPosts(n.storage);
assert(postsOnBoard1.equals(postsOnBoard2));
}
/**
* Test synchronization of a split thread
*/
@Test
public void testSyncThread()
{
final int numPosts = 10;
Random rand = new Random(12);
String[] boards = new String[] { "b", "e", "d" };
MeshNetwork net = new MeshNetwork(2, rand, boards);
Node n2 = net.RemoveNode(rand.nextInt(2));
Node n1 = net.nodes.get(0);
ArrayList<Post> allPosts = StorageTest.GenerateThread(numPosts, rand, "b", 111);
n1.AddLocalPost(allPosts.get(0));
for(int i = 1; i < numPosts; ++i)
n2.AddLocalPost(allPosts.get(i));
Set<SHA256Hash> postsOnBoard1 = StorageTest.GatherPosts(n1.storage), postsOnBoard2 = StorageTest.GatherPosts(n2.storage);
assert(!postsOnBoard1.equals(postsOnBoard2));
System.out.printf("Node %s has %d posts\n", n1.toString(), StorageTest.GatherPosts(n1.storage).size());
System.out.printf("Node %s has %d posts\n", n2.toString(), StorageTest.GatherPosts(n2.storage).size());
net.AddNode(n2, rand);
StorageTest.AssertSynced(n1.storage, n2.storage);
}
}