exprlib_test.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. package exprhelpers
  2. import (
  3. "fmt"
  4. log "github.com/sirupsen/logrus"
  5. "testing"
  6. "github.com/antonmedv/expr"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/stretchr/testify/require"
  9. )
  10. var (
  11. TestFolder = "tests"
  12. )
  13. func TestVisitor(t *testing.T) {
  14. if err := Init(); err != nil {
  15. log.Fatalf(err.Error())
  16. }
  17. tests := []struct {
  18. name string
  19. filter string
  20. result bool
  21. env map[string]interface{}
  22. err error
  23. }{
  24. {
  25. name: "debug : no variable",
  26. filter: "'crowdsec' startsWith 'crowdse'",
  27. result: true,
  28. err: nil,
  29. env: map[string]interface{}{},
  30. },
  31. {
  32. name: "debug : simple variable",
  33. filter: "'crowdsec' startsWith static_one && 1 == 1",
  34. result: true,
  35. err: nil,
  36. env: map[string]interface{}{"static_one": string("crowdse")},
  37. },
  38. {
  39. name: "debug : simple variable re-used",
  40. filter: "static_one.foo == 'bar' && static_one.foo != 'toto'",
  41. result: true,
  42. err: nil,
  43. env: map[string]interface{}{"static_one": map[string]string{"foo": "bar"}},
  44. },
  45. {
  46. name: "debug : can't compile",
  47. filter: "static_one.foo.toto == 'lol'",
  48. result: false,
  49. err: fmt.Errorf("bad syntax"),
  50. env: map[string]interface{}{"static_one": map[string]string{"foo": "bar"}},
  51. },
  52. {
  53. name: "debug : can't compile #2",
  54. filter: "static_one.f!oo.to/to == 'lol'",
  55. result: false,
  56. err: fmt.Errorf("bad syntax"),
  57. env: map[string]interface{}{"static_one": map[string]string{"foo": "bar"}},
  58. },
  59. {
  60. name: "debug : can't compile #3",
  61. filter: "",
  62. result: false,
  63. err: fmt.Errorf("bad syntax"),
  64. env: map[string]interface{}{"static_one": map[string]string{"foo": "bar"}},
  65. },
  66. }
  67. log.SetLevel(log.DebugLevel)
  68. clog := log.WithFields(log.Fields{
  69. "type": "test",
  70. })
  71. for _, test := range tests {
  72. compiledFilter, err := expr.Compile(test.filter, expr.Env(GetExprEnv(test.env)))
  73. if err != nil && test.err == nil {
  74. log.Fatalf("compile: %s", err.Error())
  75. }
  76. debugFilter, err := NewDebugger(test.filter, expr.Env(GetExprEnv(test.env)))
  77. if err != nil && test.err == nil {
  78. log.Fatalf("debug: %s", err.Error())
  79. }
  80. if compiledFilter != nil {
  81. result, err := expr.Run(compiledFilter, GetExprEnv(test.env))
  82. if err != nil && test.err == nil {
  83. log.Fatalf("run : %s", err.Error())
  84. }
  85. if isOk := assert.Equal(t, test.result, result); !isOk {
  86. t.Fatalf("test '%s' : NOK", test.filter)
  87. }
  88. }
  89. if debugFilter != nil {
  90. debugFilter.Run(clog, test.result, GetExprEnv(test.env))
  91. }
  92. }
  93. }
  94. func TestRegexpInFile(t *testing.T) {
  95. if err := Init(); err != nil {
  96. log.Fatalf(err.Error())
  97. }
  98. err := FileInit(TestFolder, "test_data_re.txt", "regex")
  99. if err != nil {
  100. log.Fatalf(err.Error())
  101. }
  102. tests := []struct {
  103. name string
  104. filter string
  105. result bool
  106. err error
  107. }{
  108. {
  109. name: "RegexpInFile() test: lower case word in data file",
  110. filter: "RegexpInFile('crowdsec', 'test_data_re.txt')",
  111. result: false,
  112. err: nil,
  113. },
  114. {
  115. name: "RegexpInFile() test: Match exactly",
  116. filter: "RegexpInFile('Crowdsec', 'test_data_re.txt')",
  117. result: true,
  118. err: nil,
  119. },
  120. {
  121. name: "RegexpInFile() test: match with word before",
  122. filter: "RegexpInFile('test Crowdsec', 'test_data_re.txt')",
  123. result: true,
  124. err: nil,
  125. },
  126. {
  127. name: "RegexpInFile() test: match with word before and other case",
  128. filter: "RegexpInFile('test CrowdSec', 'test_data_re.txt')",
  129. result: true,
  130. err: nil,
  131. },
  132. }
  133. for _, test := range tests {
  134. compiledFilter, err := expr.Compile(test.filter, expr.Env(GetExprEnv(map[string]interface{}{})))
  135. if err != nil {
  136. log.Fatalf(err.Error())
  137. }
  138. result, err := expr.Run(compiledFilter, GetExprEnv(map[string]interface{}{}))
  139. if err != nil {
  140. log.Fatalf(err.Error())
  141. }
  142. if isOk := assert.Equal(t, test.result, result); !isOk {
  143. t.Fatalf("test '%s' : NOK", test.name)
  144. }
  145. }
  146. }
  147. func TestFile(t *testing.T) {
  148. if err := Init(); err != nil {
  149. log.Fatalf(err.Error())
  150. }
  151. err := FileInit(TestFolder, "test_data.txt", "string")
  152. if err != nil {
  153. log.Fatalf(err.Error())
  154. }
  155. tests := []struct {
  156. name string
  157. filter string
  158. result bool
  159. err error
  160. }{
  161. {
  162. name: "File() test: word in file",
  163. filter: "'Crowdsec' in File('test_data.txt')",
  164. result: true,
  165. err: nil,
  166. },
  167. {
  168. name: "File() test: word in file but different case",
  169. filter: "'CrowdSecurity' in File('test_data.txt')",
  170. result: false,
  171. err: nil,
  172. },
  173. {
  174. name: "File() test: word not in file",
  175. filter: "'test' in File('test_data.txt')",
  176. result: false,
  177. err: nil,
  178. },
  179. {
  180. name: "File() test: filepath provided doesn't exist",
  181. filter: "'test' in File('non_existing_data.txt')",
  182. result: false,
  183. err: nil,
  184. },
  185. }
  186. for _, test := range tests {
  187. compiledFilter, err := expr.Compile(test.filter, expr.Env(GetExprEnv(map[string]interface{}{})))
  188. if err != nil {
  189. log.Fatalf(err.Error())
  190. }
  191. result, err := expr.Run(compiledFilter, GetExprEnv(map[string]interface{}{}))
  192. if err != nil {
  193. log.Fatalf(err.Error())
  194. }
  195. if isOk := assert.Equal(t, test.result, result); !isOk {
  196. t.Fatalf("test '%s' : NOK", test.name)
  197. }
  198. log.Printf("test '%s' : OK", test.name)
  199. }
  200. }
  201. func TestIpInRange(t *testing.T) {
  202. tests := []struct {
  203. name string
  204. env map[string]interface{}
  205. code string
  206. result bool
  207. err string
  208. }{
  209. {
  210. name: "IpInRange() test: basic test",
  211. env: map[string]interface{}{
  212. "ip": "192.168.0.1",
  213. "ipRange": "192.168.0.0/24",
  214. "IpInRange": IpInRange,
  215. },
  216. code: "IpInRange(ip, ipRange)",
  217. result: true,
  218. err: "",
  219. },
  220. {
  221. name: "IpInRange() test: malformed IP",
  222. env: map[string]interface{}{
  223. "ip": "192.168.0",
  224. "ipRange": "192.168.0.0/24",
  225. "IpInRange": IpInRange,
  226. },
  227. code: "IpInRange(ip, ipRange)",
  228. result: false,
  229. err: "",
  230. },
  231. {
  232. name: "IpInRange() test: malformed IP range",
  233. env: map[string]interface{}{
  234. "ip": "192.168.0.0/255",
  235. "ipRange": "192.168.0.0/24",
  236. "IpInRange": IpInRange,
  237. },
  238. code: "IpInRange(ip, ipRange)",
  239. result: false,
  240. err: "",
  241. },
  242. }
  243. for _, test := range tests {
  244. program, err := expr.Compile(test.code, expr.Env(test.env))
  245. require.NoError(t, err)
  246. output, err := expr.Run(program, test.env)
  247. require.NoError(t, err)
  248. require.Equal(t, test.result, output)
  249. log.Printf("test '%s' : OK", test.name)
  250. }
  251. }
  252. func TestAtof(t *testing.T) {
  253. testFloat := "1.5"
  254. expectedFloat := 1.5
  255. if Atof(testFloat) != expectedFloat {
  256. t.Fatalf("Atof should returned 1.5 as a float")
  257. }
  258. log.Printf("test 'Atof()' : OK")
  259. //bad float
  260. testFloat = "1aaa.5"
  261. expectedFloat = 0.0
  262. if Atof(testFloat) != expectedFloat {
  263. t.Fatalf("Atof should returned a negative value (error) as a float got")
  264. }
  265. log.Printf("test 'Atof()' : OK")
  266. }
  267. func TestUpper(t *testing.T) {
  268. testStr := "test"
  269. expectedStr := "TEST"
  270. if Upper(testStr) != expectedStr {
  271. t.Fatalf("Upper() should returned 1.5 as a float")
  272. }
  273. log.Printf("test 'Upper()' : OK")
  274. }