package publicsuffix import ( "testing" ) type validTestCase struct { input string domain string parsed *DomainName } func TestValid(t *testing.T) { testCases := []validTestCase{ {"example.com", "example.com", &DomainName{"com", "example", "", MustNewRule("com")}}, {"foo.example.com", "example.com", &DomainName{"com", "example", "foo", MustNewRule("com")}}, {"verybritish.co.uk", "verybritish.co.uk", &DomainName{"co.uk", "verybritish", "", MustNewRule("*.uk")}}, {"foo.verybritish.co.uk", "verybritish.co.uk", &DomainName{"co.uk", "verybritish", "foo", MustNewRule("*.uk")}}, {"parliament.uk", "parliament.uk", &DomainName{"uk", "parliament", "", MustNewRule("!parliament.uk")}}, {"foo.parliament.uk", "parliament.uk", &DomainName{"uk", "parliament", "foo", MustNewRule("!parliament.uk")}}, {"foo.blogspot.com", "foo.blogspot.com", &DomainName{"blogspot.com", "foo", "", MustNewRule("blogspot.com")}}, {"bar.foo.blogspot.com", "foo.blogspot.com", &DomainName{"blogspot.com", "foo", "bar", MustNewRule("blogspot.com")}}, } for _, testCase := range testCases { got, err := Parse(testCase.input) if err != nil { t.Errorf("TestValid(%v) returned error: %v", testCase.input, err) } if want := testCase.parsed; want.String() != got.String() { t.Errorf("TestValid(%v) = %v, want %v", testCase.input, got, want) } str, err := Domain(testCase.input) if err != nil { t.Errorf("TestValid(%v) returned error: %v", testCase.input, err) } if want := testCase.domain; want != str { t.Errorf("TestValid(%v) = %v, want %v", testCase.input, str, want) } } } type privateTestCase struct { input string domain string ignore bool error bool } func TestIncludePrivate(t *testing.T) { testCases := []privateTestCase{ {"blogspot.com", "", false, true}, {"blogspot.com", "blogspot.com", true, false}, {"foo.blogspot.com", "foo.blogspot.com", false, false}, {"foo.blogspot.com", "blogspot.com", true, false}, } for _, testCase := range testCases { got, err := DomainFromListWithOptions(DefaultList, testCase.input, &FindOptions{IgnorePrivate: testCase.ignore}) if testCase.error && err == nil { t.Errorf("TestIncludePrivate(%v) should have returned error, got: %v", testCase.input, got) continue } if !testCase.error && err != nil { t.Errorf("TestIncludePrivate(%v) returned error: %v", testCase.input, err) continue } if want := testCase.domain; want != got { t.Errorf("Domain(%v) = %v, want %v", testCase.input, got, want) } } } type idnaTestCase struct { input string domain string error bool } func TestIDNA(t *testing.T) { testACases := []idnaTestCase{ // A-labels are supported // Check single IDN part {"xn--p1ai", "", true}, {"example.xn--p1ai", "example.xn--p1ai", false}, {"subdomain.example.xn--p1ai", "example.xn--p1ai", false}, // Check multiple IDN parts {"xn--example--3bhk5a.xn--p1ai", "xn--example--3bhk5a.xn--p1ai", false}, {"subdomain.xn--example--3bhk5a.xn--p1ai", "xn--example--3bhk5a.xn--p1ai", false}, // Check multiple IDN rules {"example.xn--o1ach.xn--90a3ac", "example.xn--o1ach.xn--90a3ac", false}, {"sudbomain.example.xn--o1ach.xn--90a3ac", "example.xn--o1ach.xn--90a3ac", false}, } for _, testCase := range testACases { got, err := DomainFromListWithOptions(DefaultList, testCase.input, nil) if testCase.error && err == nil { t.Errorf("A-label %v should have returned error, got: %v", testCase.input, got) continue } if !testCase.error && err != nil { t.Errorf("A-label %v returned error: %v", testCase.input, err) continue } if want := testCase.domain; want != got { t.Errorf("A-label Domain(%v) = %v, want %v", testCase.input, got, want) } } // These tests validates the non-acceptance of U-labels. // // TODO(weppos): some tests are passing because of the default rule * // Consider to add some tests overriding the default rule to nil. // Right now, setting the default rule to nil with cause a panic if the lookup results in a nil. testUCases := []idnaTestCase{ // U-labels are NOT supported // Check single IDN part {"рф", "", true}, {"example.рф", "example.рф", false}, // passes because of * {"subdomain.example.рф", "example.рф", false}, // passes because of * // Check multiple IDN parts {"example-упр.рф", "example-упр.рф", false}, // passes because of * {"subdomain.example-упр.рф", "example-упр.рф", false}, // passes because of * // Check multiple IDN rules {"example.упр.срб", "упр.срб", false}, {"sudbomain.example.упр.срб", "упр.срб", false}, } for _, testCase := range testUCases { got, err := DomainFromListWithOptions(DefaultList, testCase.input, nil) if testCase.error && err == nil { t.Errorf("U-label %v should have returned error, got: %v", testCase.input, got) continue } if !testCase.error && err != nil { t.Errorf("U-label %v returned error: %v", testCase.input, err) continue } if want := testCase.domain; want != got { t.Errorf("U-label Domain(%v) = %v, want %v", testCase.input, got, want) } } } func TestFindRuleIANA(t *testing.T) { testCases := []struct { input, want string }{ // TLD with only 1 rule. {"biz", "biz"}, {"input.biz", "biz"}, {"b.input.biz", "biz"}, // The relevant {kobe,kyoto}.jp rules are: // jp // *.kobe.jp // !city.kobe.jp // kyoto.jp // ide.kyoto.jp {"jp", "jp"}, {"kobe.jp", "jp"}, {"c.kobe.jp", "c.kobe.jp"}, {"b.c.kobe.jp", "c.kobe.jp"}, {"a.b.c.kobe.jp", "c.kobe.jp"}, {"city.kobe.jp", "kobe.jp"}, {"www.city.kobe.jp", "kobe.jp"}, {"kyoto.jp", "kyoto.jp"}, {"test.kyoto.jp", "kyoto.jp"}, {"ide.kyoto.jp", "ide.kyoto.jp"}, {"b.ide.kyoto.jp", "ide.kyoto.jp"}, {"a.b.ide.kyoto.jp", "ide.kyoto.jp"}, // Domain with a private public suffix should return the ICANN public suffix. {"foo.compute-1.amazonaws.com", "com"}, // Domain equal to a private public suffix should return the ICANN public suffix. {"cloudapp.net", "net"}, } for _, tc := range testCases { rule := DefaultList.Find(tc.input, &FindOptions{IgnorePrivate: true, DefaultRule: nil}) if rule == nil { t.Errorf("TestFindRuleIANA(%v) nil rule", tc.input) continue } suffix := rule.Decompose(tc.input)[1] // If the TLD is empty, it means name is actually a suffix. // In fact, decompose returns an array of empty strings in this case. if suffix == "" { suffix = tc.input } if suffix != tc.want { t.Errorf("TestFindRuleIANA(%v) = %v, want %v", tc.input, suffix, tc.want) } } }