PageRenderTime 5794ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/message/message_matcher_test.go

https://gitlab.com/karouf/heka
Go | 305 lines | 272 code | 20 blank | 13 comment | 14 complexity | 412234ac85c0003dc546a273b44dd9d9 MD5 | raw file
  1. /***** BEGIN LICENSE BLOCK *****
  2. # This Source Code Form is subject to the terms of the Mozilla Public
  3. # License, v. 2.0. If a copy of the MPL was not distributed with this file,
  4. # You can obtain one at http://mozilla.org/MPL/2.0/.
  5. #
  6. # The Initial Developer of the Original Code is the Mozilla Foundation.
  7. # Portions created by the Initial Developer are Copyright (C) 2012
  8. # the Initial Developer. All Rights Reserved.
  9. #
  10. # Contributor(s):
  11. # Mike Trinkala (trink@mozilla.com)
  12. #
  13. # ***** END LICENSE BLOCK *****/
  14. package message
  15. import (
  16. "fmt"
  17. "github.com/rafrombrc/gospec/src/gospec"
  18. gs "github.com/rafrombrc/gospec/src/gospec"
  19. "testing"
  20. )
  21. func compareCaptures(c gospec.Context, m1, m2 map[string]string) {
  22. for k, v := range m1 {
  23. v1, _ := m2[k]
  24. c.Expect(v, gs.Equals, v1)
  25. }
  26. }
  27. func MatcherSpecificationSpec(c gospec.Context) {
  28. msg := getTestMessage()
  29. uuidStr := msg.GetUuidString()
  30. data := []byte("data")
  31. date := "Mon Jan 02 15:04:05 -0700 2006"
  32. field1, _ := NewField("bytes", data, "")
  33. field2, _ := NewField("int", int64(999), "")
  34. field2.AddValue(int64(1024))
  35. field3, _ := NewField("double", float64(99.9), "")
  36. field4, _ := NewField("bool", true, "")
  37. field5, _ := NewField("foo", "alternate", "")
  38. field6, _ := NewField("Payload", "name=test;type=web;", "")
  39. field7, _ := NewField("Timestamp", date, "date-time")
  40. field8, _ := NewField("zero", int64(0), "")
  41. field9, _ := NewField("string", "43", "")
  42. msg.AddField(field1)
  43. msg.AddField(field2)
  44. msg.AddField(field3)
  45. msg.AddField(field4)
  46. msg.AddField(field5)
  47. msg.AddField(field6)
  48. msg.AddField(field7)
  49. msg.AddField(field8)
  50. msg.AddField(field9)
  51. c.Specify("A MatcherSpecification", func() {
  52. malformed := []string{
  53. "",
  54. "bogus",
  55. "Type = 'test'", // invalid operator
  56. "Pid == 'test='", // Pid is not a string
  57. "Type == 'test' && (Severity==7 || Payload == 'Test Payload'", // missing paren
  58. "Invalid == 'bogus'", // unknown variable name
  59. "Fields[]", // empty name key
  60. "Fields[test][]", // empty field index
  61. "Fields[test][a]", // non numeric field index
  62. "Fields[test][0][]", // empty array index
  63. "Fields[test][0][a]", // non numeric array index
  64. "Fields[test][0][0][]", // extra index dimension
  65. "Fields[test][xxxx", // unmatched bracket
  66. "Pid =~ /6/", // regex not allowed on numeric
  67. "Pid !~ /6/", // regex not allowed on numeric
  68. "Type =~ /test", // unmatched slash
  69. "Type == /test/", // incorrect operator
  70. "Type =~ 'test'", // string instead of regexp
  71. "Type =~ /\\ytest/", // invalid escape character
  72. "Type != 'test\"", // mis matched quote types
  73. "Pid =~ 6", // number instead of regexp
  74. "NIL", // invalid use of constant
  75. "Type == NIL", // existence check only works on fields
  76. "Fields[test] > NIL", // existence check only works with equals and not equals
  77. }
  78. negative := []string{
  79. "FALSE",
  80. "Type == 'test'&&(Severity==7||Payload=='Test Payload')",
  81. "EnvVersion == '0.9'",
  82. "EnvVersion != '0.8'",
  83. "EnvVersion > '0.9'",
  84. "EnvVersion >= '0.9'",
  85. "EnvVersion < '0.8'",
  86. "EnvVersion <= '0.7'",
  87. "Severity == 5",
  88. "Severity != 6",
  89. "Severity < 6",
  90. "Severity <= 5",
  91. "Severity > 6",
  92. "Severity >= 7",
  93. "Fields[foo] == 'ba'",
  94. "Fields[foo][1] == 'bar'",
  95. "Fields[foo][0][1] == 'bar'",
  96. "Fields[bool] == FALSE",
  97. "Type =~ /Test/",
  98. "Type !~ /TEST/",
  99. "Payload =~ /^Payload/",
  100. "Type == \"te'st\"",
  101. "Type == 'te\"st'",
  102. "Fields[int] =~ /999/",
  103. "Fields[zero] == \"0\"",
  104. "Fields[string] == 43",
  105. "Fields[int] == NIL",
  106. "Fields[int][0][1] == NIL",
  107. "Fields[missing] != NIL",
  108. "Type =~ /^te/",
  109. "Type =~ /st$/",
  110. "Type !~ /^TE/",
  111. "Type !~ /ST$/",
  112. "Logger =~ /./ && Type =~ /^anything/",
  113. }
  114. positive := []string{
  115. "TRUE",
  116. "(Severity == 7 || Payload == 'Test Payload') && Type == 'TEST'",
  117. "EnvVersion == \"0.8\"",
  118. "EnvVersion == '0.8'",
  119. "EnvVersion != '0.9'",
  120. "EnvVersion > '0.7'",
  121. "EnvVersion >= '0.8'",
  122. "EnvVersion < '0.9'",
  123. "EnvVersion <= '0.8'",
  124. "Hostname != ''",
  125. "Logger == 'GoSpec'",
  126. "Pid != 0",
  127. "Severity != 5",
  128. "Severity < 7",
  129. "Severity <= 6",
  130. "Severity == 6",
  131. "Severity > 5",
  132. "Severity >= 6",
  133. "Timestamp > 0",
  134. "Type != 'test'",
  135. "Type == 'TEST' && Severity == 6",
  136. "Type == 'test' && Severity == 7 || Payload == 'Test Payload'",
  137. "Type == 'TEST'",
  138. "Type == 'foo' || Type == 'bar' || Type == 'TEST'",
  139. fmt.Sprintf("Uuid == '%s'", uuidStr),
  140. "Fields[foo] == 'bar'",
  141. "Fields[foo][0] == 'bar'",
  142. "Fields[foo][0][0] == 'bar'",
  143. "Fields[foo][1] == 'alternate'",
  144. "Fields[foo][1][0] == 'alternate'",
  145. "Fields[foo] == 'bar'",
  146. "Fields[bytes] == 'data'",
  147. "Fields[int] == 999",
  148. "Fields[int][0][1] == 1024",
  149. "Fields[double] == 99.9",
  150. "Fields[bool] == TRUE",
  151. "Type =~ /TEST/",
  152. "Type !~ /bogus/",
  153. "Type =~ /TEST/ && Payload =~ /Payload/",
  154. "Fields[foo][1] =~ /alt/",
  155. "Fields[Payload] =~ /name=\\w+/",
  156. "Type =~ /(ST)/",
  157. "Fields[int] != NIL",
  158. "Fields[int][0][1] != NIL",
  159. "Fields[int][0][2] == NIL",
  160. "Fields[missing] == NIL",
  161. "Type =~ /^TE/",
  162. "Type =~ /ST$/",
  163. "Type !~ /^te/",
  164. "Type !~ /st$/",
  165. }
  166. c.Specify("malformed matcher tests", func() {
  167. for _, v := range malformed {
  168. _, err := CreateMatcherSpecification(v)
  169. c.Expect(err, gs.Not(gs.IsNil))
  170. }
  171. })
  172. c.Specify("negative matcher tests", func() {
  173. for _, v := range negative {
  174. ms, err := CreateMatcherSpecification(v)
  175. c.Expect(err, gs.IsNil)
  176. match := ms.Match(msg)
  177. c.Expect(match, gs.IsFalse)
  178. }
  179. })
  180. c.Specify("positive matcher tests", func() {
  181. for _, v := range positive {
  182. ms, err := CreateMatcherSpecification(v)
  183. c.Expect(err, gs.IsNil)
  184. match := ms.Match(msg)
  185. c.Expect(match, gs.IsTrue)
  186. }
  187. })
  188. })
  189. }
  190. func BenchmarkMatcherCreate(b *testing.B) {
  191. s := "Type == 'Test' && Severity == 6"
  192. for i := 0; i < b.N; i++ {
  193. CreateMatcherSpecification(s)
  194. }
  195. }
  196. func BenchmarkMatcherMatch(b *testing.B) {
  197. b.StopTimer()
  198. s := "Type == 'TEST' && Severity == 6"
  199. ms, _ := CreateMatcherSpecification(s)
  200. msg := getTestMessage()
  201. b.StartTimer()
  202. for i := 0; i < b.N; i++ {
  203. ms.Match(msg)
  204. }
  205. }
  206. func BenchmarkMatcherSimpleRegex(b *testing.B) {
  207. b.StopTimer()
  208. s := "Type =~ /[Tt]EST/ && Severity == 6"
  209. ms, _ := CreateMatcherSpecification(s)
  210. msg := getTestMessage()
  211. b.StartTimer()
  212. for i := 0; i < b.N; i++ {
  213. ms.Match(msg)
  214. }
  215. }
  216. func BenchmarkMatcherSimpleRegexCapture(b *testing.B) {
  217. b.StopTimer()
  218. s := "Type =~ /^(TEST)/ && Severity == 6"
  219. ms, _ := CreateMatcherSpecification(s)
  220. msg := getTestMessage()
  221. b.StartTimer()
  222. for i := 0; i < b.N; i++ {
  223. ms.Match(msg)
  224. }
  225. }
  226. func BenchmarkMatcherFieldString(b *testing.B) {
  227. b.StopTimer()
  228. s := "Fields[foo] == 'bar' && Severity == 6"
  229. ms, _ := CreateMatcherSpecification(s)
  230. msg := getTestMessage()
  231. b.StartTimer()
  232. for i := 0; i < b.N; i++ {
  233. ms.Match(msg)
  234. }
  235. }
  236. func BenchmarkMatcherFieldNumeric(b *testing.B) {
  237. b.StopTimer()
  238. s := "Fields[number] == 64 && Severity == 6"
  239. ms, _ := CreateMatcherSpecification(s)
  240. msg := getTestMessage()
  241. b.StartTimer()
  242. for i := 0; i < b.N; i++ {
  243. ms.Match(msg)
  244. }
  245. }
  246. func BenchmarkMatcherFieldNonExistence(b *testing.B) {
  247. b.StopTimer()
  248. s := "Fields[missing] == NIL"
  249. ms, _ := CreateMatcherSpecification(s)
  250. msg := getTestMessage()
  251. b.StartTimer()
  252. for i := 0; i < b.N; i++ {
  253. ms.Match(msg)
  254. }
  255. }
  256. func BenchmarkMatcherFieldExistence(b *testing.B) {
  257. b.StopTimer()
  258. s := "Fields[int] != NIL"
  259. ms, _ := CreateMatcherSpecification(s)
  260. msg := getTestMessage()
  261. b.StartTimer()
  262. for i := 0; i < b.N; i++ {
  263. ms.Match(msg)
  264. }
  265. }
  266. func BenchmarkMatcherStartsWith(b *testing.B) {
  267. b.StopTimer()
  268. s := "Payload =~ /^Test/"
  269. ms, _ := CreateMatcherSpecification(s)
  270. msg := getTestMessage()
  271. b.StartTimer()
  272. for i := 0; i < b.N; i++ {
  273. ms.Match(msg)
  274. }
  275. }
  276. func BenchmarkMatcherEndsWith(b *testing.B) {
  277. b.StopTimer()
  278. s := "Payload =~ /load$/"
  279. ms, _ := CreateMatcherSpecification(s)
  280. msg := getTestMessage()
  281. b.StartTimer()
  282. for i := 0; i < b.N; i++ {
  283. ms.Match(msg)
  284. }
  285. }