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 TestResultCache(t *testing.T) { 68 agent.Options.BufferSize = 10 69 agent.Options.EnablePersistentBuffer = 0 70 _ = log.Open(log.Console, log.Debug, "", 0) 71 72 writer := mockWriter{lastid: 1, t: t} 73 c := New(&agent.Options, 0, nil) 74 cache := c.(*MemoryCache) 75 76 value := "xyz" 77 result := plugin.Result{ 78 Itemid: 1, 79 Value: &value, 80 Ts: time.Now(), 81 } 82 83 cache.write(&result) 84 cache.flushOutput(&writer) 85 86 cache.write(&result) 87 cache.write(&result) 88 cache.flushOutput(&writer) 89 90 cache.write(&result) 91 cache.write(&result) 92 cache.write(&result) 93 cache.write(&result) 94 cache.flushOutput(&writer) 95} 96 97func TestToken(t *testing.T) { 98 tokens := make(map[string]bool) 99 for i := 0; i < 100000; i++ { 100 token := newToken() 101 if len(token) != 32 { 102 t.Errorf("Expected token length 32 while got %d", len(token)) 103 return 104 } 105 if _, ok := tokens[token]; ok { 106 t.Errorf("Duplicated token detected") 107 } 108 tokens[token] = true 109 } 110} 111 112func checkBuffer(t *testing.T, c *MemoryCache, input []*plugin.Result, expected []*AgentData) { 113 for _, r := range input { 114 c.write(r) 115 } 116 117 if !reflect.DeepEqual(c.results, expected) { 118 t.Errorf("Expected:") 119 for _, d := range expected { 120 t.Errorf(" %+v", *d) 121 } 122 t.Errorf("While got:") 123 for _, d := range c.results { 124 t.Errorf(" %+v", *d) 125 } 126 } 127} 128 129func TestBuffer(t *testing.T) { 130 input := []*plugin.Result{ 131 {Itemid: 1}, 132 {Itemid: 2}, 133 {Itemid: 3}, 134 {Itemid: 4}, 135 {Itemid: 5}, 136 {Itemid: 6}, 137 {Itemid: 7}, 138 {Itemid: 8}, 139 {Itemid: 9}, 140 {Itemid: 10}, 141 } 142 143 expected := []*AgentData{ 144 {Id: 1, Itemid: 1}, 145 {Id: 2, Itemid: 2}, 146 {Id: 3, Itemid: 3}, 147 {Id: 4, Itemid: 4}, 148 {Id: 5, Itemid: 5}, 149 {Id: 6, Itemid: 6}, 150 {Id: 7, Itemid: 7}, 151 {Id: 8, Itemid: 8}, 152 {Id: 9, Itemid: 9}, 153 {Id: 10, Itemid: 10}, 154 } 155 156 _ = log.Open(log.Console, log.Debug, "", 0) 157 agent.Options.BufferSize = 10 158 agent.Options.EnablePersistentBuffer = 0 159 c := New(&agent.Options, 0, nil) 160 cache := c.(*MemoryCache) 161 checkBuffer(t, cache, input, expected) 162} 163 164func TestBufferFull5(t *testing.T) { 165 input := []*plugin.Result{ 166 {Itemid: 1}, 167 {Itemid: 2}, 168 {Itemid: 3}, 169 {Itemid: 4}, 170 {Itemid: 5}, 171 {Itemid: 6}, 172 {Itemid: 7}, 173 {Itemid: 8}, 174 {Itemid: 9}, 175 {Itemid: 10}, 176 {Itemid: 11}, 177 {Itemid: 12}, 178 {Itemid: 13}, 179 {Itemid: 14}, 180 {Itemid: 15}, 181 } 182 183 expected := []*AgentData{ 184 {Id: 6, Itemid: 6}, 185 {Id: 7, Itemid: 7}, 186 {Id: 8, Itemid: 8}, 187 {Id: 9, Itemid: 9}, 188 {Id: 10, Itemid: 10}, 189 {Id: 11, Itemid: 11}, 190 {Id: 12, Itemid: 12}, 191 {Id: 13, Itemid: 13}, 192 {Id: 14, Itemid: 14}, 193 {Id: 15, Itemid: 15}, 194 } 195 196 _ = log.Open(log.Console, log.Debug, "", 0) 197 agent.Options.BufferSize = 10 198 agent.Options.EnablePersistentBuffer = 0 199 c := New(&agent.Options, 0, nil) 200 cache := c.(*MemoryCache) 201 checkBuffer(t, cache, input, expected) 202} 203 204func TestBufferFull5ReplaceFirst(t *testing.T) { 205 input := []*plugin.Result{ 206 {Itemid: 1}, 207 {Itemid: 2}, 208 {Itemid: 3}, 209 {Itemid: 4}, 210 {Itemid: 5}, 211 {Itemid: 6}, 212 {Itemid: 7}, 213 {Itemid: 8}, 214 {Itemid: 9}, 215 {Itemid: 10}, 216 {Itemid: 1}, 217 {Itemid: 2}, 218 {Itemid: 3}, 219 {Itemid: 4}, 220 {Itemid: 5}, 221 } 222 223 expected := []*AgentData{ 224 {Id: 6, Itemid: 6}, 225 {Id: 7, Itemid: 7}, 226 {Id: 8, Itemid: 8}, 227 {Id: 9, Itemid: 9}, 228 {Id: 10, Itemid: 10}, 229 {Id: 11, Itemid: 1}, 230 {Id: 12, Itemid: 2}, 231 {Id: 13, Itemid: 3}, 232 {Id: 14, Itemid: 4}, 233 {Id: 15, Itemid: 5}, 234 } 235 236 _ = log.Open(log.Console, log.Debug, "", 0) 237 agent.Options.BufferSize = 10 238 agent.Options.EnablePersistentBuffer = 0 239 c := New(&agent.Options, 0, nil) 240 cache := c.(*MemoryCache) 241 checkBuffer(t, cache, input, expected) 242} 243 244func TestBufferFull5ReplaceLast(t *testing.T) { 245 input := []*plugin.Result{ 246 {Itemid: 1}, 247 {Itemid: 2}, 248 {Itemid: 3}, 249 {Itemid: 4}, 250 {Itemid: 5}, 251 {Itemid: 6}, 252 {Itemid: 7}, 253 {Itemid: 8}, 254 {Itemid: 9}, 255 {Itemid: 10}, 256 {Itemid: 6}, 257 {Itemid: 7}, 258 {Itemid: 8}, 259 {Itemid: 9}, 260 {Itemid: 10}, 261 } 262 263 expected := []*AgentData{ 264 {Id: 1, Itemid: 1}, 265 {Id: 2, Itemid: 2}, 266 {Id: 3, Itemid: 3}, 267 {Id: 4, Itemid: 4}, 268 {Id: 5, Itemid: 5}, 269 {Id: 11, Itemid: 6}, 270 {Id: 12, Itemid: 7}, 271 {Id: 13, Itemid: 8}, 272 {Id: 14, Itemid: 9}, 273 {Id: 15, Itemid: 10}, 274 } 275 276 _ = log.Open(log.Console, log.Debug, "", 0) 277 agent.Options.BufferSize = 10 278 agent.Options.EnablePersistentBuffer = 0 279 c := New(&agent.Options, 0, nil) 280 cache := c.(*MemoryCache) 281 checkBuffer(t, cache, input, expected) 282} 283 284func TestBufferFull5ReplacInterleaved(t *testing.T) { 285 input := []*plugin.Result{ 286 {Itemid: 1}, 287 {Itemid: 2}, 288 {Itemid: 3}, 289 {Itemid: 4}, 290 {Itemid: 5}, 291 {Itemid: 6}, 292 {Itemid: 7}, 293 {Itemid: 8}, 294 {Itemid: 9}, 295 {Itemid: 10}, 296 {Itemid: 1}, 297 {Itemid: 3}, 298 {Itemid: 5}, 299 {Itemid: 7}, 300 {Itemid: 9}, 301 } 302 303 expected := []*AgentData{ 304 {Id: 2, Itemid: 2}, 305 {Id: 4, Itemid: 4}, 306 {Id: 6, Itemid: 6}, 307 {Id: 8, Itemid: 8}, 308 {Id: 10, Itemid: 10}, 309 {Id: 11, Itemid: 1}, 310 {Id: 12, Itemid: 3}, 311 {Id: 13, Itemid: 5}, 312 {Id: 14, Itemid: 7}, 313 {Id: 15, Itemid: 9}, 314 } 315 316 _ = log.Open(log.Console, log.Debug, "", 0) 317 agent.Options.BufferSize = 10 318 agent.Options.EnablePersistentBuffer = 0 319 c := New(&agent.Options, 0, nil) 320 cache := c.(*MemoryCache) 321 checkBuffer(t, cache, input, expected) 322} 323 324func TestBufferFull5OneItem(t *testing.T) { 325 input := []*plugin.Result{ 326 {Itemid: 1}, 327 {Itemid: 2}, 328 {Itemid: 3}, 329 {Itemid: 4}, 330 {Itemid: 5}, 331 {Itemid: 6}, 332 {Itemid: 7}, 333 {Itemid: 8}, 334 {Itemid: 9}, 335 {Itemid: 10}, 336 {Itemid: 1}, 337 {Itemid: 1}, 338 {Itemid: 1}, 339 {Itemid: 1}, 340 {Itemid: 1}, 341 } 342 343 expected := []*AgentData{ 344 {Id: 2, Itemid: 2}, 345 {Id: 3, Itemid: 3}, 346 {Id: 4, Itemid: 4}, 347 {Id: 5, Itemid: 5}, 348 {Id: 6, Itemid: 6}, 349 {Id: 7, Itemid: 7}, 350 {Id: 8, Itemid: 8}, 351 {Id: 9, Itemid: 9}, 352 {Id: 10, Itemid: 10}, 353 {Id: 15, Itemid: 1}, 354 } 355 356 _ = log.Open(log.Console, log.Debug, "", 0) 357 agent.Options.BufferSize = 10 358 agent.Options.EnablePersistentBuffer = 0 359 c := New(&agent.Options, 0, nil) 360 cache := c.(*MemoryCache) 361 checkBuffer(t, cache, input, expected) 362} 363 364func TestBufferFull4OneItemPersistent(t *testing.T) { 365 input := []*plugin.Result{ 366 {Itemid: 1, Persistent: true}, 367 {Itemid: 2}, 368 {Itemid: 3}, 369 {Itemid: 4}, 370 {Itemid: 5}, 371 {Itemid: 6}, 372 {Itemid: 7}, 373 {Itemid: 8}, 374 {Itemid: 9}, 375 {Itemid: 10}, 376 {Itemid: 1, Persistent: true}, 377 {Itemid: 1, Persistent: true}, 378 {Itemid: 1, Persistent: true}, 379 {Itemid: 1, Persistent: true}, 380 } 381 382 expected := []*AgentData{ 383 {Id: 1, Itemid: 1, persistent: true}, 384 {Id: 6, Itemid: 6}, 385 {Id: 7, Itemid: 7}, 386 {Id: 8, Itemid: 8}, 387 {Id: 9, Itemid: 9}, 388 {Id: 10, Itemid: 10}, 389 {Id: 11, Itemid: 1, persistent: true}, 390 {Id: 12, Itemid: 1, persistent: true}, 391 {Id: 13, Itemid: 1, persistent: true}, 392 {Id: 14, Itemid: 1, persistent: true}, 393 } 394 395 _ = log.Open(log.Console, log.Debug, "", 0) 396 agent.Options.BufferSize = 10 397 agent.Options.EnablePersistentBuffer = 0 398 c := New(&agent.Options, 0, nil) 399 cache := c.(*MemoryCache) 400 checkBuffer(t, cache, input, expected) 401} 402 403func TestBufferFull5OneItemPersistent(t *testing.T) { 404 input := []*plugin.Result{ 405 {Itemid: 1, Persistent: true}, 406 {Itemid: 2}, 407 {Itemid: 3}, 408 {Itemid: 4}, 409 {Itemid: 5}, 410 {Itemid: 6}, 411 {Itemid: 7}, 412 {Itemid: 8}, 413 {Itemid: 9}, 414 {Itemid: 10}, 415 {Itemid: 1, Persistent: true}, 416 {Itemid: 1, Persistent: true}, 417 {Itemid: 1, Persistent: true}, 418 {Itemid: 1, Persistent: true}, 419 {Itemid: 1, Persistent: true}, 420 } 421 422 expected := []*AgentData{ 423 {Id: 1, Itemid: 1, persistent: true}, 424 {Id: 6, Itemid: 6}, 425 {Id: 7, Itemid: 7}, 426 {Id: 8, Itemid: 8}, 427 {Id: 9, Itemid: 9}, 428 {Id: 10, Itemid: 10}, 429 {Id: 11, Itemid: 1, persistent: true}, 430 {Id: 12, Itemid: 1, persistent: true}, 431 {Id: 13, Itemid: 1, persistent: true}, 432 {Id: 14, Itemid: 1, persistent: true}, 433 {Id: 15, Itemid: 1, persistent: true}, 434 } 435 436 _ = log.Open(log.Console, log.Debug, "", 0) 437 agent.Options.BufferSize = 10 438 agent.Options.EnablePersistentBuffer = 0 439 c := New(&agent.Options, 0, nil) 440 cache := c.(*MemoryCache) 441 checkBuffer(t, cache, input, expected) 442} 443 444func TestBufferFull10PersistentAndNormal(t *testing.T) { 445 input := []*plugin.Result{ 446 {Itemid: 1, Persistent: true}, 447 {Itemid: 2}, 448 {Itemid: 3}, 449 {Itemid: 4}, 450 {Itemid: 5}, 451 {Itemid: 6}, 452 {Itemid: 7}, 453 {Itemid: 8}, 454 {Itemid: 9}, 455 {Itemid: 10}, 456 {Itemid: 1, Persistent: true}, 457 {Itemid: 1, Persistent: true}, 458 {Itemid: 1, Persistent: true}, 459 {Itemid: 1, Persistent: true}, 460 {Itemid: 1, Persistent: true}, 461 {Itemid: 6}, 462 {Itemid: 6}, 463 {Itemid: 11}, 464 {Itemid: 12}, 465 {Itemid: 13}, 466 } 467 468 expected := []*AgentData{ 469 {Id: 1, Itemid: 1, persistent: true}, 470 {Id: 10, Itemid: 10}, 471 {Id: 11, Itemid: 1, persistent: true}, 472 {Id: 12, Itemid: 1, persistent: true}, 473 {Id: 13, Itemid: 1, persistent: true}, 474 {Id: 14, Itemid: 1, persistent: true}, 475 {Id: 15, Itemid: 1, persistent: true}, 476 {Id: 17, Itemid: 6}, 477 {Id: 18, Itemid: 11}, 478 {Id: 19, Itemid: 12}, 479 {Id: 20, Itemid: 13}, 480 } 481 482 _ = log.Open(log.Console, log.Debug, "", 0) 483 agent.Options.BufferSize = 10 484 agent.Options.EnablePersistentBuffer = 0 485 c := New(&agent.Options, 0, nil) 486 cache := c.(*MemoryCache) 487 checkBuffer(t, cache, input, expected) 488} 489