package be.iminds.ilabt.jfed.util;

import org.testng.Assert;
import org.testng.annotations.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

/**
 * GeniUrnTest
 */
public class GeniUrnTest {

    @Test
    public void testUrnA() throws GeniUrn.GeniUrnParseException {
        String urnStr = "urn:publicid:IDN+test.example.com+slice+testSlice";
        GeniUrn urn = new GeniUrn(urnStr);
        Assert.assertEquals(urn.getEncodedResourceName(), "testSlice");
        Assert.assertEquals(urn.getEncodedResourceType(), "slice");
        Assert.assertEquals(urn.getEncodedTopLevelAuthority(), "test.example.com");
        Assert.assertEquals(urn.getResourceName(), "testSlice");
        Assert.assertEquals(urn.getResourceType(), "slice");
        Assert.assertEquals(urn.getTopLevelAuthority(), "test.example.com");
        Assert.assertNull(urn.getEncodedSubAuthName());
        Assert.assertNull(urn.getSubAuthName());

        //ResourceId interface
        Assert.assertEquals(urn.getType(), "urn");
        Assert.assertEquals(urn.getValue(), urnStr);
        Assert.assertEquals(urn.toString(), urnStr);

        GeniUrn urn2 = GeniUrn.parse(urnStr);
        Assert.assertEquals(urn, urn2);
    }
    @Test
    public void testUrnB() throws GeniUrn.GeniUrnParseException {
        String urnStr = "urn:publicid:IDN+test.example.com:subAuth+slice+testSlice";
        GeniUrn urn = new GeniUrn(urnStr);
        Assert.assertEquals(urn.getEncodedResourceName(), "testSlice");
        Assert.assertEquals(urn.getEncodedResourceType(), "slice");
        Assert.assertEquals(urn.getEncodedTopLevelAuthority(), "test.example.com:subAuth");
        Assert.assertEquals(urn.getResourceName(), "testSlice");
        Assert.assertEquals(urn.getResourceType(), "slice");
        Assert.assertEquals(urn.getTopLevelAuthority(), "test.example.com//subAuth");
        Assert.assertNotNull(urn.getEncodedSubAuthName());
        Assert.assertEquals(urn.getSubAuthName(), "subAuth");
        Assert.assertEquals(urn.getSubAuthNames(1), "subAuth");
        Assert.assertEquals(urn.getEncodedSubAuthName(), "subAuth");
        Assert.assertEquals(urn.getEncodedSubAuthNames(1), "subAuth");
        Assert.assertNull(urn.getEncodedSubAuthNames(2));
        Assert.assertNull(urn.getSubAuthNames(2));
        Assert.assertEquals(urn.getSubAuthName(0), "subAuth");
        Assert.assertEquals(urn.getEncodedSubAuthName(0), "subAuth");
        Assert.assertNull(urn.getSubAuthName(1));
        Assert.assertNull(urn.getEncodedSubAuthName(1));

        //ResourceId interface
        Assert.assertEquals(urn.getType(), "urn");
        Assert.assertEquals(urn.getValue(), urnStr);
        Assert.assertEquals(urn.toString(), urnStr);

        GeniUrn urn2 = GeniUrn.parse(urnStr);
        Assert.assertEquals(urn, urn2);
    }
    @Test
    public void testUrnC() throws GeniUrn.GeniUrnParseException {
        String urnStr = "urn:publicid:IDN+test.example.com:subAuth:blabla+slice+testSlice";
        GeniUrn urn = new GeniUrn(urnStr);
        Assert.assertEquals(urn.getEncodedResourceName(), "testSlice");
        Assert.assertEquals(urn.getEncodedResourceType(), "slice");
        Assert.assertEquals(urn.getEncodedTopLevelAuthority(), "test.example.com:subAuth:blabla");
        Assert.assertEquals(urn.getResourceName(), "testSlice");
        Assert.assertEquals(urn.getResourceType(), "slice");
        Assert.assertEquals(urn.getTopLevelAuthority(), "test.example.com//subAuth//blabla");
        Assert.assertEquals(urn.getEncodedSubAuthName(), "subAuth:blabla");
        Assert.assertEquals(urn.getEncodedSubAuthNames(1), "subAuth");
        Assert.assertEquals(urn.getEncodedSubAuthNames(2), "subAuth:blabla");
        Assert.assertEquals(urn.getSubAuthName(), "subAuth//blabla");
        Assert.assertEquals(urn.getSubAuthNames(1), "subAuth");
        Assert.assertEquals(urn.getSubAuthNames(2), "subAuth//blabla");
        Assert.assertNull(urn.getEncodedSubAuthNames(3));
        Assert.assertNull(urn.getSubAuthNames(3));
        Assert.assertEquals(urn.getSubAuthName(0), "subAuth");
        Assert.assertEquals(urn.getSubAuthName(1), "blabla");
        Assert.assertEquals(urn.getEncodedSubAuthName(0), "subAuth");
        Assert.assertEquals(urn.getEncodedSubAuthName(1), "blabla");
        Assert.assertNull(urn.getSubAuthName(2));
        Assert.assertNull(urn.getEncodedSubAuthName(2));

        //ResourceId interface
        Assert.assertEquals(urn.getType(), "urn");
        Assert.assertEquals(urn.getValue(), urnStr);
        Assert.assertEquals(urn.toString(), urnStr);

        GeniUrn urn2 = GeniUrn.parse(urnStr);
        Assert.assertEquals(urn, urn2);
    }
    @Test(expectedExceptions = GeniUrn.GeniUrnParseException.class)
    public void testUrnErrorA() throws GeniUrn.GeniUrnParseException {
        String urnStr = "urn:publicid:ID+test.example.com:tst+slice+testSlice";
        GeniUrn urn2 = GeniUrn.parse(urnStr);
        Assert.assertNull(urn2);
        GeniUrn urn = new GeniUrn(urnStr); //should throw GeniUrnParseException
        Assert.assertNull(urn);
    }
    @Test(expectedExceptions = GeniUrn.GeniUrnParseException.class)
    public void testUrnErrorB() throws GeniUrn.GeniUrnParseException {
        String urnStr = "urn:publicid:IDN+test.example.com:tst+slice+testSlice/blabla";
        GeniUrn urn2 = GeniUrn.parse(urnStr);
        Assert.assertNull(urn2);
        GeniUrn urn = new GeniUrn(urnStr); //should throw GeniUrnParseException
        Assert.assertNull(urn);
    }
    @Test(expectedExceptions = GeniUrn.GeniUrnParseException.class)
    public void testUrnErrorC() throws GeniUrn.GeniUrnParseException {
        String urnStr = "urn:publicid:IDN+test.example.com:tst+slice+testSlice\\x8Fblabla";
        GeniUrn urn2 = GeniUrn.parse(urnStr);
        Assert.assertNull(urn2);
        GeniUrn urn = new GeniUrn(urnStr); //should throw GeniUrnParseException
        Assert.assertNull(urn);
    }
    @Test(expectedExceptions = GeniUrn.GeniUrnParseException.class)
    public void testUrnErrorD() throws GeniUrn.GeniUrnParseException {
        String urnStr = "urn:publicid:IDN+test.example.com{tst+slice+testSlice";
        GeniUrn urn2 = GeniUrn.parse(urnStr);
        Assert.assertNull(urn2);
        GeniUrn urn = new GeniUrn(urnStr); //should throw GeniUrnParseException
        Assert.assertNull(urn);
    }
    @Test(expectedExceptions = GeniUrn.GeniUrnParseException.class)
    public void testUrnErrorE() throws GeniUrn.GeniUrnParseException {
        String urnStr = "urn:publicid:IDN+test.example.com{tst+slice+test%Slice";
        GeniUrn urn2 = GeniUrn.parse(urnStr);
        Assert.assertNull(urn2);
        GeniUrn urn = new GeniUrn(urnStr); //should throw GeniUrnParseException
        Assert.assertNull(urn);
    }

