/*
 * Copyright 2009-2010 Yuichiro Moriguchi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.morilib.regex;

import net.morilib.automata.NFA;
import net.morilib.automata.NFAState;
import net.morilib.automata.nfa.GenericNFAMatcher;
import net.morilib.regex.dfa.RegexParser;
import junit.framework.TestCase;

/**
 *
 *
 * @author MORIGUCHI, Yuichiro 2013/10/20
 */
public class RegexParserTest extends TestCase {

	public void test0001() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("a");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("a"));
		assertFalse(m.match("ab"));
	}

	public void test0002() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("abc");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("abc"));
		assertFalse(m.match("ab"));
		assertFalse(m.match("abcd"));
	}

	public void test0003() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("a|c");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("a"));
		assertTrue(m.match("c"));
		assertFalse(m.match("ac"));
	}

	public void test0004() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("ab|cd");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("ab"));
		assertTrue(m.match("cd"));
		assertFalse(m.match("abcd"));
	}

	public void test0005() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("a*");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match(""));
		assertTrue(m.match("a"));
		assertTrue(m.match("aaaa"));
		assertFalse(m.match("ab"));
	}

	public void test0006() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("a+");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("a"));
		assertTrue(m.match("aaaa"));
		assertFalse(m.match(""));
		assertFalse(m.match("ab"));
	}

	public void test0007() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("a?");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match(""));
		assertTrue(m.match("a"));
		assertFalse(m.match("aa"));
		assertFalse(m.match("ab"));
	}

	public void test0008() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("(ab)*");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match(""));
		assertTrue(m.match("ab"));
		assertTrue(m.match("abab"));
		assertFalse(m.match("aba"));
	}

	public void test0009() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("(ab)+");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("ab"));
		assertTrue(m.match("abab"));
		assertFalse(m.match(""));
		assertFalse(m.match("aba"));
	}

	public void test0010() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("(ab)?");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match(""));
		assertTrue(m.match("ab"));
		assertFalse(m.match("abab"));
		assertFalse(m.match("aba"));
	}

	public void test0011() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("a(b|c)*d");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("ad"));
		assertTrue(m.match("abd"));
		assertTrue(m.match("acd"));
		assertTrue(m.match("abcd"));
		assertTrue(m.match("abcbd"));
		assertFalse(m.match("azd"));
	}

	public void test0012() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("ab|cd|ef");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("ab"));
		assertTrue(m.match("cd"));
		assertTrue(m.match("ef"));
		assertFalse(m.match("abcd"));
	}

	public void test0013() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("a(b|c|d)*d");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("ad"));
		assertTrue(m.match("abd"));
		assertTrue(m.match("acd"));
		assertTrue(m.match("add"));
		assertTrue(m.match("abcd"));
		assertTrue(m.match("abcbd"));
		assertTrue(m.match("abcdbd"));
		assertFalse(m.match("azd"));
	}

	public void test0021() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("[a-zA-Z]*");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match(""));
		assertTrue(m.match("a"));
		assertTrue(m.match("abCd"));
		assertFalse(m.match("a9"));
	}

	public void test0022() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("[a-z&[^g]C]*");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match(""));
		assertTrue(m.match("a"));
		assertTrue(m.match("afhz"));
		assertFalse(m.match("g"));
		assertFalse(m.match("C"));
	}

	public void test0031() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("a{2,4}");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("aa"));
		assertTrue(m.match("aaa"));
		assertTrue(m.match("aaaa"));
		assertFalse(m.match("a"));
		assertFalse(m.match("aaaaa"));
	}

	public void test0032() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("a{2,}");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("aa"));
		assertTrue(m.match("aaa"));
		assertTrue(m.match("aaaaaaaaaa"));
		assertFalse(m.match("a"));
	}

	public void test0033() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("a{,4}");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match(""));
		assertTrue(m.match("a"));
		assertTrue(m.match("aa"));
		assertTrue(m.match("aaa"));
		assertTrue(m.match("aaaa"));
		assertFalse(m.match("aaaaa"));
	}

	public void test0034() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("a{2,2}");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("aa"));
		assertFalse(m.match("aaa"));
		assertFalse(m.match("aaaa"));
		assertFalse(m.match("a"));
		assertFalse(m.match("aaaaa"));
	}

	public void test0035() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("(abc){2,4}");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("abcabc"));
		assertTrue(m.match("abcabcabc"));
		assertTrue(m.match("abcabcabcabc"));
		assertFalse(m.match("abc"));
		assertFalse(m.match("abcabcabcabcabc"));
		assertFalse(m.match("abcab"));
		assertFalse(m.match("abcabcab"));
	}

	public void test0041() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("\\d+");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("2"));
		assertTrue(m.match("72"));
		assertTrue(m.match("765"));
		assertFalse(m.match("a"));
		assertFalse(m.match("7a"));
	}

	public void test0042() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("\\D+");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("THE IDOLM@STER"));
		assertFalse(m.match("961"));
		assertFalse(m.match("7a"));
	}

	public void test0043() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("\\s+");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match(" \t\n"));
		assertFalse(m.match("a"));
		assertFalse(m.match(" a"));
	}

	public void test0044() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("\\S+");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("765Production"));
		assertFalse(m.match(" \t\n"));
		assertFalse(m.match("THE IDOLM@STER"));
	}

	public void test0045() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("\\w+");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("AMAMI_Haruka_is_an_idol_of_Studio_765"));
		assertFalse(m.match("!!"));
		assertFalse(m.match("IDOLM@STER"));
	}

	public void test0046() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("\\W+");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("!!"));
		assertFalse(m.match("AMAMI_Haruka_is_an_idol_of_Studio_765"));
		assertFalse(m.match("IDOLM@STER"));
	}

	public void test0047() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("\\X");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match(" "));
		assertTrue(m.match("2"));
		assertTrue(m.match("\u3042"));       // Hiragana a
		assertTrue(m.match("\u3059\u3099")); // Hiragana zu=su+point
		assertFalse(m.match("aa"));
	}

	public void test0048() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse(".+");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("AMAMI_Harika is a character of THE IDOLM@STER"));
		assertTrue(m.match("KISARAGI Chihaya is also an idol of 765 Production"));
		assertFalse(m.match("\n"));
		assertFalse(m.match("aaa\naaa"));
	}

	public void test0049() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("\\p{L}");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("A"));
		assertTrue(m.match("z"));
		assertTrue(m.match("\u03bb"));       // Greek Letter lambda
		assertTrue(m.match("\u0430"));       // Cyrillic Letter a
		assertTrue(m.match("\u3042"));       // Hiragana a
		// Kanji(Hanzi) indicates "Truth" and pronounces "Makoto/Shin" in Japanese
		assertTrue(m.match("\u771f"));
		assertTrue(m.match("\uac00"));       // Hangul ga
		assertFalse(m.match(" "));
		assertFalse(m.match("@"));
		assertFalse(m.match("\u3099"));      // Hiragana Dakuon mark
	}

	public void test0061() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("(?s).+");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("AMAMI_Harika is a character of THE IDOLM@STER"));
		assertTrue(m.match("KISARAGI Chihaya is also an idol of 765 Production"));
		assertTrue(m.match("\n"));
		assertTrue(m.match("aaa\naaa"));
		assertFalse(m.match(""));
	}

	public void test0062() throws Exception {
//		NFA<Object, NFAState, Integer> v;
//		GenericNFAMatcher<Object, NFAState> m;
//
//		v = RegexParser.parse("(?i)[a-z ,]+");
//		m = new GenericNFAMatcher<Object, NFAState>(v);
//		assertTrue(m.match("haruka amami"));
//		assertTrue(m.match("AMAMI, Haruka"));
	}

	public void test0063() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("[a-z ,]+");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("haruka amami"));
		assertFalse(m.match("AMAMI, Haruka"));
	}

	public void test0064() throws Exception {
		NFA<Object, NFAState, Integer> v;
		GenericNFAMatcher<Object, NFAState> m;

		v = RegexParser.parse("(?)[a-z ,]+");
		m = new GenericNFAMatcher<Object, NFAState>(v);
		assertTrue(m.match("haruka amami"));
		assertFalse(m.match("AMAMI, Haruka"));
	}

}
