/*
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2005 satoshi akabane(akabane@logical-paradox.org)
 * $Id: DomainConnectionProviderTest.java,v 1.2 2005/09/07 13:38:06 rampil Exp $
 */
package org.logical_paradox.vsan.dfs;

import java.util.ResourceBundle;

import org.logical_paradox.vsan.domain.Domain;
import org.logical_paradox.vsan.domain.exception.DomainAccessException;
import org.logical_paradox.vsan.node.DiskArrayNode;

import junit.framework.TestCase;

/**
 * ドメイン接続プロバイダーのテスト
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.2 $
 */
public class DomainConnectionProviderTest extends TestCase {
	/** テスト用のコンフィグレーション */
	private DfsConfig config = null;
	/** テスト用のドメイン情報 */
	private Domain domain = null;

	/**
	 * Constructor for DomainConnectionProviderTest.
	 * @param arg0
	 */
	public DomainConnectionProviderTest(String arg0) {
		super(arg0);
	}

	/**
	 * 新しいドメイン接続を確立するテスト
	 * 期待結果；新しい接続インスタンスが返却される。
	 */
	public void testGetNewDomainConnection() throws DomainAccessException {
		DomainConnectionProvider dcp = new DomainConnectionProviderMoc(config, domain);

		assertEquals(0, dcp.size());

		DomainConnection con = dcp.getConnection("node01");
		assertEquals(1, con.getSharedNum());
		assertEquals(1, dcp.size());
	}

	/**
	 * ドメイン接続のリサイクルに関するテスト
	 * 期待結果：同じインスタンスが返る
	 * @throws DomainAccessException
	 */
	public void testRecycleDomainConnection() throws DomainAccessException {
		DomainConnectionProvider dcp = new DomainConnectionProviderMoc(config, domain);

		assertEquals(0, dcp.size());

		// 接続1
		DomainConnection con1 = dcp.getConnection("node01");
		assertEquals(1, con1.getSharedNum());
		assertEquals(1, dcp.size());

		// 接続2
		DomainConnection con2 = dcp.getConnection("node02");
		assertEquals(1, con2.getSharedNum());
		assertEquals(2, dcp.size());

		// 接続3
		DomainConnection con3 = dcp.getConnection("node03");
		assertEquals(2, con3.getSharedNum());
		assertEquals(2, con1.getSharedNum());
		assertEquals(2, dcp.size());

		assertSame(con1, con3);
		assertFalse(con3 == con2);
	}

	/**
	 * ドメイン接続数の限界超越テスト
	 * 期待結果：例外が発生する
	 * @throws DomainConnection
	 */
	public void testOverConnectionLimit() throws DomainAccessException {
		DomainConnectionProvider dcp = new DomainConnectionProviderMoc(config, domain);

		DomainConnection con = null;
		// 10セッションまではOK(2接続を5セッションで共有)
		for(int i = 0; i < 10; i++) {
			con = dcp.getConnection("node" + i);
		}

		try {
			// 11セッション目はダメ
			dcp.getConnection("overflowconnection");
			fail();
		} catch(DomainAccessException e) {
			// OK
		}
	}

	// テスト用のモック
	class DomainConnectionProviderMoc extends DomainConnectionProvider {
		/**
		 * @param cfg
		 * @param d
		 */
		public DomainConnectionProviderMoc(DfsConfig cfg, Domain d) {
			super(cfg, d);
		}
		// 適当なドメイン接続を返す
		protected DomainConnection newConnection(String clientNodeId)
			throws DomainAccessException {

			return new DomainConnectionMoc(clientNodeId, getDomain());
		}

		public int size() {
			return super.size();
		}

	}
	class DomainConnectionMoc extends DomainConnection {
		/**
		 * @param nodeId
		 * @param dm
		 * @throws DomainAccessException
		 */
		public DomainConnectionMoc(String nodeId, Domain dm) throws DomainAccessException {
			super(nodeId, dm);
		}
		// DACに接続したふりをする
		protected void connect() throws DomainAccessException {
		}

	}
	protected void setUp() throws Exception {
		// テスト用のリソースを読み込む
		config = new DfsConfig(ResourceBundle.getBundle("dfs_test"));

		// テスト用のドメイン情報を作成する
		domain = new Domain("domain01", new DiskArrayNode[]{
			new DiskArrayNode("n001"), new DiskArrayNode("n002"), new DiskArrayNode("n003")
			}
		);
	}

}