    @Test
    public void testGetSubAuthNames() throws GeniUrn.GeniUrnParseException {
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst+test+t").getEncodedSubAuthNames(1), equalTo("tst"));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst:a+test+t").getEncodedSubAuthNames(1), equalTo("tst"));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst:a+test+t").getEncodedSubAuthNames(2), equalTo("tst:a"));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst:a:b+test+t").getEncodedSubAuthNames(1), equalTo("tst"));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst:a:b+test+t").getEncodedSubAuthNames(2), equalTo("tst:a"));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst:a:b+test+t").getEncodedSubAuthNames(3), equalTo("tst:a:b"));

        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com+test+t").getEncodedSubAuthNames(1), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com+test+t").getEncodedSubAuthNames(2), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com+test+t").getEncodedSubAuthNames(3), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst+test+t").getEncodedSubAuthNames(2), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst+test+t").getEncodedSubAuthNames(3), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst:a+test+t").getEncodedSubAuthNames(3), is(nullValue()));
        
        
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst+test+t").getSubAuthNames(1), equalTo("tst"));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst:a+test+t").getSubAuthNames(1), equalTo("tst"));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst:a+test+t").getSubAuthNames(2), equalTo("tst//a"));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst:a:b+test+t").getSubAuthNames(1), equalTo("tst"));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst:a:b+test+t").getSubAuthNames(2), equalTo("tst//a"));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst:a:b+test+t").getSubAuthNames(3), equalTo("tst//a//b"));

        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com+test+t").getSubAuthNames(1), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com+test+t").getSubAuthNames(2), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com+test+t").getSubAuthNames(3), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst+test+t").getSubAuthNames(2), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst+test+t").getSubAuthNames(3), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+test.example.com:tst:a+test+t").getSubAuthNames(3), is(nullValue()));
    }
    @Test
    public void testGetSubAuthName() throws GeniUrn.GeniUrnParseException {
        assertThat(new GeniUrn("urn:publicid:IDN+example.com+test+t").getSubAuthName(0), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com+test+t").getSubAuthName(1), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com+test+t").getSubAuthName(2), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com+test+t").getSubAuthName(3), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst+test+t").getSubAuthName(0), equalTo("tst"));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst+test+t").getSubAuthName(1), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst+test+t").getSubAuthName(2), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst+test+t").getSubAuthName(3), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a+test+t").getSubAuthName(0), equalTo("tst"));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a+test+t").getSubAuthName(1), equalTo("a"));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a+test+t").getSubAuthName(2), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a+test+t").getSubAuthName(3), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a:b+test+t").getSubAuthName(0), equalTo("tst"));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a:b+test+t").getSubAuthName(1), equalTo("a"));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a:b+test+t").getSubAuthName(2), equalTo("b"));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a:b+test+t").getSubAuthName(3), is(nullValue()));
        
        assertThat(new GeniUrn("urn:publicid:IDN+example.com+test+t").getEncodedSubAuthName(0), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com+test+t").getEncodedSubAuthName(1), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com+test+t").getEncodedSubAuthName(2), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com+test+t").getEncodedSubAuthName(3), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst+test+t").getEncodedSubAuthName(0), equalTo("tst"));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst+test+t").getEncodedSubAuthName(1), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst+test+t").getEncodedSubAuthName(2), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst+test+t").getEncodedSubAuthName(3), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a+test+t").getEncodedSubAuthName(0), equalTo("tst"));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a+test+t").getEncodedSubAuthName(1), equalTo("a"));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a+test+t").getEncodedSubAuthName(2), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a+test+t").getEncodedSubAuthName(3), is(nullValue()));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a:b+test+t").getEncodedSubAuthName(0), equalTo("tst"));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a:b+test+t").getEncodedSubAuthName(1), equalTo("a"));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a:b+test+t").getEncodedSubAuthName(2), equalTo("b"));
        assertThat(new GeniUrn("urn:publicid:IDN+example.com:tst:a:b+test+t").getEncodedSubAuthName(3), is(nullValue()));
    }



    public GeniUrn testHelper(String tld, String type, String name, String expectedUrnString) throws GeniUrn.GeniUrnParseException {
        GeniUrn urn = GeniUrn.createGeniUrnFromDecodedParts(tld, type, name);
        Assert.assertEquals(urn.getResourceName(), name);
        Assert.assertEquals(urn.getResourceType(), type);
        Assert.assertEquals(urn.getTopLevelAuthority(), tld);
        Assert.assertEquals(urn.getEncodedResourceName(), GeniUrn.urnEncoding(name));
        Assert.assertEquals(urn.getEncodedResourceType(), GeniUrn.urnEncoding(type));
        Assert.assertEquals(urn.getEncodedTopLevelAuthority(), GeniUrn.urnEncoding(tld));
        Assert.assertEquals(urn.getType(), "urn"); //ResourceId interface

        Assert.assertEquals(urn.getValue(), expectedUrnString);
        Assert.assertEquals(urn.toString(), expectedUrnString);
        GeniUrn urn2 = new GeniUrn(expectedUrnString);
        Assert.assertEquals(urn2, urn);

        Assert.assertEquals(urn2.getResourceName(), name);
        Assert.assertEquals(urn2.getResourceType(), type);
        Assert.assertEquals(urn2.getTopLevelAuthority(), tld);
        Assert.assertEquals(urn2.getType(), "urn"); //ResourceId interface
        Assert.assertEquals(urn2.getValue(), expectedUrnString);
        Assert.assertEquals(urn2.toString(), expectedUrnString);

        return urn2;
    }

    @Test
    public void testUrnWithWhiteSpaceInName() throws GeniUrn.GeniUrnParseException {
        testHelper("test.example.com", "slice", "test nr 1", "urn:publicid:IDN+test.example.com+slice+test+nr+1");

        //check that whitespace is collapsed and leading and trailing whitespace is removed
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "test  nr 1").getValue(), "urn:publicid:IDN+test.example.com+slice+test+nr+1");

        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "test  nr 1").getEncodedResourceName(), "test+nr+1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "test     nr 1").getEncodedResourceName(), "test+nr+1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "test nr   1").getEncodedResourceName(), "test+nr+1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "test nr \t1").getEncodedResourceName(), "test+nr+1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "test nr 1   ").getEncodedResourceName(), "test+nr+1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", " test nr 1").getEncodedResourceName(), "test+nr+1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "   test nr 1").getEncodedResourceName(), "test+nr+1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "\ttest nr 1").getEncodedResourceName(), "test+nr+1");

        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "test  nr 1").getResourceName(), "test nr 1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "test     nr 1").getResourceName(), "test nr 1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "test nr   1").getResourceName(), "test nr 1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "test nr \t1").getResourceName(), "test nr 1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "test nr 1   ").getResourceName(), "test nr 1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", " test nr 1").getResourceName(), "test nr 1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "   test nr 1").getResourceName(), "test nr 1");
        Assert.assertEquals(GeniUrn.createGeniUrnFromDecodedParts("test.example.com", "slice", "\ttest nr 1").getResourceName(), "test nr 1");
    }

    @Test
    public void testParseUrnWithSpecialInName() throws GeniUrn.GeniUrnParseException {
        testHelper("test.example.com", "slice", "test+with/specials", "urn:publicid:IDN+test.example.com+slice+test%2Bwith%2Fspecials");
        testHelper("test.example.com", "slice", "test;with%specials'", "urn:publicid:IDN+test.example.com+slice+test%3Bwith%25specials%27");
        testHelper("test.example.com", "slice", "test?with#specials", "urn:publicid:IDN+test.example.com+slice+test%3Fwith%23specials");
        testHelper("test.example.com", "slice", "test::with//specials", "urn:publicid:IDN+test.example.com+slice+test;with:specials");
        testHelper("test.example.com", "slice", "test:::with///specials", "urn:publicid:IDN+test.example.com+slice+test;%3Awith:%2Fspecials");
    }

    @Test
    public void testUrnEncoding() throws GeniUrn.GeniUrnParseException {
        Assert.assertEquals(GeniUrn.urnEncoding("+"), "%2B");
        Assert.assertEquals(GeniUrn.urnEncoding("/"), "%2F");
        Assert.assertEquals(GeniUrn.urnEncoding(";"), "%3B");
        Assert.assertEquals(GeniUrn.urnEncoding("'"), "%27");
        Assert.assertEquals(GeniUrn.urnEncoding("%"), "%25");
        Assert.assertEquals(GeniUrn.urnEncoding("?"), "%3F");
        Assert.assertEquals(GeniUrn.urnEncoding("#"), "%23");
        Assert.assertEquals(GeniUrn.urnEncoding("::"), ";");
        Assert.assertEquals(GeniUrn.urnEncoding("//"), ":");
        Assert.assertEquals(GeniUrn.urnEncoding(":::"), ";%3A");
        Assert.assertEquals(GeniUrn.urnEncoding("///"), ":%2F");
    }

    @Test
    public void testUrnDecoding() throws GeniUrn.GeniUrnParseException {
        Assert.assertEquals(GeniUrn.urnDecoding("%2B"), "+");
        Assert.assertEquals(GeniUrn.urnDecoding("%2F"), "/");
        Assert.assertEquals(GeniUrn.urnDecoding("%3B"), ";");
        Assert.assertEquals(GeniUrn.urnDecoding("%27"), "'");
        Assert.assertEquals(GeniUrn.urnDecoding("%25"), "%");
        Assert.assertEquals(GeniUrn.urnDecoding("%3F"), "?");
        Assert.assertEquals(GeniUrn.urnDecoding("%23"), "#");
        Assert.assertEquals(GeniUrn.urnDecoding(";"), "::");
        Assert.assertEquals(GeniUrn.urnDecoding(":"), "//");
        Assert.assertEquals(GeniUrn.urnDecoding(";%3A"), ":::");
        Assert.assertEquals(GeniUrn.urnDecoding(":%2F"), "///");
    }

    @Test
    public void testCreateGeniExamples() throws GeniUrn.GeniUrnParseException {
      // IDN plc//princeton authority sa 	urn:publicid:IDN+plc:princeton+authority+sa
      // IDN gcf//gpo//gpolab user joe 	urn:publicid:IDN+gcf:gpo:gpolab+user+joe
      // IDN gcf//gpo//gpolab node switch 1 port 2	urn:publicid:IDN+gcf:gpo:gpolab+node+switch+1+port+2
        GeniUrn a = testHelper("plc//princeton", "authority", "sa", "urn:publicid:IDN+plc:princeton+authority+sa");
        GeniUrn b = testHelper("gcf//gpo//gpolab", "user", "joe", "urn:publicid:IDN+gcf:gpo:gpolab+user+joe");
        GeniUrn c = testHelper("gcf//gpo//gpolab", "node", "switch 1 port 2", "urn:publicid:IDN+gcf:gpo:gpolab+node+switch+1+port+2");

        Assert.assertEquals(a.getEncodedSubAuthName(), "princeton");
        Assert.assertEquals(b.getEncodedSubAuthName(), "gpo:gpolab");
    }

    public GeniUrn testHelper2(String unencodedString, String urn) {
        GeniUrn res = GeniUrn.createGeniUrnFromPublicID(unencodedString);
        Assert.assertEquals(res.getValue(), urn);
        return res;
    }

    @Test
    public void testCreateGeniExamples2() throws GeniUrn.GeniUrnParseException {
        GeniUrn a = testHelper2("IDN plc//princeton authority sa", "urn:publicid:IDN+plc:princeton+authority+sa");
        GeniUrn b = testHelper2("IDN gcf//gpo//gpolab user joe", "urn:publicid:IDN+gcf:gpo:gpolab+user+joe");
        GeniUrn c = testHelper2("IDN gcf//gpo//gpolab node switch 1 port 2", "urn:publicid:IDN+gcf:gpo:gpolab+node+switch+1+port+2");

        Assert.assertEquals(a.getEncodedSubAuthName(), "princeton");
        Assert.assertEquals(b.getEncodedSubAuthName(), "gpo:gpolab");
    }

    @Test
    public void testHasCompatibleAuthority() throws GeniUrn.GeniUrnParseException {
        GeniUrn tabc =  new GeniUrn("urn:publicid:IDN+example.com:a:bb:ccc+test+tabc");
        GeniUrn tab =   new GeniUrn("urn:publicid:IDN+example.com:a:bb+testb+tab");
        GeniUrn ta =    new GeniUrn("urn:publicid:IDN+example.com:a+testc+ta");
        GeniUrn t =     new GeniUrn("urn:publicid:IDN+example.com+testd+t");
        GeniUrn tx =    new GeniUrn("urn:publicid:IDN+example.com:xxx+testea+t1");
        GeniUrn tay =   new GeniUrn("urn:publicid:IDN+example.com:a:yy+testbb+t2");
        GeniUrn tabz =  new GeniUrn("urn:publicid:IDN+example.com:a:bb:z+testcc+t3");
        GeniUrn tabcz = new GeniUrn("urn:publicid:IDN+example.com:a:bb:ccc:zzzzzzz+testccc+t3");
        GeniUrn uabc =  new GeniUrn("urn:publicid:IDN+u.tld:a:bb:ccc+testdd+t4");
        GeniUrn uab =   new GeniUrn("urn:publicid:IDN+u.tld:a:bb+testee+t5");
        GeniUrn ua =    new GeniUrn("urn:publicid:IDN+u.tld:a+testff+t6");
        GeniUrn u =     new GeniUrn("urn:publicid:IDN+u.tld+testgg+t7");

        assertThat(tabc.hasCompatibleAuthority(tabc),  is(true));
        assertThat(tabc.hasCompatibleAuthority(tab),   is(true));
        assertThat(tabc.hasCompatibleAuthority(ta),    is(true));
        assertThat(tabc.hasCompatibleAuthority(t),     is(true));
        assertThat(tabc.hasCompatibleAuthority(tx),    is(false));
        assertThat(tabc.hasCompatibleAuthority(tay),   is(false));
        assertThat(tabc.hasCompatibleAuthority(tabz),  is(false));
        assertThat(tabc.hasCompatibleAuthority(tabcz), is(true));
        assertThat(tabc.hasCompatibleAuthority(uabc),  is(false));
        assertThat(tabc.hasCompatibleAuthority(uab),   is(false));
        assertThat(tabc.hasCompatibleAuthority(ua),    is(false));
        assertThat(tabc.hasCompatibleAuthority(u),     is(false));

        assertThat(tab.hasCompatibleAuthority(tabc),  is(true));
        assertThat(tab.hasCompatibleAuthority(tab),   is(true));
        assertThat(tab.hasCompatibleAuthority(ta),    is(true));
        assertThat(tab.hasCompatibleAuthority(t),     is(true));
        assertThat(tab.hasCompatibleAuthority(tx),    is(false));
        assertThat(tab.hasCompatibleAuthority(tay),   is(false));
        assertThat(tab.hasCompatibleAuthority(tabz),  is(true));
        assertThat(tab.hasCompatibleAuthority(tabcz), is(true));
        assertThat(tab.hasCompatibleAuthority(uabc),  is(false));
        assertThat(tab.hasCompatibleAuthority(uab),   is(false));
        assertThat(tab.hasCompatibleAuthority(ua),    is(false));
        assertThat(tab.hasCompatibleAuthority(u),     is(false));

        assertThat(ta.hasCompatibleAuthority(tabc),  is(true));
        assertThat(ta.hasCompatibleAuthority(tab),   is(true));
        assertThat(ta.hasCompatibleAuthority(ta),    is(true));
        assertThat(ta.hasCompatibleAuthority(t),     is(true));
        assertThat(ta.hasCompatibleAuthority(tx),    is(false));
        assertThat(ta.hasCompatibleAuthority(tay),   is(true));
        assertThat(ta.hasCompatibleAuthority(tabz),  is(true));
        assertThat(ta.hasCompatibleAuthority(tabcz), is(true));
        assertThat(ta.hasCompatibleAuthority(uabc),  is(false));
        assertThat(ta.hasCompatibleAuthority(uab),   is(false));
        assertThat(ta.hasCompatibleAuthority(ua),    is(false));
        assertThat(ta.hasCompatibleAuthority(u),     is(false));

        assertThat(t.hasCompatibleAuthority(tabc),  is(true));
        assertThat(t.hasCompatibleAuthority(tab),   is(true));
        assertThat(t.hasCompatibleAuthority(ta),    is(true));
        assertThat(t.hasCompatibleAuthority(t),     is(true));
        assertThat(t.hasCompatibleAuthority(tx),    is(true));
        assertThat(t.hasCompatibleAuthority(tay),   is(true));
        assertThat(t.hasCompatibleAuthority(tabz),  is(true));
        assertThat(t.hasCompatibleAuthority(tabcz), is(true));
        assertThat(t.hasCompatibleAuthority(uabc),  is(false));
        assertThat(t.hasCompatibleAuthority(uab),   is(false));
        assertThat(t.hasCompatibleAuthority(ua),    is(false));
        assertThat(t.hasCompatibleAuthority(u),     is(false));

        assertThat(tx.hasCompatibleAuthority(tabc),  is(false));
        assertThat(tx.hasCompatibleAuthority(tab),   is(false));
        assertThat(tx.hasCompatibleAuthority(ta),    is(false));
        assertThat(tx.hasCompatibleAuthority(t),     is(true));
        assertThat(tx.hasCompatibleAuthority(tx),    is(true));
        assertThat(tx.hasCompatibleAuthority(tay),   is(false));
        assertThat(tx.hasCompatibleAuthority(tabz),  is(false));
        assertThat(tx.hasCompatibleAuthority(tabcz), is(false));
        assertThat(tx.hasCompatibleAuthority(uabc),  is(false));
        assertThat(tx.hasCompatibleAuthority(uab),   is(false));
        assertThat(tx.hasCompatibleAuthority(ua),    is(false));
        assertThat(tx.hasCompatibleAuthority(u),     is(false));

        assertThat(tabcz.hasCompatibleAuthority(tabc),  is(true));
        assertThat(tabcz.hasCompatibleAuthority(tab),   is(true));
        assertThat(tabcz.hasCompatibleAuthority(ta),    is(true));
        assertThat(tabcz.hasCompatibleAuthority(t),     is(true));
        assertThat(tabcz.hasCompatibleAuthority(tx),    is(false));
        assertThat(tabcz.hasCompatibleAuthority(tay),   is(false));
        assertThat(tabcz.hasCompatibleAuthority(tabz),  is(false));
        assertThat(tabcz.hasCompatibleAuthority(tabcz), is(true));
        assertThat(tabcz.hasCompatibleAuthority(uabc),  is(false));
        assertThat(tabcz.hasCompatibleAuthority(uab),   is(false));
        assertThat(tabcz.hasCompatibleAuthority(ua),    is(false));
        assertThat(tabcz.hasCompatibleAuthority(u),     is(false));

        assertThat(uab.hasCompatibleAuthority(tabc),  is(false));
        assertThat(uab.hasCompatibleAuthority(tab),   is(false));
        assertThat(uab.hasCompatibleAuthority(ta),    is(false));
        assertThat(uab.hasCompatibleAuthority(t),     is(false));
        assertThat(uab.hasCompatibleAuthority(tx),    is(false));
        assertThat(uab.hasCompatibleAuthority(tay),   is(false));
        assertThat(uab.hasCompatibleAuthority(tabz),  is(false));
        assertThat(uab.hasCompatibleAuthority(tabcz), is(false));
        assertThat(uab.hasCompatibleAuthority(uabc),  is(true));
        assertThat(uab.hasCompatibleAuthority(uab),   is(true));
        assertThat(uab.hasCompatibleAuthority(ua),    is(true));
        assertThat(uab.hasCompatibleAuthority(u),     is(true));

        // X.hasCompatibleAuthority(X) for each X
        assertThat(tabc.hasCompatibleAuthority(tabc),   is(true));
        assertThat(tab.hasCompatibleAuthority(tab),     is(true));
        assertThat(ta.hasCompatibleAuthority(ta),       is(true));
        assertThat(t.hasCompatibleAuthority(t),         is(true));
        assertThat(tx.hasCompatibleAuthority(tx),       is(true));
        assertThat(tay.hasCompatibleAuthority(tay),     is(true));
        assertThat(tabz.hasCompatibleAuthority(tabz),   is(true));
        assertThat(tabcz.hasCompatibleAuthority(tabcz), is(true));
        assertThat(uabc.hasCompatibleAuthority(uabc),   is(true));
        assertThat(uab.hasCompatibleAuthority(uab),     is(true));
        assertThat(ua.hasCompatibleAuthority(ua),       is(true));
        assertThat(u.hasCompatibleAuthority(u),         is(true));
    }
}
