// +build go1.16 package funcs_test import ( "fmt" "strings" "testing" "testing/fstest" "sync" "io/fs" "github.com/gin-gonic/gin" "go.sebtobie.de/httpserver/funcs" ) const al = "abcdefghijklmnopqrstunwxyz" type Node struct { name string children []*Node } func (n *Node) getchildren(dir string, m *sync.Map, wg *sync.WaitGroup) { var p = n.name if dir != "" { p = strings.Join([]string{dir, n.name}, "/") } if len(n.children) != 0 { m.Store(p, &fstest.MapFile{Mode: fs.ModeDir | fs.ModePerm}) for _, c := range n.children { wg.Add(1) go c.getchildren(p, m, wg) } } else { m.Store(p, &fstest.MapFile{Data: []byte(p), Mode: fs.ModePerm}) } wg.Done() } func getFS(depth, width int) fstest.MapFS { var nodes = &Node{ "", createNodes(depth, width), } var m = sync.Map{} var wg = sync.WaitGroup{} wg.Add(1) go nodes.getchildren("", &m, &wg) wg.Wait() var fs = make(fstest.MapFS) m.Range(func(key, value interface{}) bool { fs[key.(string)] = value.(*fstest.MapFile) return true }) return fs } func name(i int) string { var output string for { if i < 26 { output = output + string(al[i]) break } output += string(al[i%26]) i = (i - (i % 26)) / 26 } return output } func createNodes(depth, width int) (n []*Node) { if depth != 0 { for i := 0; i < width; i++ { n = append(n, &Node{string(name(i)), createNodes(depth-1, width)}) } } return } func toMap(routes gin.RoutesInfo) (m map[string]gin.RouteInfo) { m = make(map[string]gin.RouteInfo) for _, r := range routes { m[r.Path] = r } return } func TestStaticFS(t *testing.T) { t.Parallel() var ( r = gin.New() rg = r.Group("") fs fstest.MapFS = getFS(5, 10) ) funcs.StaticFS(rg, &fs) routes := toMap(r.Routes()) t.Log(routes) for path, node := range fs { if node.Mode.IsDir() { continue } _, found := routes["/"+path] if !found { t.Errorf("Path %s was not handled", path) } } } func BenchmarkStaticFS(b *testing.B) { ro := gin.New() fs := getFS(52, 2) b.ResetTimer() for i := 0; i < b.N; i++ { g := ro.Group(fmt.Sprint(i)) funcs.StaticFS(g, fs) } }