您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

365 行
9.4 KiB

  1. package decoder
  2. import (
  3. "bytes"
  4. "testing"
  5. "github.com/AFASystems/presence/internal/pkg/common/appcontext"
  6. "github.com/AFASystems/presence/internal/pkg/model"
  7. "github.com/segmentio/kafka-go"
  8. )
  9. func TestDecodeBeacon_EmptyData(t *testing.T) {
  10. // Setup
  11. appState := appcontext.NewAppState()
  12. mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
  13. parserRegistry := &model.ParserRegistry{}
  14. adv := model.BeaconAdvertisement{
  15. ID: "test-beacon",
  16. Data: "", // Empty data
  17. }
  18. // Execute
  19. err := decodeBeacon(adv, appState, mockWriter, parserRegistry)
  20. // Assert
  21. if err != nil {
  22. t.Errorf("Expected no error for empty data, got %v", err)
  23. }
  24. if len(mockWriter.Messages) != 0 {
  25. t.Errorf("Expected no messages for empty data, got %d", len(mockWriter.Messages))
  26. }
  27. }
  28. func TestDecodeBeacon_WhitespaceOnly(t *testing.T) {
  29. // Setup
  30. appState := appcontext.NewAppState()
  31. mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
  32. parserRegistry := &model.ParserRegistry{}
  33. adv := model.BeaconAdvertisement{
  34. ID: "test-beacon",
  35. Data: " ", // Whitespace only
  36. }
  37. // Execute
  38. err := decodeBeacon(adv, appState, mockWriter, parserRegistry)
  39. // Assert
  40. if err != nil {
  41. t.Errorf("Expected no error for whitespace-only data, got %v", err)
  42. }
  43. if len(mockWriter.Messages) != 0 {
  44. t.Errorf("Expected no messages for whitespace-only data, got %d", len(mockWriter.Messages))
  45. }
  46. }
  47. func TestDecodeBeacon_InvalidHex(t *testing.T) {
  48. // Setup
  49. appState := appcontext.NewAppState()
  50. mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
  51. parserRegistry := &model.ParserRegistry{}
  52. adv := model.BeaconAdvertisement{
  53. ID: "test-beacon",
  54. Data: "INVALID_HEX_DATA!!!",
  55. }
  56. // Execute
  57. err := decodeBeacon(adv, appState, mockWriter, parserRegistry)
  58. // Assert
  59. if err == nil {
  60. t.Error("Expected error for invalid hex data, got nil")
  61. }
  62. if len(mockWriter.Messages) != 0 {
  63. t.Errorf("Expected no messages for invalid hex, got %d", len(mockWriter.Messages))
  64. }
  65. }
  66. func TestDecodeBeacon_ValidHexNoParser(t *testing.T) {
  67. // Setup
  68. appState := appcontext.NewAppState()
  69. mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
  70. parserRegistry := &model.ParserRegistry{} // No parsers registered
  71. // Valid hex but no matching parser
  72. adv := model.BeaconAdvertisement{
  73. ID: "test-beacon",
  74. Data: "0201060302A0", // Valid AD structure
  75. }
  76. // Execute
  77. err := decodeBeacon(adv, appState, mockWriter, parserRegistry)
  78. // Assert
  79. if err != nil {
  80. t.Errorf("Expected no error when no parser matches, got %v", err)
  81. }
  82. if len(mockWriter.Messages) != 0 {
  83. t.Errorf("Expected no messages when no parser matches, got %d", len(mockWriter.Messages))
  84. }
  85. }
  86. func TestDecodeBeacon_Deduplication(t *testing.T) {
  87. // Setup
  88. appState := appcontext.NewAppState()
  89. mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
  90. parserRegistry := &model.ParserRegistry{}
  91. // Register a test parser
  92. config := model.Config{
  93. Name: "test-parser",
  94. Prefix: "02",
  95. Length: 2,
  96. }
  97. parserRegistry.Register("test-parser", config)
  98. // Create an event that will be parsed
  99. adv := model.BeaconAdvertisement{
  100. ID: "test-beacon",
  101. Data: "020106", // Simple AD structure
  102. }
  103. // First processing - should publish
  104. err := decodeBeacon(adv, appState, mockWriter, parserRegistry)
  105. if err != nil {
  106. t.Fatalf("First processing failed: %v", err)
  107. }
  108. firstMessageCount := len(mockWriter.Messages)
  109. // Second processing with identical data - should deduplicate
  110. err = decodeBeacon(adv, appState, mockWriter, parserRegistry)
  111. if err != nil {
  112. t.Fatalf("Second processing failed: %v", err)
  113. }
  114. // Assert - message count should not have changed
  115. if len(mockWriter.Messages) != firstMessageCount {
  116. t.Errorf("Expected deduplication, got %d messages (should be %d)", len(mockWriter.Messages), firstMessageCount)
  117. }
  118. }
  119. func TestDecodeBeacon_DifferentDataPublishes(t *testing.T) {
  120. // Setup
  121. appState := appcontext.NewAppState()
  122. mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
  123. parserRegistry := &model.ParserRegistry{}
  124. // Register a test parser
  125. config := model.Config{
  126. Name: "test-parser",
  127. Prefix: "02",
  128. Length: 2,
  129. }
  130. parserRegistry.Register("test-parser", config)
  131. // First processing
  132. adv1 := model.BeaconAdvertisement{
  133. ID: "test-beacon",
  134. Data: "020106",
  135. }
  136. err := decodeBeacon(adv1, appState, mockWriter, parserRegistry)
  137. if err != nil {
  138. t.Fatalf("First processing failed: %v", err)
  139. }
  140. firstMessageCount := len(mockWriter.Messages)
  141. // Second processing with different data - should publish again
  142. adv2 := model.BeaconAdvertisement{
  143. ID: "test-beacon",
  144. Data: "020107", // Different data
  145. }
  146. err = decodeBeacon(adv2, appState, mockWriter, parserRegistry)
  147. if err != nil {
  148. t.Fatalf("Second processing failed: %v", err)
  149. }
  150. // Assert - message count should have increased
  151. if len(mockWriter.Messages) != firstMessageCount+1 {
  152. t.Errorf("Expected new message for different data, got %d messages (expected %d)", len(mockWriter.Messages), firstMessageCount+1)
  153. }
  154. }
  155. func TestDecodeBeacon_WithFlagBytes(t *testing.T) {
  156. // Setup
  157. appState := appcontext.NewAppState()
  158. mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
  159. parserRegistry := &model.ParserRegistry{}
  160. // Register a test parser
  161. config := model.Config{
  162. Name: "test-parser",
  163. Prefix: "02",
  164. Length: 2,
  165. }
  166. parserRegistry.Register("test-parser", config)
  167. // Data with flag bytes (0x01 at position 1)
  168. adv := model.BeaconAdvertisement{
  169. ID: "test-beacon",
  170. Data: "0201060302A0", // Will have flags removed
  171. }
  172. // Execute
  173. err := decodeBeacon(adv, appState, mockWriter, parserRegistry)
  174. // Assert - should process successfully after flag removal
  175. if err != nil {
  176. t.Errorf("Expected no error with flag bytes, got %v", err)
  177. }
  178. }
  179. func TestDecodeBeacon_MultipleBeacons(t *testing.T) {
  180. // Setup
  181. appState := appcontext.NewAppState()
  182. mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
  183. parserRegistry := &model.ParserRegistry{}
  184. // Register a test parser
  185. config := model.Config{
  186. Name: "test-parser",
  187. Prefix: "02",
  188. Length: 2,
  189. }
  190. parserRegistry.Register("test-parser", config)
  191. // Process multiple different beacons
  192. beacons := []model.BeaconAdvertisement{
  193. {ID: "beacon-1", Data: "020106"},
  194. {ID: "beacon-2", Data: "020107"},
  195. {ID: "beacon-3", Data: "020108"},
  196. }
  197. for _, adv := range beacons {
  198. err := decodeBeacon(adv, appState, mockWriter, parserRegistry)
  199. if err != nil {
  200. t.Errorf("Failed to process beacon %s: %v", adv.ID, err)
  201. }
  202. }
  203. // Each unique beacon should produce a message
  204. if len(mockWriter.Messages) != len(beacons) {
  205. t.Errorf("Expected %d messages, got %d", len(beacons), len(mockWriter.Messages))
  206. }
  207. }
  208. func TestProcessIncoming_ErrorHandling(t *testing.T) {
  209. // Setup
  210. appState := appcontext.NewAppState()
  211. mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
  212. parserRegistry := &model.ParserRegistry{}
  213. // Invalid data that will cause an error
  214. adv := model.BeaconAdvertisement{
  215. ID: "test-beacon",
  216. Data: "INVALID_HEX",
  217. }
  218. // Execute - should not panic, just handle error
  219. processIncoming(adv, appState, mockWriter, parserRegistry)
  220. // Assert - no messages should be written
  221. if len(mockWriter.Messages) != 0 {
  222. t.Errorf("Expected no messages on error, got %d", len(mockWriter.Messages))
  223. }
  224. }
  225. func TestDecodeBeacon_EventHashing(t *testing.T) {
  226. // Setup
  227. appState := appcontext.NewAppState()
  228. mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
  229. parserRegistry := &model.ParserRegistry{}
  230. // Register a test parser that creates consistent events
  231. config := model.Config{
  232. Name: "test-parser",
  233. Prefix: "02",
  234. Length: 2,
  235. }
  236. parserRegistry.Register("test-parser", config)
  237. adv := model.BeaconAdvertisement{
  238. ID: "test-beacon",
  239. Data: "020106",
  240. }
  241. // First processing
  242. err := decodeBeacon(adv, appState, mockWriter, parserRegistry)
  243. if err != nil {
  244. t.Fatalf("First processing failed: %v", err)
  245. }
  246. // Get the event from appState
  247. event, exists := appState.GetBeaconEvent("test-beacon")
  248. if !exists {
  249. t.Fatal("Event should exist in appState")
  250. }
  251. // Verify hash is created
  252. hash := event.Hash()
  253. if hash == nil || len(hash) == 0 {
  254. t.Error("Expected non-empty hash")
  255. }
  256. // Second processing should be deduplicated based on hash
  257. err = decodeBeacon(adv, appState, mockWriter, parserRegistry)
  258. if err != nil {
  259. t.Fatalf("Second processing failed: %v", err)
  260. }
  261. // Should still have only one message
  262. if len(mockWriter.Messages) != 1 {
  263. t.Errorf("Expected 1 message after deduplication, got %d", len(mockWriter.Messages))
  264. }
  265. }
  266. func TestDecodeBeacon_VariousHexFormats(t *testing.T) {
  267. // Setup
  268. appState := appcontext.NewAppState()
  269. mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
  270. parserRegistry := &model.ParserRegistry{}
  271. testCases := []struct {
  272. name string
  273. hexData string
  274. shouldError bool
  275. }{
  276. {"lowercase hex", "020106aa", false},
  277. {"uppercase hex", "020106AA", false},
  278. {"mixed case", "020106AaFf", false},
  279. {"with spaces", " 020106 ", false},
  280. {"odd length", "02016", true},
  281. {"invalid chars", "020106ZZ", true},
  282. }
  283. for _, tc := range testCases {
  284. t.Run(tc.name, func(t *testing.T) {
  285. adv := model.BeaconAdvertisement{
  286. ID: "test-beacon",
  287. Data: tc.hexData,
  288. }
  289. err := decodeBeacon(adv, appState, mockWriter, parserRegistry)
  290. if tc.shouldError && err == nil {
  291. t.Errorf("Expected error for %s, got nil", tc.name)
  292. }
  293. if !tc.shouldError && err != nil && !bytes.Contains(err.Error(), []byte("no parser")) {
  294. // Error is OK if it's "no parser", but not for hex decoding
  295. t.Logf("Got expected error for %s: %v", tc.name, err)
  296. }
  297. })
  298. }
  299. }