/*
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2005 satoshi akabane(akabane@logical-paradox.org)
 * $Id: NodeTest.java,v 1.2 2005/03/18 13:55:26 rampil Exp $
 */
package org.logical_paradox.testsite.oln.object;

import java.util.Random;

import junit.framework.TestCase;

/**
 * ノードオブジェクトとそれに関連するロジックのテスト
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.2 $
 */
public class NodeTest extends TestCase {

	/**
	 * Constructor for NodeTest.
	 * @param arg0
	 */
	public NodeTest(String arg0) {
		super(arg0);
	}
	/**
	 * ノード同士の比較
	 */
	public void testEquals() {
		assertEquals(new Node(1,0,0), new Node(1,0,0));
		assertEquals(new Node(1,-1,0), new Node(1,-1,0));
		assertEquals(new Node(10000,-1,-1), new Node(10000,-1,-1));
		assertFalse(new Node(10001,-1,-1).equals(new Node(10000,-1,-1)));
		assertFalse(new Node(1,5,0).equals(new Node(1,0,0)));
		assertFalse(new Node(1,0,0).equals(new Node(1,0,5)));
	}
	/**
	 * contains()メソッドのテスト
	 * 指定したノードがノードリストに正しく格納されていることを検出できるかどうか
	 */
	public void testContains() {
		Node node = new Node(0, 100,200);
		Node n1 = new Node(2, 200,300);
		Node n2 = new Node(3,400,500);
		Node n3 = new Node(4,600,700);

		Node f1 = new Node(5,200,999);

		node.add(n1);
		node.add(n2);
		node.add(n3);

		assertTrue(node.contains(n1));
		assertTrue(node.contains(n2));
		assertTrue(node.contains(n3));

		assertFalse(node.contains(f1));

		Node c1 = new Node(2,200,300);
		Node c2 = new Node(999,400,500);

		assertTrue(node.contains(c1));
		assertFalse(node.contains(c2));
	}
	/**
	 * hugのテスト
	 * <li>hugした相手のノードリストに自分のノードが正しく登録されていること</li>
	 * <li>hugした相手のノードが自分のノードリストに正しく登録されていること</li>
	 * を確認する
	 *
	 */
	public void testHug() {
		Node me = new Node(100, 500, 999);
		Node buddy = new Node(256, 512, 1024);

		assertEquals(0, me.getRelativeNodes().size());
		assertEquals(0, buddy.getRelativeNodes().size());

		buddy.hug(me);
		me.add(buddy);

		assertEquals(1, me.getRelativeNodes().size());
		assertEquals(1, buddy.getRelativeNodes().size());
		assertTrue(me.getRelativeNodes().get(0) == buddy);
		assertTrue(buddy.getRelativeNodes().get(0) == me);
	}
	/**
	 * 適当にノードを追加する
	 * 1ノード追加するごとに、最適ノード選択処理を実行する
	 * 例外が発生しなければOK
	 */
	public void testRandomConfigure() {
		Node node = new Node(1, 320, 128);
		Random r = new Random();

		int loopCount = Math.abs(r.nextInt()) % 500 + 500;
		for(int i = 0; i < loopCount; i++) {
			node.add(new Node(100+i, Math.abs(r.nextInt()) % 640, Math.abs(r.nextInt()) % 480));
			node.configure();
		}
	}
	/**
	 * 適当にノードを連結させた状態で、最適ノード選択処理を実行する
	 * 全てのノードについて、自分と同じノードが含まれていなければOK
	 * また，ノード連結時の最適ノード選択処理において、ノードがリンクを保持しなくなった場合はエラーとする
	 */
	public void testConnectivity() {
		Random r = new Random();
		Node[] nodes = new Node[Math.abs(r.nextInt()) % 100 + 100];
		for(int i = 0; i < nodes.length; i++) {
			nodes[i] = new Node(i+1, Math.abs(r.nextInt()) % 640, Math.abs(r.nextInt()) % 480);
		}

		// ランダムに連結させる
		for(int i = 0; i < nodes.length; i++) {
			int loopCount = Math.abs(r.nextInt() % 25 + 5);
			while(loopCount > 0) {
				int nno = Math.abs(r.nextInt()) % nodes.length;
				if(nno == i) {
					continue;					// 自分自身は連結しない
				}
				nodes[i].hug(nodes[nno]);		// hug
				loopCount--;
			}
			// 最適ノード選択処理
			nodes[i].configure();
		}

		// 連結状態の妥当性判定
		for(int i = 0; i < nodes.length; i++) {
			// 自分と同じノードが格納されていないかどうか確認
			assertFalse(nodes[i].contains(nodes[i]));
			// リンク切れが発生しない状況なので、リンク切れも確認する
			assertTrue(nodes.length <= 1 || nodes[i].getRelativeNodes().size() > 0);
		}
	}
}
