func TestQueryQuery(t *testing.T) { inventory := New() query := Query{ RowKey: "Row", ColumnKey: "Column", } gFont := inventory.Query(query) test.VerifyFatal(t, 1, 0, true, nil == gFont) wFont := &font.Font{ Family: "Amaranth", Format: font.EOT, Path: filepath.Join(amf, "amaranth-regular.eot"), Style: "normal", Weight: 400, } inventory.Put("Amaranth", "woff400normal", wFont) query = Query{ RowKey: "Amaranth", ColumnKey: "woff400normal", } gFont = inventory.Query(query) test.VerifyFatal(t, 2, 0, false, nil == gFont) test.Verify(t, 3, 0, wFont.Family, gFont.Family) test.Verify(t, 4, 0, true, wFont.Format.Equal(gFont.Format)) test.Verify(t, 5, 0, wFont.Style, gFont.Style) test.Verify(t, 6, 0, wFont.Weight, gFont.Weight) test.Verify(t, 7, 0, wFont.Path, gFont.Path) }
func TestMakeGzipHandler(t *testing.T) { handler := MakeGzipHandler(helloHandler) server := httptest.NewServer(handler) defer server.Close() client := http.Client{} req, err := http.NewRequest("GET", server.URL, nil) test.VerifyFatal(t, 1, 0, true, nil == err) req.Header.Add("Accept-Encoding", "gzip") resp, err := client.Do(req) defer resp.Body.Close() test.VerifyFatal(t, 2, 0, true, nil == err) wContentEncoding := "gzip" gContentEncoding := resp.Header.Get("Content-Encoding") test.Verify(t, 3, 0, wContentEncoding, gContentEncoding) buf := new(bytes.Buffer) gzipWriter := gzip.NewWriter(buf) fmt.Fprint(gzipWriter, "Hej!") err = gzipWriter.Close() test.VerifyFatal(t, 4, 0, true, nil == err) wBody := buf.Bytes() gBody, err := ioutil.ReadAll(resp.Body) test.VerifyFatal(t, 5, 0, true, nil == err) test.Verify(t, 6, 0, true, bytes.Equal(wBody, gBody)) }
func TestFontContents(t *testing.T) { font := &Font{ Family: "Amaranth", Format: WOFF, Path: filepath.Join(amf, "amaranth-regular.woff"), Style: "normal", Weight: 400, } gContents, err := font.Contents() test.VerifyFatal(t, 1, 0, true, nil == err) wContents, err := ioutil.ReadFile(font.Path) test.VerifyFatal(t, 2, 0, true, nil == err) test.Verify(t, 3, 0, 0, bytes.Compare(wContents, gContents)) }
func TestFontModTime(t *testing.T) { font := &Font{ Family: "Amaranth", Format: WOFF, Path: filepath.Join(amf, "amaranth-regular.woff"), Style: "normal", Weight: 400, } gModTime, err := font.ModTime() test.VerifyFatal(t, 1, 0, true, nil == err) fi, err := os.Stat(font.Path) test.VerifyFatal(t, 2, 0, true, nil == err) wModTime := fi.ModTime() test.Verify(t, 3, 0, true, gModTime.Equal(wModTime)) }
func TestReadJson(t *testing.T) { type TestJson struct { Test string } testJson := &TestJson{} err := ReadJson(filepath.Join(td, "test.json"), testJson) test.VerifyFatal(t, 1, 0, true, nil == err) test.Verify(t, 2, 0, "json", testJson.Test) }
func TestWhitelistRead(t *testing.T) { gWhitelist := New() err := gWhitelist.Read(filepath.Join(td, "whitelist.json")) test.VerifyFatal(t, 1, 0, true, nil == err) wWhitelist := Whitelist{ Domains: []string{ "http://one/", "http://two/", "http://three/", }, } test.VerifyFatal(t, 2, 0, wWhitelist.Size(), gWhitelist.Size()) for i, wdomain := range wWhitelist.Domains { j := i + 1 gdomain := gWhitelist.Domains[i] test.Verify(t, 3, j, wdomain, gdomain) } }
func TestInventoryBuild(t *testing.T) { inventory := New() err := inventory.Build(fl) test.VerifyFatal(t, 1, 0, true, nil == err) wSize := len(InventoryBuildTestCases) test.VerifyFatal(t, 2, 0, wSize, inventory.Len()) for i, c := range InventoryBuildTestCases { j := i + 1 wFont := c.Font gFont := inventory.Query(c.Query) test.VerifyFatal(t, 3, j, false, nil == gFont) test.Verify(t, 4, j, wFont.Family, gFont.Family) test.Verify(t, 5, j, true, wFont.Format.Equal(gFont.Format)) test.Verify(t, 6, j, wFont.Style, gFont.Style) test.Verify(t, 7, j, wFont.Weight, gFont.Weight) test.Verify(t, 8, j, wFont.Path, gFont.Path) } }
func TestFontFaceFromFont(t *testing.T) { ff := &FontFace{} f := font.Font{ Family: "Amaranth", Format: font.WOFF, Path: filepath.Join(amf, "amaranth-regular.woff"), Style: "normal", Weight: 400, } err := ff.FromFont(f) test.VerifyFatal(t, 1, 0, true, nil == err) data, err := f.Contents() test.Verify(t, 2, 0, util.Base64(data), ff.Base64Data) test.Verify(t, 3, 0, f.Family, ff.Family) test.Verify(t, 4, 0, f.Format.String(), ff.Format) wMimeType := f.MimeType() test.VerifyFatal(t, 5, 0, false, "" == wMimeType) test.Verify(t, 6, 0, wMimeType, ff.MimeType) test.Verify(t, 7, 0, f.Style, ff.Style) test.Verify(t, 8, 0, f.Weight, ff.Weight) }
func TestQueries(t *testing.T) { for i, c := range QueriesCases { j := i + 1 gqueries := Queries(c.Family, c.Format) gqueriesSize := len(gqueries) wqueriesSize := len(c.Queries) test.VerifyFatal(t, 1, j, wqueriesSize, gqueriesSize) for k, wquery := range c.Queries { gquery := gqueries[k] test.Verify(t, 2, j, wquery.RowKey, gquery.RowKey) test.Verify(t, 3, j, gquery.ColumnKey, gquery.ColumnKey) } } }
func TestMetadataFonts(t *testing.T) { metadata := &Metadata{ Family: "Amaranth", Subfamilies: []Subfamily{ // Subfamily 1 Subfamily{ Basename: "amaranth-regular", Formats: []string{"eot", "woff"}, Style: "normal", Weight: 400, }, // Subfamily 2 Subfamily{ Basename: "amaranth-italic", Formats: []string{"eot", "woff"}, Style: "italic", Weight: 400, }, // Subfamily 3 Subfamily{ Basename: "amaranth-bold", Formats: []string{"eot", "woff"}, Style: "normal", Weight: 700, }, // Subfamily 4 Subfamily{ Basename: "amaranth-bolditalic", Formats: []string{"eot", "woff"}, Style: "italic", Weight: 700, }, }, path: filepath.Join(amf, "metadata.json"), } gFonts := metadata.Fonts() wFonts := []*Font{ // Font 1 &Font{ Family: "Amaranth", Format: EOT, Path: filepath.Join(amf, "amaranth-regular.eot"), Style: "normal", Weight: 400, }, // Font 2 &Font{ Family: "Amaranth", Format: WOFF, Path: filepath.Join(amf, "amaranth-regular.woff"), Style: "normal", Weight: 400, }, // Font 3 &Font{ Family: "Amaranth", Format: EOT, Path: filepath.Join(amf, "amaranth-italic.eot"), Style: "italic", Weight: 400, }, // Font 4 &Font{ Family: "Amaranth", Format: WOFF, Path: filepath.Join(amf, "amaranth-italic.woff"), Style: "italic", Weight: 400, }, // Font 5 &Font{ Family: "Amaranth", Format: EOT, Path: filepath.Join(amf, "amaranth-bold.eot"), Style: "normal", Weight: 700, }, // Font 6 &Font{ Family: "Amaranth", Format: WOFF, Path: filepath.Join(amf, "amaranth-bold.woff"), Style: "normal", Weight: 700, }, // Font 7 &Font{ Family: "Amaranth", Format: EOT, Path: filepath.Join(amf, "amaranth-bolditalic.eot"), Style: "italic", Weight: 700, }, // Font 8 &Font{ Family: "Amaranth", Format: WOFF, Path: filepath.Join(amf, "amaranth-bolditalic.woff"), Style: "italic", Weight: 700, }, } test.VerifyFatal(t, 1, 0, len(wFonts), len(gFonts)) for i, wFont := range wFonts { j := i + 1 gFont := gFonts[i] test.Verify(t, 2, j, wFont.Family, gFont.Family) test.Verify(t, 3, j, true, wFont.Format.Equal(gFont.Format)) test.Verify(t, 4, j, wFont.Path, gFont.Path) test.Verify(t, 5, j, wFont.Style, gFont.Style) test.Verify(t, 6, j, wFont.Weight, gFont.Weight) } }
func TestMetadataRead(t *testing.T) { gMetadata := new(Metadata) err := gMetadata.Read(filepath.Join(amf, "metadata.json")) test.VerifyFatal(t, 1, 0, true, nil == err) wMetadata := &Metadata{ Family: "Amaranth", Subfamilies: []Subfamily{ // Subfamily 1 Subfamily{ Basename: "amaranth-regular", Formats: []string{"eot", "woff"}, Style: "normal", Weight: 400, }, // Subfamily 2 Subfamily{ Basename: "amaranth-italic", Formats: []string{"eot", "woff"}, Style: "italic", Weight: 400, }, // Subfamily 3 Subfamily{ Basename: "amaranth-bold", Formats: []string{"eot", "woff"}, Style: "normal", Weight: 700, }, // Subfamily 4 Subfamily{ Basename: "amaranth-bolditalic", Formats: []string{"eot", "woff"}, Style: "italic", Weight: 700, }, }, path: filepath.Join(amf, "metadata.json"), } test.Verify(t, 2, 0, wMetadata.Family, gMetadata.Family) gSubfamilies := gMetadata.Subfamilies wSubfamilies := wMetadata.Subfamilies test.VerifyFatal(t, 3, 0, len(wSubfamilies), len(gSubfamilies)) for i, wSubfamily := range wMetadata.Subfamilies { j := i + 1 gSubfamily := gMetadata.Subfamilies[i] test.Verify(t, 4, j, wSubfamily.Basename, gSubfamily.Basename) gFormats := gSubfamily.Formats wFormats := wSubfamily.Formats test.VerifyFatal(t, 5, j, len(wFormats), len(gFormats)) for k, wFormat := range wFormats { gFormat := gFormats[k] test.Verify(t, 6, j, wFormat, gFormat) } test.Verify(t, 7, j, wSubfamily.Style, gSubfamily.Style) test.Verify(t, 8, j, wSubfamily.Weight, gSubfamily.Weight) } test.Verify(t, 9, 0, wMetadata.path, gMetadata.path) }
func TestCssHandler(t *testing.T) { type Request struct { Method string URL string } // Build an inventory. // Used in cases 6-7. inv := inventory.New() err := inv.Build(fl) test.VerifyFatal(t, 1, 0, true, err == nil) // Build an "allow all" whitelist. // Use this whitelist to allow all // referrers to fetch the resource. // Used in cases 3-7. aawl := whitelist.New() aawl.Domains = append(aawl.Domains, "") // Parse templates. // Used in cases 7-9. eot := filepath.Join(tp, "eot.css.tmpl") woff := filepath.Join(tp, "woff.css.tmpl") tmpl, err := template.ParseFiles(eot, woff) test.VerifyFatal(t, 2, 0, true, err == nil) // Execute template containing Amaranth Regular. // Used in case 7. ar := &font.Font{ Family: "Amaranth", Format: font.WOFF, Path: filepath.Join(amf, "amaranth-regular.woff"), Style: "normal", Weight: 400, } var tmplData []*FontFace data, err := ar.Contents() test.VerifyFatal(t, 3, 0, true, err == nil) mimeType := ar.MimeType() test.VerifyFatal(t, 4, 0, false, "" == mimeType) arff := &FontFace{ Base64Data: util.Base64(data), Family: ar.Family, Format: ar.Format.String(), MimeType: mimeType, Style: ar.Style, Weight: ar.Weight, } buf := new(bytes.Buffer) tmplName := ar.Format.String() + ".css.tmpl" tmplData = append(tmplData, arff) err = tmpl.ExecuteTemplate(buf, tmplName, tmplData) test.VerifyFatal(t, 5, 0, true, nil == err) arBody := buf.Bytes() // Generate the entity tag corresponding to Amaranth Regular. // Uncompressed response. // Used in case 7. hash := md5.New() modtime, err := ar.ModTime() test.VerifyFatal(t, 6, 0, true, nil == err) io.WriteString(hash, modtime.String()) arEtag := fmt.Sprintf("%x", hash.Sum(nil)) // Gzip compressed response. // Used in cases 8-9. arEtagGzip := arEtag + "+gzip" var cases = []struct { Body []byte Context HandlerContext Header map[string]string IfNoneMatch string // If-None-Match client request header. Request *Request StatusCode int }{ // Case 1 { Header: map[string]string{ "Content-Type": "text/plain; charset=utf-8", }, Request: &Request{ Method: "POST", URL: "", }, StatusCode: http.StatusNotImplemented, }, // Case 2 { Header: map[string]string{ "Content-Type": "text/plain; charset=utf-8", }, Request: &Request{ Method: "GET", URL: "", }, StatusCode: http.StatusForbidden, }, // Case 3 { Context: HandlerContext{ Whitelist: *aawl, }, Header: map[string]string{ "Content-Type": "text/plain; charset=utf-8", }, Request: &Request{ Method: "GET", URL: "?family=", }, StatusCode: http.StatusBadRequest, }, // Case 4 { Context: HandlerContext{ Whitelist: *aawl, }, Header: map[string]string{ "Content-Type": "text/plain; charset=utf-8", }, Request: &Request{ Method: "GET", URL: "?family=Amaranth&format=nonexistent", }, StatusCode: http.StatusBadRequest, }, // Case 5 { Context: HandlerContext{ Whitelist: *aawl, }, Header: map[string]string{ "Content-Type": "text/plain; charset=utf-8", }, Request: &Request{ Method: "GET", URL: "?family=|Amaranth", }, StatusCode: http.StatusBadRequest, }, // Case 6 { Context: HandlerContext{ Flags: Flags{ Etag: true, }, Inventory: *inv, Whitelist: *aawl, }, Header: map[string]string{ "Content-Type": "text/plain; charset=utf-8", "Etag": "", }, Request: &Request{ Method: "GET", URL: "?family=Nonexistent", }, StatusCode: http.StatusBadRequest, }, // Case 7 { Body: arBody, Context: HandlerContext{ Flags: Flags{ CcMaxAge: 2592000, Etag: true, }, Inventory: *inv, Templates: *tmpl, Whitelist: *aawl, }, Header: map[string]string{ "Cache-Control": "max-age=2592000", "Content-Type": "text/css; charset=utf-8", "Etag": arEtag, }, Request: &Request{ Method: "GET", URL: "?family=Amaranth", }, StatusCode: http.StatusOK, }, // Case 8 { Body: arBody, Context: HandlerContext{ Flags: Flags{ Etag: true, Gzip: true, }, Inventory: *inv, Templates: *tmpl, Whitelist: *aawl, }, Header: map[string]string{ "Cache-Control": "max-age=0", "Content-Type": "text/css; charset=utf-8", "Etag": arEtagGzip, }, Request: &Request{ Method: "GET", URL: "?family=Amaranth", }, StatusCode: http.StatusOK, }, // Case 9 { Context: HandlerContext{ Flags: Flags{ Etag: true, Gzip: true, }, Inventory: *inv, Templates: *tmpl, Whitelist: *aawl, }, Header: map[string]string{ "Cache-Control": "max-age=0", "Etag": arEtagGzip, }, IfNoneMatch: arEtagGzip, Request: &Request{ Method: "GET", URL: "?family=Amaranth", }, StatusCode: http.StatusNotModified, }, } for i, c := range cases { j := i + 1 handler := MakeHandler(CssHandler, c.Context) server := httptest.NewServer(handler) defer server.Close() client := http.Client{} reqURL := server.URL + c.Request.URL req, err := http.NewRequest(c.Request.Method, reqURL, nil) test.VerifyFatal(t, 6, j, true, nil == err) if c.IfNoneMatch != "" { req.Header.Add("If-None-Match", c.IfNoneMatch) } resp, err := client.Do(req) defer resp.Body.Close() test.VerifyFatal(t, 7, j, true, nil == err) test.Verify(t, 8, j, c.StatusCode, resp.StatusCode) wContentType := c.Header["Content-Type"] gContentType := resp.Header.Get("Content-Type") test.Verify(t, 9, j, wContentType, gContentType) wCacheControl := c.Header["Cache-Control"] gCacheControl := resp.Header.Get("Cache-Control") test.Verify(t, 10, j, wCacheControl, gCacheControl) wEtag := c.Header["Etag"] gEtag := resp.Header.Get("Etag") test.Verify(t, 11, j, wEtag, gEtag) if (c.StatusCode == http.StatusOK) && (resp.StatusCode == http.StatusOK) { gbody, err := ioutil.ReadAll(resp.Body) test.VerifyFatal(t, 13, j, true, nil == err) wbody := c.Body test.Verify(t, 14, j, true, bytes.Equal(wbody, gbody)) } } }
func TestMakeHandler(t *testing.T) { var cases = []struct { Context HandlerContext Header map[string]string }{ // Case 1 { Context: HandlerContext{ Flags: Flags{ AcAllowOrigin: false, Gzip: true, Version: "test/0.1", }, }, Header: map[string]string{ "Server": "test/0.1", "Vary": "Accept-Encoding", }, }, // Case 2 { Context: HandlerContext{ Flags: Flags{ AcAllowOrigin: true, Gzip: false, Version: "test/0.1", }, }, Header: map[string]string{ "Access-Control-Allow-Origin": "*", "Server": "test/0.1", }, }, // Case 3 { Context: HandlerContext{ Flags: Flags{ AcAllowOrigin: false, Gzip: true, Version: "", }, }, Header: map[string]string{ "Vary": "Accept-Encoding", }, }, // Case 4 { Context: HandlerContext{ Flags: Flags{}, }, Header: map[string]string{}, }, } for i, c := range cases { j := i + 1 handler := MakeHandler(emptyHandler, c.Context) server := httptest.NewServer(handler) defer server.Close() client := http.Client{} resp, err := client.Get(server.URL) defer resp.Body.Close() test.VerifyFatal(t, 1, j, true, nil == err) wHeader := c.Header gHeader := resp.Header test.Verify(t, 2, j, wHeader["Server"], gHeader.Get("Server")) test.Verify(t, 3, j, wHeader["Vary"], gHeader.Get("Vary")) wAcAllowOrigin := wHeader["Access-Control-Allow-Origin"] gAcAllowOrigin := gHeader.Get("Access-Control-Allow-Origin") test.Verify(t, 4, j, wAcAllowOrigin, gAcAllowOrigin) } }