package jp.ehobby.util.number;

import static org.junit.Assert.*;

import org.junit.Test;

/**
 * NumberUtilitites単体テスト.
 */
@SuppressWarnings("static-method")
public class NumberUtilitiesTest {

	/** テスト用データ(空文字リスト).	*/
	private static final String[] EMPTY_STRING_LIST = {
		"",							// 空文字				//$NON-NLS-1$
		" ",						// 空白文字				//$NON-NLS-1$
		"　",						// 空白文字(全角)		//$NON-NLS-1$
		"_"	,						// アンダーバー			//$NON-NLS-1$
		"＿",						// アンダーバー(全角)	//$NON-NLS-1$
		",",						// カンマ				//$NON-NLS-1$
		"，",						// カンマ(全角)			//$NON-NLS-1$
		" 　 　　  ",				// 空白文字複合			//$NON-NLS-1$
		"_＿_＿＿__",				// アンダーバー複合		//$NON-NLS-1$
		",，,，，,,",				// カンマ複合			//$NON-NLS-1$
		" 　,， __＿，　"			// 総合複合				//$NON-NLS-1$
	};


	/** テスト用データ.	*/
	private static final String[] STRING_NUMBER_LIST = {
		"-__5"	, "－＿＿５＿",		//$NON-NLS-1$//$NON-NLS-2$
		"-4"	, "－４",			//$NON-NLS-1$//$NON-NLS-2$
		"-0x03"	, "－0x03",			//$NON-NLS-1$//$NON-NLS-2$
		"-02"	, "－０２",			//$NON-NLS-1$//$NON-NLS-2$
		"-1"	, "‐０００１",		//$NON-NLS-1$//$NON-NLS-2$
		"0"		, "０",				//$NON-NLS-1$//$NON-NLS-2$
		" 1 "	, "　１",			//$NON-NLS-1$//$NON-NLS-2$
		"_2"	, "＿２",			//$NON-NLS-1$//$NON-NLS-2$
		"3_"	, "３＿",			//$NON-NLS-1$//$NON-NLS-2$
		",4,"	, "，４，",			//$NON-NLS-1$//$NON-NLS-2$
		"05"	, "０５",			//$NON-NLS-1$//$NON-NLS-2$
		"　6＿"	, " ６_",			//$NON-NLS-1$//$NON-NLS-2$
		"+7"	, "＋７",			//$NON-NLS-1$//$NON-NLS-2$
		"_+_8"	, "＿＋８",			//$NON-NLS-1$//$NON-NLS-2$
		"011"	, "０１１",			//$NON-NLS-1$//$NON-NLS-2$
		"0_12"	, "０＿１＿２",		//$NON-NLS-1$//$NON-NLS-2$
		"0x0B"	, "０ＢＨ",			//$NON-NLS-1$//$NON-NLS-2$
		"0x0C"	, "０ＣＨ",			//$NON-NLS-1$//$NON-NLS-2$
		"0b_0000_1101",				//$NON-NLS-1$
		"_０ｂ１１０１",			//$NON-NLS-1$
		"EH"	, "Ｅｈ",			//$NON-NLS-1$//$NON-NLS-2$
		"0x0f"	, "０ｘＦ",			//$NON-NLS-1$//$NON-NLS-2$
		"0b_1111_1111",				//$NON-NLS-1$
		"0x012345678H",				//$NON-NLS-1$
		"0123",						//$NON-NLS-1$
	};

	/** テスト結果確認用データ.	*/
	private static final long[] RESULT_NUMBER_LIST = {
		-5,-5,-4,-4,-3,-3,-2,-2,-1,-1,0,0,
		 1, 1, 2, 2, 3, 3, 4, 4, 5, 5,
		 6, 6, 7, 7, 8, 8, 9, 9,10,10,
		11,11,12,12,13,13,14,14,15,15,
		0xff,
		0x012345678,
		0123
	};


	/**
	 * null 指定.
	 *
	 * @method  longValue(final String)
	 * @process longValue(null) を実行する.
	 * @spec    NullPointerException を throw すること.
	 */
	@Test
	public void testLongValueNull() {
		try {
			NumberUtilities.longValue(null);
			fail();
		} catch (@SuppressWarnings("unused") NullPointerException e) {
			// NOP
		}
	}

	/**
	 * 空文字、空白文字のみで構成された文字列を指定.
	 *
	 * @method  longValue(final String)
	 * @process longValue に空文字、あるいは空白文字のみで構成された文字列を渡す.
	 * @spec    NumberFormatException を throw すること.
	 */
	@Test
	public void testLongValueEmpty() {
		for (String numStr : EMPTY_STRING_LIST) {
			try {
				NumberUtilities.longValue(numStr);
				fail();
			} catch (@SuppressWarnings("unused") NumberFormatException e) {
				// NOP
			}
		}
	}


