common_test.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. package minify // import "github.com/tdewolff/minify"
  2. import (
  3. "fmt"
  4. "io"
  5. "io/ioutil"
  6. "math"
  7. "math/rand"
  8. "strconv"
  9. "testing"
  10. "github.com/tdewolff/test"
  11. )
  12. func TestContentType(t *testing.T) {
  13. contentTypeTests := []struct {
  14. contentType string
  15. expected string
  16. }{
  17. {"text/html", "text/html"},
  18. {"text/html; charset=UTF-8", "text/html;charset=utf-8"},
  19. {"text/html; charset=UTF-8 ; param = \" ; \"", "text/html;charset=utf-8;param=\" ; \""},
  20. {"text/html, text/css", "text/html,text/css"},
  21. }
  22. for _, tt := range contentTypeTests {
  23. t.Run(tt.contentType, func(t *testing.T) {
  24. contentType := ContentType([]byte(tt.contentType))
  25. test.Minify(t, tt.contentType, nil, string(contentType), tt.expected)
  26. })
  27. }
  28. }
  29. func TestDataURI(t *testing.T) {
  30. dataURITests := []struct {
  31. dataURI string
  32. expected string
  33. }{
  34. {"data:,text", "data:,text"},
  35. {"data:text/plain;charset=us-ascii,text", "data:,text"},
  36. {"data:TEXT/PLAIN;CHARSET=US-ASCII,text", "data:,text"},
  37. {"data:text/plain;charset=us-asciiz,text", "data:;charset=us-asciiz,text"},
  38. {"data:;base64,dGV4dA==", "data:,text"},
  39. {"data:text/svg+xml;base64,PT09PT09", "data:text/svg+xml;base64,PT09PT09"},
  40. {"data:text/xml;version=2.0,content", "data:text/xml;version=2.0,content"},
  41. {"data:text/xml; version = 2.0,content", "data:text/xml;version=2.0,content"},
  42. {"data:,=====", "data:,%3D%3D%3D%3D%3D"},
  43. {"data:,======", "data:;base64,PT09PT09"},
  44. {"data:text/x,<?x?>", "data:text/x,%3C%3Fx%3F%3E"},
  45. }
  46. m := New()
  47. m.AddFunc("text/x", func(_ *M, w io.Writer, r io.Reader, _ map[string]string) error {
  48. b, _ := ioutil.ReadAll(r)
  49. test.String(t, string(b), "<?x?>")
  50. w.Write(b)
  51. return nil
  52. })
  53. for _, tt := range dataURITests {
  54. t.Run(tt.dataURI, func(t *testing.T) {
  55. dataURI := DataURI(m, []byte(tt.dataURI))
  56. test.Minify(t, tt.dataURI, nil, string(dataURI), tt.expected)
  57. })
  58. }
  59. }
  60. func TestNumber(t *testing.T) {
  61. numberTests := []struct {
  62. number string
  63. expected string
  64. }{
  65. {"0", "0"},
  66. {".0", "0"},
  67. {"1.0", "1"},
  68. {"0.1", ".1"},
  69. {"+1", "1"},
  70. {"-1", "-1"},
  71. {"-0.1", "-.1"},
  72. {"10", "10"},
  73. {"100", "100"},
  74. {"1000", "1e3"},
  75. {"0.001", ".001"},
  76. {"0.0001", "1e-4"},
  77. {"100e1", "1e3"},
  78. {"1.1e+1", "11"},
  79. {"1.1e6", "11e5"},
  80. {"0.252", ".252"},
  81. {"1.252", "1.252"},
  82. {"-1.252", "-1.252"},
  83. {"0.075", ".075"},
  84. {"789012345678901234567890123456789e9234567890123456789", "789012345678901234567890123456789e9234567890123456789"},
  85. {".000100009", "100009e-9"},
  86. {".0001000009", ".0001000009"},
  87. {".0001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009", ".0001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009"},
  88. {"E\x1f", "E\x1f"}, // fuzz
  89. {"1e9223372036854775807", "1e9223372036854775807"},
  90. {"11e9223372036854775807", "11e9223372036854775807"},
  91. {".01e-9223372036854775808", ".01e-9223372036854775808"},
  92. {".011e-9223372036854775808", ".011e-9223372036854775808"},
  93. {".12345e8", "12345e3"},
  94. {".12345e7", "1234500"},
  95. {".12345e6", "123450"},
  96. {".12345e5", "12345"},
  97. {".012345e6", "12345"},
  98. {".12345e4", "1234.5"},
  99. {"-.12345e4", "-1234.5"},
  100. {".12345e0", ".12345"},
  101. {".12345e-1", ".012345"},
  102. {".12345e-2", ".0012345"},
  103. {".12345e-3", "12345e-8"},
  104. {".12345e-4", "12345e-9"},
  105. {".12345e-5", "12345e-10"},
  106. {".123456e-3", "123456e-9"},
  107. {".123456e-2", ".00123456"},
  108. {".1234567e-4", "1234567e-11"},
  109. {".1234567e-3", ".0001234567"},
  110. {"12345678e-1", "1234567.8"},
  111. {"72.e-3", ".072"},
  112. {"7640e-2", "76.4"},
  113. {"10.e-3", ".01"},
  114. {".0319e3", "31.9"},
  115. {"39.7e-2", ".397"},
  116. {"39.7e-3", ".0397"},
  117. {".01e1", ".1"},
  118. {".001e1", ".01"},
  119. {"39.7e-5", "397e-6"},
  120. }
  121. for _, tt := range numberTests {
  122. t.Run(tt.number, func(t *testing.T) {
  123. number := Number([]byte(tt.number), -1)
  124. test.Minify(t, tt.number, nil, string(number), tt.expected)
  125. })
  126. }
  127. }
  128. func TestNumberTruncate(t *testing.T) {
  129. numberTests := []struct {
  130. number string
  131. truncate int
  132. expected string
  133. }{
  134. {"0.1", 1, ".1"},
  135. {"0.0001", 1, "1e-4"},
  136. {"0.111", 1, ".1"},
  137. {"0.111", 0, "0"},
  138. {"0.075", 1, ".1"},
  139. {"0.025", 1, "0"},
  140. {"9.99", 1, "10"},
  141. {"8.88", 1, "8.9"},
  142. {"8.88", 0, "9"},
  143. {"8.00", 0, "8"},
  144. {".88", 0, "1"},
  145. {"1.234", 1, "1.2"},
  146. {"33.33", 0, "33"},
  147. {"29.666", 0, "30"},
  148. {"1.51", 1, "1.5"},
  149. }
  150. for _, tt := range numberTests {
  151. t.Run(tt.number, func(t *testing.T) {
  152. number := Number([]byte(tt.number), tt.truncate)
  153. test.Minify(t, tt.number, nil, string(number), tt.expected, "truncate to", tt.truncate)
  154. })
  155. }
  156. }
  157. func TestNumberRandom(t *testing.T) {
  158. N := int(1e4)
  159. if testing.Short() {
  160. N = 0
  161. }
  162. for i := 0; i < N; i++ {
  163. b := RandNumBytes()
  164. f, _ := strconv.ParseFloat(string(b), 64)
  165. b2 := make([]byte, len(b))
  166. copy(b2, b)
  167. b2 = Number(b2, -1)
  168. f2, _ := strconv.ParseFloat(string(b2), 64)
  169. if math.Abs(f-f2) > 1e-6 {
  170. fmt.Println("Bad:", f, "!=", f2, "in", string(b), "to", string(b2))
  171. }
  172. }
  173. }
  174. ////////////////
  175. var n = 100
  176. var numbers [][]byte
  177. func TestMain(t *testing.T) {
  178. numbers = make([][]byte, 0, n)
  179. for j := 0; j < n; j++ {
  180. numbers = append(numbers, RandNumBytes())
  181. }
  182. }
  183. func RandNumBytes() []byte {
  184. var b []byte
  185. n := rand.Int() % 10
  186. for i := 0; i < n; i++ {
  187. b = append(b, byte(rand.Int()%10)+'0')
  188. }
  189. if rand.Int()%2 == 0 {
  190. b = append(b, '.')
  191. n = rand.Int() % 10
  192. for i := 0; i < n; i++ {
  193. b = append(b, byte(rand.Int()%10)+'0')
  194. }
  195. }
  196. if rand.Int()%2 == 0 {
  197. b = append(b, 'e')
  198. if rand.Int()%2 == 0 {
  199. b = append(b, '-')
  200. }
  201. n = 1 + rand.Int()%4
  202. for i := 0; i < n; i++ {
  203. b = append(b, byte(rand.Int()%10)+'0')
  204. }
  205. }
  206. return b
  207. }
  208. func BenchmarkNumber(b *testing.B) {
  209. for i := 0; i < b.N; i++ {
  210. for j := 0; j < n; j++ {
  211. Number(numbers[j], -1)
  212. }
  213. }
  214. }
  215. func BenchmarkNumber2(b *testing.B) {
  216. num := []byte("1.2345e-6")
  217. for i := 0; i < b.N; i++ {
  218. Number(num, -1)
  219. }
  220. }