1/* 2** Zabbix 3** Copyright (C) 2001-2021 Zabbix SIA 4** 5** This program is free software; you can redistribute it and/or modify 6** it under the terms of the GNU General Public License as published by 7** the Free Software Foundation; either version 2 of the License, or 8** (at your option) any later version. 9** 10** This program is distributed in the hope that it will be useful, 11** but WITHOUT ANY WARRANTY; without even the implied warranty of 12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13** GNU General Public License for more details. 14** 15** You should have received a copy of the GNU General Public License 16** along with this program; if not, write to the Free Software 17** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18**/ 19package resultcache 20 21import ( 22 "encoding/json" 23 "errors" 24 "reflect" 25 "testing" 26 "time" 27 28 "zabbix.com/internal/agent" 29 "zabbix.com/pkg/log" 30 "zabbix.com/pkg/plugin" 31) 32 33type mockWriter struct { 34 counter int 35 lastid uint64 36 t *testing.T 37} 38 39func (w *mockWriter) Write(data []byte, timeout time.Duration) (err error) { 40 log.Debugf("%s", string(data)) 41 if w.counter&1 != 0 { 42 err = errors.New("mock error") 43 } else { 44 var request AgentDataRequest 45 _ = json.Unmarshal(data, &request) 46 for _, d := range request.Data { 47 if d.Id != w.lastid { 48 w.t.Errorf("Expected %d data id while got %d", w.lastid, d.Id) 49 w.t.Fail() 50 } 51 w.lastid++ 52 } 53 } 54 55 w.counter++ 56 return 57} 58 59func (w *mockWriter) Addr() string { 60 return "" 61} 62 63func (w *mockWriter) CanRetry() bool { 64 return false 65} 66 67func (w *mockWriter) Hostname() string { 68 return "" 69} 70 71func TestResultCache(t *testing.T) { 72 agent.Options.BufferSize = 10 73 agent.Options.EnablePersistentBuffer = 0 74 _ = log.Open(log.Console, log.Debug, "", 0) 75 76 writer := mockWriter{lastid: 1, t: t} 77 c := New(&agent.Options, 0, nil) 78 cache := c.(*MemoryCache) 79 80 value := "xyz" 81 result := plugin.Result{ 82 Itemid: 1, 83 Value: &value, 84 Ts: time.Now(), 85 } 86 87 cache.write(&result) 88 cache.flushOutput(&writer) 89 90 cache.write(&result) 91 cache.write(&result) 92 cache.flushOutput(&writer) 93 94 cache.write(&result) 95 cache.write(&result) 96 cache.write(&result) 97 cache.write(&result) 98 cache.flushOutput(&writer) 99} 100 101func TestToken(t *testing.T) { 102 tokens := make(map[string]bool) 103 for i := 0; i < 100000; i++ { 104 token := newToken() 105 if len(token) != 32 { 106 t.Errorf("Expected token length 32 while got %d", len(token)) 107 return 108 } 109 if _, ok := tokens[token]; ok { 110 t.Errorf("Duplicated token detected") 111 } 112 tokens[token] = true 113 } 114} 115 116func checkBuffer(t *testing.T, c *MemoryCache, input []*plugin.Result, expected []*AgentData) { 117 for _, r := range input { 118 c.write(r) 119 } 120 121 if !reflect.DeepEqual(c.results, expected) { 122 t.Errorf("Expected:") 123 for _, d := range expected { 124 t.Errorf(" %+v", *d) 125 } 126 t.Errorf("While got:") 127 for _, d := range c.results { 128 t.Errorf(" %+v", *d) 129 } 130 } 131} 132 133func TestBuffer(t *testing.T) { 134 input := []*plugin.Result{ 135 {Itemid: 1}, 136 {Itemid: 2}, 137 {Itemid: 3}, 138 {Itemid: 4}, 139 {Itemid: 5}, 140 {Itemid: 6}, 141 {Itemid: 7}, 142 {Itemid: 8}, 143 {Itemid: 9}, 144 {Itemid: 10}, 145 } 146 147 expected := []*AgentData{ 148 {Id: 1, Itemid: 1}, 149 {Id: 2, Itemid: 2}, 150 {Id: 3, Itemid: 3}, 151 {Id: 4, Itemid: 4}, 152 {Id: 5, Itemid: 5}, 153 {Id: 6, Itemid: 6}, 154 {Id: 7, Itemid: 7}, 155 {Id: 8, Itemid: 8}, 156 {Id: 9, Itemid: 9}, 157 {Id: 10, Itemid: 10}, 158 } 159 160 _ = log.Open(log.Console, log.Debug, "", 0) 161 agent.Options.BufferSize = 10 162 agent.Options.EnablePersistentBuffer = 0 163 c := New(&agent.Options, 0, nil) 164 cache := c.(*MemoryCache) 165 checkBuffer(t, cache, input, expected) 166} 167 168func TestBufferFull5(t *testing.T) { 169 input := []*plugin.Result{ 170 {Itemid: 1}, 171 {Itemid: 2}, 172 {Itemid: 3}, 173 {Itemid: 4}, 174 {Itemid: 5}, 175 {Itemid: 6}, 176 {Itemid: 7}, 177 {Itemid: 8}, 178 {Itemid: 9}, 179 {Itemid: 10}, 180 {Itemid: 11}, 181 {Itemid: 12}, 182 {Itemid: 13}, 183 {Itemid: 14}, 184 {Itemid: 15}, 185 } 186 187 expected := []*AgentData{ 188 {Id: 6, Itemid: 6}, 189 {Id: 7, Itemid: 7}, 190 {Id: 8, Itemid: 8}, 191 {Id: 9, Itemid: 9}, 192 {Id: 10, Itemid: 10}, 193 {Id: 11, Itemid: 11}, 194 {Id: 12, Itemid: 12}, 195 {Id: 13, Itemid: 13}, 196 {Id: 14, Itemid: 14}, 197 {Id: 15, Itemid: 15}, 198 } 199 200 _ = log.Open(log.Console, log.Debug, "", 0) 201 agent.Options.BufferSize = 10 202 agent.Options.EnablePersistentBuffer = 0 203 c := New(&agent.Options, 0, nil) 204 cache := c.(*MemoryCache) 205 checkBuffer(t, cache, input, expected) 206} 207 208func TestBufferFull5ReplaceFirst(t *testing.T) { 209 input := []*plugin.Result{ 210 {Itemid: 1}, 211 {Itemid: 2}, 212 {Itemid: 3}, 213 {Itemid: 4}, 214 {Itemid: 5}, 215 {Itemid: 6}, 216 {Itemid: 7}, 217 {Itemid: 8}, 218 {Itemid: 9}, 219 {Itemid: 10}, 220 {Itemid: 1}, 221 {Itemid: 2}, 222 {Itemid: 3}, 223 {Itemid: 4}, 224 {Itemid: 5}, 225 } 226 227 expected := []*AgentData{ 228 {Id: 6, Itemid: 6}, 229 {Id: 7, Itemid: 7}, 230 {Id: 8, Itemid: 8}, 231 {Id: 9, Itemid: 9}, 232 {Id: 10, Itemid: 10}, 233 {Id: 11, Itemid: 1}, 234 {Id: 12, Itemid: 2}, 235 {Id: 13, Itemid: 3}, 236 {Id: 14, Itemid: 4}, 237 {Id: 15, Itemid: 5}, 238 } 239 240 _ = log.Open(log.Console, log.Debug, "", 0) 241 agent.Options.BufferSize = 10 242 agent.Options.EnablePersistentBuffer = 0 243 c := New(&agent.Options, 0, nil) 244 cache := c.(*MemoryCache) 245 checkBuffer(t, cache, input, expected) 246} 247 248func TestBufferFull5ReplaceLast(t *testing.T) { 249 input := []*plugin.Result{ 250 {Itemid: 1}, 251 {Itemid: 2}, 252 {Itemid: 3}, 253 {Itemid: 4}, 254 {Itemid: 5}, 255 {Itemid: 6}, 256 {Itemid: 7}, 257 {Itemid: 8}, 258 {Itemid: 9}, 259 {Itemid: 10}, 260 {Itemid: 6}, 261 {Itemid: 7}, 262 {Itemid: 8}, 263 {Itemid: 9}, 264 {Itemid: 10}, 265 } 266 267 expected := []*AgentData{ 268 {Id: 1, Itemid: 1}, 269 {Id: 2, Itemid: 2}, 270 {Id: 3, Itemid: 3}, 271 {Id: 4, Itemid: 4}, 272 {Id: 5, Itemid: 5}, 273 {Id: 11, Itemid: 6}, 274 {Id: 12, Itemid: 7}, 275 {Id: 13, Itemid: 8}, 276 {Id: 14, Itemid: 9}, 277 {Id: 15, Itemid: 10}, 278 } 279 280 _ = log.Open(log.Console, log.Debug, "", 0) 281 agent.Options.BufferSize = 10 282 agent.Options.EnablePersistentBuffer = 0 283 c := New(&agent.Options, 0, nil) 284 cache := c.(*MemoryCache) 285 checkBuffer(t, cache, input, expected) 286} 287 288func TestBufferFull5ReplacInterleaved(t *testing.T) { 289 input := []*plugin.Result{ 290 {Itemid: 1}, 291 {Itemid: 2}, 292 {Itemid: 3}, 293 {Itemid: 4}, 294 {Itemid: 5}, 295 {Itemid: 6}, 296 {Itemid: 7}, 297 {Itemid: 8}, 298 {Itemid: 9}, 299 {Itemid: 10}, 300 {Itemid: 1}, 301 {Itemid: 3}, 302 {Itemid: 5}, 303 {Itemid: 7}, 304 {Itemid: 9}, 305 } 306 307 expected := []*AgentData{ 308 {Id: 2, Itemid: 2}, 309 {Id: 4, Itemid: 4}, 310 {Id: 6, Itemid: 6}, 311 {Id: 8, Itemid: 8}, 312 {Id: 10, Itemid: 10}, 313 {Id: 11, Itemid: 1}, 314 {Id: 12, Itemid: 3}, 315 {Id: 13, Itemid: 5}, 316 {Id: 14, Itemid: 7}, 317 {Id: 15, Itemid: 9}, 318 } 319 320 _ = log.Open(log.Console, log.Debug, "", 0) 321 agent.Options.BufferSize = 10 322 agent.Options.EnablePersistentBuffer = 0 323 c := New(&agent.Options, 0, nil) 324 cache := c.(*MemoryCache) 325 checkBuffer(t, cache, input, expected) 326} 327 328func TestBufferFull5OneItem(t *testing.T) { 329 input := []*plugin.Result{ 330 {Itemid: 1}, 331 {Itemid: 2}, 332 {Itemid: 3}, 333 {Itemid: 4}, 334 {Itemid: 5}, 335 {Itemid: 6}, 336 {Itemid: 7}, 337 {Itemid: 8}, 338 {Itemid: 9}, 339 {Itemid: 10}, 340 {Itemid: 1}, 341 {Itemid: 1}, 342 {Itemid: 1}, 343 {Itemid: 1}, 344 {Itemid: 1}, 345 } 346 347 expected := []*AgentData{ 348 {Id: 2, Itemid: 2}, 349 {Id: 3, Itemid: 3}, 350 {Id: 4, Itemid: 4}, 351 {Id: 5, Itemid: 5}, 352 {Id: 6, Itemid: 6}, 353 {Id: 7, Itemid: 7}, 354 {Id: 8, Itemid: 8}, 355 {Id: 9, Itemid: 9}, 356 {Id: 10, Itemid: 10}, 357 {Id: 15, Itemid: 1}, 358 } 359 360 _ = log.Open(log.Console, log.Debug, "", 0) 361 agent.Options.BufferSize = 10 362 agent.Options.EnablePersistentBuffer = 0 363 c := New(&agent.Options, 0, nil) 364 cache := c.(*MemoryCache) 365 checkBuffer(t, cache, input, expected) 366} 367 368func TestBufferFull4OneItemPersistent(t *testing.T) { 369 input := []*plugin.Result{ 370 {Itemid: 1, Persistent: true}, 371 {Itemid: 2}, 372 {Itemid: 3}, 373 {Itemid: 4}, 374 {Itemid: 5}, 375 {Itemid: 6}, 376 {Itemid: 7}, 377 {Itemid: 8}, 378 {Itemid: 9}, 379 {Itemid: 10}, 380 {Itemid: 1, Persistent: true}, 381 {Itemid: 1, Persistent: true}, 382 {Itemid: 1, Persistent: true}, 383 {Itemid: 1, Persistent: true}, 384 } 385 386 expected := []*AgentData{ 387 {Id: 1, Itemid: 1, persistent: true}, 388 {Id: 6, Itemid: 6}, 389 {Id: 7, Itemid: 7}, 390 {Id: 8, Itemid: 8}, 391 {Id: 9, Itemid: 9}, 392 {Id: 10, Itemid: 10}, 393 {Id: 11, Itemid: 1, persistent: true}, 394 {Id: 12, Itemid: 1, persistent: true}, 395 {Id: 13, Itemid: 1, persistent: true}, 396 {Id: 14, Itemid: 1, persistent: true}, 397 } 398 399 _ = log.Open(log.Console, log.Debug, "", 0) 400 agent.Options.BufferSize = 10 401 agent.Options.EnablePersistentBuffer = 0 402 c := New(&agent.Options, 0, nil) 403 cache := c.(*MemoryCache) 404 checkBuffer(t, cache, input, expected) 405} 406 407func TestBufferFull5OneItemPersistent(t *testing.T) { 408 input := []*plugin.Result{ 409 {Itemid: 1, Persistent: true}, 410 {Itemid: 2}, 411 {Itemid: 3}, 412 {Itemid: 4}, 413 {Itemid: 5}, 414 {Itemid: 6}, 415 {Itemid: 7}, 416 {Itemid: 8}, 417 {Itemid: 9}, 418 {Itemid: 10}, 419 {Itemid: 1, Persistent: true}, 420 {Itemid: 1, Persistent: true}, 421 {Itemid: 1, Persistent: true}, 422 {Itemid: 1, Persistent: true}, 423 {Itemid: 1, Persistent: true}, 424 } 425 426 expected := []*AgentData{ 427 {Id: 1, Itemid: 1, persistent: true}, 428 {Id: 6, Itemid: 6}, 429 {Id: 7, Itemid: 7}, 430 {Id: 8, Itemid: 8}, 431 {Id: 9, Itemid: 9}, 432 {Id: 10, Itemid: 10}, 433 {Id: 11, Itemid: 1, persistent: true}, 434 {Id: 12, Itemid: 1, persistent: true}, 435 {Id: 13, Itemid: 1, persistent: true}, 436 {Id: 14, Itemid: 1, persistent: true}, 437 {Id: 15, Itemid: 1, persistent: true}, 438 } 439 440 _ = log.Open(log.Console, log.Debug, "", 0) 441 agent.Options.BufferSize = 10 442 agent.Options.EnablePersistentBuffer = 0 443 c := New(&agent.Options, 0, nil) 444 cache := c.(*MemoryCache) 445 checkBuffer(t, cache, input, expected) 446} 447 448func TestBufferFull10PersistentAndNormal(t *testing.T) { 449 input := []*plugin.Result{ 450 {Itemid: 1, Persistent: true}, 451 {Itemid: 2}, 452 {Itemid: 3}, 453 {Itemid: 4}, 454 {Itemid: 5}, 455 {Itemid: 6}, 456 {Itemid: 7}, 457 {Itemid: 8}, 458 {Itemid: 9}, 459 {Itemid: 10}, 460 {Itemid: 1, Persistent: true}, 461 {Itemid: 1, Persistent: true}, 462 {Itemid: 1, Persistent: true}, 463 {Itemid: 1, Persistent: true}, 464 {Itemid: 1, Persistent: true}, 465 {Itemid: 6}, 466 {Itemid: 6}, 467 {Itemid: 11}, 468 {Itemid: 12}, 469 {Itemid: 13}, 470 } 471 472 expected := []*AgentData{ 473 {Id: 1, Itemid: 1, persistent: true}, 474 {Id: 10, Itemid: 10}, 475 {Id: 11, Itemid: 1, persistent: true}, 476 {Id: 12, Itemid: 1, persistent: true}, 477 {Id: 13, Itemid: 1, persistent: true}, 478 {Id: 14, Itemid: 1, persistent: true}, 479 {Id: 15, Itemid: 1, persistent: true}, 480 {Id: 17, Itemid: 6}, 481 {Id: 18, Itemid: 11}, 482 {Id: 19, Itemid: 12}, 483 {Id: 20, Itemid: 13}, 484 } 485 486 _ = log.Open(log.Console, log.Debug, "", 0) 487 agent.Options.BufferSize = 10 488 agent.Options.EnablePersistentBuffer = 0 489 c := New(&agent.Options, 0, nil) 490 cache := c.(*MemoryCache) 491 checkBuffer(t, cache, input, expected) 492} 493