1package parse 2 3import ( 4 "encoding/base64" 5 "mime" 6 "testing" 7 8 "github.com/tdewolff/test" 9) 10 11func TestParseNumber(t *testing.T) { 12 var numberTests = []struct { 13 number string 14 expected int 15 }{ 16 {"5", 1}, 17 {"0.51", 4}, 18 {"0.5e-99", 7}, 19 {"0.5e-", 3}, 20 {"+50.0", 5}, 21 {".0", 2}, 22 {"0.", 1}, 23 {"", 0}, 24 {"+", 0}, 25 {".", 0}, 26 {"a", 0}, 27 } 28 for _, tt := range numberTests { 29 t.Run(tt.number, func(t *testing.T) { 30 n := Number([]byte(tt.number)) 31 test.T(t, n, tt.expected) 32 }) 33 } 34} 35 36func TestParseDimension(t *testing.T) { 37 var dimensionTests = []struct { 38 dimension string 39 expectedNum int 40 expectedUnit int 41 }{ 42 {"5px", 1, 2}, 43 {"5px ", 1, 2}, 44 {"5%", 1, 1}, 45 {"5em", 1, 2}, 46 {"px", 0, 0}, 47 {"1", 1, 0}, 48 {"1~", 1, 0}, 49 } 50 for _, tt := range dimensionTests { 51 t.Run(tt.dimension, func(t *testing.T) { 52 num, unit := Dimension([]byte(tt.dimension)) 53 test.T(t, num, tt.expectedNum, "number") 54 test.T(t, unit, tt.expectedUnit, "unit") 55 }) 56 } 57} 58 59func TestMediatype(t *testing.T) { 60 var mediatypeTests = []struct { 61 mediatype string 62 expectedMimetype string 63 expectedParams map[string]string 64 }{ 65 {"text/plain", "text/plain", nil}, 66 {"text/plain;charset=US-ASCII", "text/plain", map[string]string{"charset": "US-ASCII"}}, 67 {" text/plain ; charset = US-ASCII ", "text/plain", map[string]string{"charset": "US-ASCII"}}, 68 {" text/plain a", "text/plain", nil}, 69 {"text/plain;base64", "text/plain", map[string]string{"base64": ""}}, 70 {"text/plain;inline=;base64", "text/plain", map[string]string{"inline": "", "base64": ""}}, 71 {"ÿ ", "ÿ ", nil}, // OSS-Fuzz; ÿ is two bytes in UTF8 72 {"ÿ ;", "ÿ ", map[string]string{"": ""}}, 73 } 74 for _, tt := range mediatypeTests { 75 t.Run(tt.mediatype, func(t *testing.T) { 76 mimetype, params := Mediatype([]byte(tt.mediatype)) 77 test.String(t, string(mimetype), tt.expectedMimetype, "mimetype") 78 test.T(t, params, tt.expectedParams, "parameters") // TODO 79 }) 80 } 81} 82 83func TestParseDataURI(t *testing.T) { 84 var dataURITests = []struct { 85 dataURI string 86 expectedMimetype string 87 expectedData string 88 expectedErr error 89 }{ 90 {"www.domain.com", "", "", ErrBadDataURI}, 91 {"data:,", "text/plain", "", nil}, 92 {"data:text/xml,", "text/xml", "", nil}, 93 {"data:,text", "text/plain", "text", nil}, 94 {"data:;base64,dGV4dA==", "text/plain", "text", nil}, 95 {"data:image/svg+xml,", "image/svg+xml", "", nil}, 96 {"data:;base64,()", "", "", base64.CorruptInputError(0)}, 97 {"data:image/svg+xml,%3Cpath%20stroke-width='9.38%'/%3E", "image/svg+xml", "<path stroke-width='9.38%'/>", nil}, 98 {"data:,%ii", "text/plain", "%ii", nil}, 99 } 100 for _, tt := range dataURITests { 101 t.Run(tt.dataURI, func(t *testing.T) { 102 mimetype, data, err := DataURI([]byte(tt.dataURI)) 103 test.T(t, err, tt.expectedErr) 104 test.String(t, string(mimetype), tt.expectedMimetype, "mimetype") 105 test.String(t, string(data), tt.expectedData, "data") 106 }) 107 } 108} 109 110func TestParseQuoteEntity(t *testing.T) { 111 var quoteEntityTests = []struct { 112 quoteEntity string 113 expectedQuote byte 114 expectedN int 115 }{ 116 {""", '"', 5}, 117 {"'", '\'', 6}, 118 {""", '"', 8}, 119 {"'", '\'', 6}, 120 {""", '"', 6}, 121 {"'", '\'', 6}, 122 {">", 0x00, 0}, 123 {"&", 0x00, 0}, 124 } 125 for _, tt := range quoteEntityTests { 126 t.Run(tt.quoteEntity, func(t *testing.T) { 127 quote, n := QuoteEntity([]byte(tt.quoteEntity)) 128 test.T(t, quote, tt.expectedQuote, "quote") 129 test.T(t, n, tt.expectedN, "quote length") 130 }) 131 } 132} 133 134//////////////////////////////////////////////////////////////// 135 136func BenchmarkParseMediatypeStd(b *testing.B) { 137 mediatype := "text/plain" 138 for i := 0; i < b.N; i++ { 139 mime.ParseMediaType(mediatype) 140 } 141} 142 143func BenchmarkParseMediatypeParamStd(b *testing.B) { 144 mediatype := "text/plain;inline=1" 145 for i := 0; i < b.N; i++ { 146 mime.ParseMediaType(mediatype) 147 } 148} 149 150func BenchmarkParseMediatypeParamsStd(b *testing.B) { 151 mediatype := "text/plain;charset=US-ASCII;language=US-EN;compression=gzip;base64" 152 for i := 0; i < b.N; i++ { 153 mime.ParseMediaType(mediatype) 154 } 155} 156 157func BenchmarkParseMediatypeParse(b *testing.B) { 158 mediatype := []byte("text/plain") 159 for i := 0; i < b.N; i++ { 160 Mediatype(mediatype) 161 } 162} 163 164func BenchmarkParseMediatypeParamParse(b *testing.B) { 165 mediatype := []byte("text/plain;inline=1") 166 for i := 0; i < b.N; i++ { 167 Mediatype(mediatype) 168 } 169} 170 171func BenchmarkParseMediatypeParamsParse(b *testing.B) { 172 mediatype := []byte("text/plain;charset=US-ASCII;language=US-EN;compression=gzip;base64") 173 for i := 0; i < b.N; i++ { 174 Mediatype(mediatype) 175 } 176} 177