選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

glob_test.go 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright (c) 2020 Shivaram Lingamneni <slingamn@cs.stanford.edu>
  2. // released under the MIT license
  3. package utils
  4. import (
  5. "regexp"
  6. "testing"
  7. )
  8. func globMustCompile(glob string) *regexp.Regexp {
  9. re, err := CompileGlob(glob, false)
  10. if err != nil {
  11. panic(err)
  12. }
  13. return re
  14. }
  15. func assertMatches(glob, str string, match bool, t *testing.T) {
  16. re := globMustCompile(glob)
  17. if re.MatchString(str) != match {
  18. t.Errorf("should %s match %s? %t, but got %t instead", glob, str, match, !match)
  19. }
  20. }
  21. func TestGlob(t *testing.T) {
  22. assertMatches("https://testnet.oragono.io", "https://testnet.oragono.io", true, t)
  23. assertMatches("https://*.oragono.io", "https://testnet.oragono.io", true, t)
  24. assertMatches("*://*.oragono.io", "https://testnet.oragono.io", true, t)
  25. assertMatches("*://*.oragono.io", "https://oragono.io", false, t)
  26. assertMatches("*://*.oragono.io", "https://githubusercontent.com", false, t)
  27. assertMatches("*://*.oragono.io", "https://testnet.oragono.io.example.com", false, t)
  28. assertMatches("", "", true, t)
  29. assertMatches("", "x", false, t)
  30. assertMatches("*", "", true, t)
  31. assertMatches("*", "x", true, t)
  32. assertMatches("c?b", "cab", true, t)
  33. assertMatches("c?b", "cub", true, t)
  34. assertMatches("c?b", "cb", false, t)
  35. assertMatches("c?b", "cube", false, t)
  36. assertMatches("?*", "cube", true, t)
  37. assertMatches("?*", "", false, t)
  38. assertMatches("S*e", "Skåne", true, t)
  39. assertMatches("Sk?ne", "Skåne", true, t)
  40. }
  41. func BenchmarkGlob(b *testing.B) {
  42. g := globMustCompile("https://*google.com")
  43. b.ResetTimer()
  44. for i := 0; i < b.N; i++ {
  45. g.MatchString("https://www.google.com")
  46. }
  47. }
  48. func BenchmarkGlobCompilation(b *testing.B) {
  49. for i := 0; i < b.N; i++ {
  50. CompileGlob("https://*google.com", false)
  51. }
  52. }
  53. // these are actual bans from my production network :-/
  54. var bans = []string{
  55. "*!*@tor-network.onion",
  56. "`!*@*",
  57. "qanon!*@*",
  58. "*!bibi@tor-network.onion",
  59. "shivarm!*@*",
  60. "8====d!*@*",
  61. "shiviram!*@*",
  62. "poop*!*@*",
  63. "shivoram!*@*",
  64. "shivvy!*@*",
  65. "shavirim!*@*",
  66. "shivarm_!*@*",
  67. "_!*@*",
  68. }
  69. func TestMasks(t *testing.T) {
  70. matcher, err := CompileMasks(bans)
  71. if err != nil {
  72. panic(err)
  73. }
  74. if !matcher.MatchString("evan!user@tor-network.onion") {
  75. t.Errorf("match expected")
  76. }
  77. if !matcher.MatchString("`!evan@b9un4fv3he44q.example.com") {
  78. t.Errorf("match expected")
  79. }
  80. if matcher.MatchString("horse!horse@t5dwi8vacg47y.example.com") {
  81. t.Errorf("match not expected")
  82. }
  83. if matcher.MatchString("horse_!horse@t5dwi8vacg47y.example.com") {
  84. t.Errorf("match not expected")
  85. }
  86. if matcher.MatchString("shivaram!shivaram@yrqgsrjy2p7my.example.com") {
  87. t.Errorf("match not expected")
  88. }
  89. }
  90. func BenchmarkMasksCompile(b *testing.B) {
  91. for i := 0; i < b.N; i++ {
  92. CompileMasks(bans)
  93. }
  94. }
  95. func BenchmarkMasksMatch(b *testing.B) {
  96. matcher, _ := CompileMasks(bans)
  97. b.ResetTimer()
  98. for i := 0; i < b.N; i++ {
  99. matcher.MatchString("evan!user@tor-network.onion")
  100. matcher.MatchString("horse_!horse@t5dwi8vacg47y.example.com")
  101. matcher.MatchString("shivaram!shivaram@yrqgsrjy2p7my.example.com")
  102. }
  103. }
  104. // compare performance to compilation of the | clauses as separate regexes
  105. // first for compilation, then for matching
  106. func compileAll(masks []string) (result []*regexp.Regexp, err error) {
  107. a := make([]*regexp.Regexp, 0, len(masks))
  108. for _, mask := range masks {
  109. m, err := CompileGlob(mask, false)
  110. if err != nil {
  111. return nil, err
  112. }
  113. a = append(a, m)
  114. }
  115. return a, nil
  116. }
  117. func matchesAny(masks []*regexp.Regexp, str string) bool {
  118. for _, r := range masks {
  119. if r.MatchString(str) {
  120. return true
  121. }
  122. }
  123. return false
  124. }
  125. func BenchmarkLinearCompile(b *testing.B) {
  126. for i := 0; i < b.N; i++ {
  127. compileAll(bans)
  128. }
  129. }
  130. func BenchmarkLinearMatch(b *testing.B) {
  131. a, err := compileAll(bans)
  132. if err != nil {
  133. panic(err)
  134. }
  135. if matchesAny(a, "horse_!horse@t5dwi8vacg47y.example.com") {
  136. panic("incorrect match")
  137. }
  138. if !matchesAny(a, "evan!user@tor-network.onion") {
  139. panic("incorrect match")
  140. }
  141. b.ResetTimer()
  142. for i := 0; i < b.N; i++ {
  143. matchesAny(a, "horse_!horse@t5dwi8vacg47y.example.com")
  144. matchesAny(a, "evan!user@tor-network.onion")
  145. matchesAny(a, "shivaram!shivaram@yrqgsrjy2p7my.example.com")
  146. }
  147. }