| // Copyright 2023 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package http |
| |
| import ( |
| "cmp" |
| "fmt" |
| "slices" |
| "strconv" |
| "testing" |
| ) |
| |
| func TestMapping(t *testing.T) { |
| var m mapping[int, string] |
| for i := 0; i < maxSlice; i++ { |
| m.add(i, strconv.Itoa(i)) |
| } |
| if m.m != nil { |
| t.Fatal("m.m != nil") |
| } |
| for i := 0; i < maxSlice; i++ { |
| g, _ := m.find(i) |
| w := strconv.Itoa(i) |
| if g != w { |
| t.Fatalf("%d: got %s, want %s", i, g, w) |
| } |
| } |
| m.add(4, "4") |
| if m.s != nil { |
| t.Fatal("m.s != nil") |
| } |
| if m.m == nil { |
| t.Fatal("m.m == nil") |
| } |
| g, _ := m.find(4) |
| if w := "4"; g != w { |
| t.Fatalf("got %s, want %s", g, w) |
| } |
| } |
| |
| func TestMappingEachPair(t *testing.T) { |
| var m mapping[int, string] |
| var want []entry[int, string] |
| for i := 0; i < maxSlice*2; i++ { |
| v := strconv.Itoa(i) |
| m.add(i, v) |
| want = append(want, entry[int, string]{i, v}) |
| |
| } |
| |
| var got []entry[int, string] |
| m.eachPair(func(k int, v string) bool { |
| got = append(got, entry[int, string]{k, v}) |
| return true |
| }) |
| slices.SortFunc(got, func(e1, e2 entry[int, string]) int { |
| return cmp.Compare(e1.key, e2.key) |
| }) |
| if !slices.Equal(got, want) { |
| t.Errorf("got %v, want %v", got, want) |
| } |
| } |
| |
| func BenchmarkFindChild(b *testing.B) { |
| key := "articles" |
| children := []string{ |
| "*", |
| "cmd.html", |
| "code.html", |
| "contrib.html", |
| "contribute.html", |
| "debugging_with_gdb.html", |
| "docs.html", |
| "effective_go.html", |
| "files.log", |
| "gccgo_contribute.html", |
| "gccgo_install.html", |
| "go-logo-black.png", |
| "go-logo-blue.png", |
| "go-logo-white.png", |
| "go1.1.html", |
| "go1.2.html", |
| "go1.html", |
| "go1compat.html", |
| "go_faq.html", |
| "go_mem.html", |
| "go_spec.html", |
| "help.html", |
| "ie.css", |
| "install-source.html", |
| "install.html", |
| "logo-153x55.png", |
| "Makefile", |
| "root.html", |
| "share.png", |
| "sieve.gif", |
| "tos.html", |
| "articles", |
| } |
| if len(children) != 32 { |
| panic("bad len") |
| } |
| for _, n := range []int{2, 4, 8, 16, 32} { |
| list := children[:n] |
| b.Run(fmt.Sprintf("n=%d", n), func(b *testing.B) { |
| |
| b.Run("rep=linear", func(b *testing.B) { |
| var entries []entry[string, any] |
| for _, c := range list { |
| entries = append(entries, entry[string, any]{c, nil}) |
| } |
| b.ResetTimer() |
| for i := 0; i < b.N; i++ { |
| findChildLinear(key, entries) |
| } |
| }) |
| b.Run("rep=map", func(b *testing.B) { |
| m := map[string]any{} |
| for _, c := range list { |
| m[c] = nil |
| } |
| var x any |
| b.ResetTimer() |
| for i := 0; i < b.N; i++ { |
| x = m[key] |
| } |
| _ = x |
| }) |
| b.Run(fmt.Sprintf("rep=hybrid%d", maxSlice), func(b *testing.B) { |
| var h mapping[string, any] |
| for _, c := range list { |
| h.add(c, nil) |
| } |
| var x any |
| b.ResetTimer() |
| for i := 0; i < b.N; i++ { |
| x, _ = h.find(key) |
| } |
| _ = x |
| }) |
| }) |
| } |
| } |
| |
| func findChildLinear(key string, entries []entry[string, any]) any { |
| for _, e := range entries { |
| if key == e.key { |
| return e.value |
| } |
| } |
| return nil |
| } |