	/**
	 * 文字列形式数値を指定.
	 *
	 * @method  longValue(final String)
	 * @process longValueに文字列形式文字で構成された文字列を渡す.
	 * @spec    数値に変換されること.
	 */
	@Test
	public void testLongValue() {
		for (int i = 0; i < STRING_NUMBER_LIST.length; i++) {
			String numStr = STRING_NUMBER_LIST[i];
			long result = NumberUtilities.longValue(numStr);
			assertEquals(RESULT_NUMBER_LIST[i], result);
		}
	}


	/**
	 * 当該進数を超える値を指定.
	 *
	 * @method  longValue(final String)
	 * @process longValue に指定進数を超える文字が含まれた文字列を渡す.
	 * @spec    NumberFormatException が throw されること.
	 */
	@Test
	public void testLongValueOver() {
		try {
			NumberUtilities.longValue("0b_1101_2111");	//$NON-NLS-1$
			fail();
		} catch (@SuppressWarnings("unused") NumberFormatException e) {
			// NOP
		}

		try {
			NumberUtilities.longValue("123A");			//$NON-NLS-1$
			fail();
		} catch (@SuppressWarnings("unused") NumberFormatException e) {
			// NOP
		}

		try {
			NumberUtilities.longValue("0128");			//$NON-NLS-1$
			fail();
		} catch (@SuppressWarnings("unused") NumberFormatException e) {
			// NOP
		}

	}


	/**
	 * 文字形式数値変換'0'～'F'.
	 *
	 * @method  charToNumber(final char)
	 * @process charToNumber に文字形式数値 '0'～'F'を渡し実行する.
	 * @spec    数値に変換されること
	 */
	@Test
	public void testCharToNumber0F() {
		String testStr = "0123456789ABCDEF";	//$NON-NLS-1$
		for (int i = 0; i < testStr.length(); i++) {
			char c   = testStr.charAt(i);
			int  val = NumberUtilities.charToNumber(c);
			assertEquals(i, val);
		}
	}

	/**
	 * 文字形式数値変換'0'～'f'.
	 *
	 * @method  charToNumber(final char)
	 * @process charToNumber に文字形式数値 '0'～'f'を渡し実行する.
	 * @spec    数値に変換されること
	 */
	@Test
	public void testCharToNumber0f() {
		String testStr = "0123456789abcdef";	//$NON-NLS-1$
		for (int i = 0; i < testStr.length(); i++) {
			char c   = testStr.charAt(i);
			int  val = NumberUtilities.charToNumber(c);
			assertEquals(i, val);
		}
	}


	/**
	 * 文字形式数値変換'０'～'Ｆ'.
	 *
	 * @method  charToNumber(final char)
	 * @process charToNumber に文字形式数値 '０'～'Ｆ'を渡し実行する.
	 * @spec    数値に変換されること
	 */
	@Test
	public void testCharToNumberZenkaku0F() {
		String testStr = "０１２３４５６７８９ＡＢＣＤＥＦ";	//$NON-NLS-1$
		for (int i = 0; i < testStr.length(); i++) {
			char c   = testStr.charAt(i);
			int  val = NumberUtilities.charToNumber(c);
			assertEquals(i, val);
		}
	}


	/**
	 * 文字形式数値変換'０'～'ｆ'.
	 *
	 * @method  charToNumber(final char)
	 * @process charToNumber に文字形式数値 '０'～'ｆ'を渡し実行する.
	 * @spec    数値に変換されること
	 */
	@Test
	public void testCharToNumberZenkaku0f() {
		String testStr = "０１２３４５６７８９ａｂｃｄｅｆ";	//$NON-NLS-1$
		for (int i = 0; i < testStr.length(); i++) {
			char c   = testStr.charAt(i);
			int  val = NumberUtilities.charToNumber(c);
			assertEquals(i, val);
		}
	}


	/**
	 * 文字形式数値変換数値形式以外文字
	 *
	 * @method  charToNumber(final char)
	 * @process charToNumber に数値形式以外の文字を渡し実行する.
	 * @spec    数値に変換されること
	 */
	@Test
	public void testCharToNumberInvalidChar() {
		String testStr = " _,一①";								//$NON-NLS-1$
		for (int i = 0; i < testStr.length(); i++) {
			char c   = testStr.charAt(i);
			int  val = NumberUtilities.charToNumber(c);
			assertEquals(-1, val);
		}
	}
}
