package crawl import ( "testing" "time" ) const robotsBody = `# a comment User-agent: * Disallow: /private Disallow: /tmp/ Crawl-delay: 5 User-agent: Maven Disallow: / Allow: /public ` func TestParseRobotsPicksTheMostSpecificGroup(t *testing.T) { // The Maven group applies to us even though we send a longer UA string. r := ParseRobots(robotsBody, "Maven/1.0 (self-hosted personal assistant)") if r.Allowed("/anything") { t.Error("Disallow: / in our own group was ignored") } if !r.Allowed("/public/page") { t.Error("Allow: /public must beat the shorter Disallow: /") } // A different agent falls into the * group. star := ParseRobots(robotsBody, "SomeoneElse/2") if !star.Allowed("/anything") { t.Error("the * group disallows nothing but /private and /tmp/") } if star.Allowed("/private/x") || star.Allowed("/tmp/") { t.Error("the * group's disallows were not applied") } if star.Delay != 5*time.Second { t.Errorf("crawl-delay = %v, want 5s", star.Delay) } } func TestParseRobotsEmptyMeansAllowAll(t *testing.T) { for _, body := range []string{"", "# nothing here\n", "User-agent: *\nDisallow:\n"} { if !ParseRobots(body, "Maven").Allowed("/whatever") { t.Errorf("body %q must allow everything", body) } } } func TestRobotsWildcards(t *testing.T) { r := ParseRobots("User-agent: *\nDisallow: /*.pdf$\nDisallow: /a/*/secret\n", "Maven") if r.Allowed("/docs/manual.pdf") { t.Error("*.pdf$ did not match") } if !r.Allowed("/docs/manual.pdf.html") { t.Error("$ must anchor at the end") } if r.Allowed("/a/b/secret") { t.Error("/a/*/secret did not match") } if !r.Allowed("/a/b/public") { t.Error("unrelated path was refused") } } // Consecutive User-agent lines share one group, which is common in the wild. func TestRobotsSharedGroup(t *testing.T) { r := ParseRobots("User-agent: Googlebot\nUser-agent: Maven\nDisallow: /x\n", "Maven/1.0") if r.Allowed("/x/y") { t.Fatal("a shared group's rules were not applied to the second agent") } } func TestRobotsCacheTTL(t *testing.T) { c := newRobotsCache(time.Minute) now := time.Now() c.put("example.com", ParseRobots("User-agent: *\nDisallow: /\n", "Maven"), now) if _, ok := c.get("example.com", now.Add(30*time.Second)); !ok { t.Error("a fresh entry must be served from cache") } if _, ok := c.get("example.com", now.Add(2*time.Minute)); ok { t.Error("an expired entry must be re-read") } }