go.ligato.io/vpp-agent/v3@v3.5.0/proto/ligato/vpp/interfaces/models_test.go (about) 1 // Copyright (c) 2018 Cisco and/or its affiliates. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package vpp_interfaces 16 17 import ( 18 "testing" 19 20 "go.ligato.io/vpp-agent/v3/proto/ligato/netalloc" 21 ) 22 23 /*func TestInterfaceKey(t *testing.T) { 24 tests := []struct { 25 name string 26 iface string 27 expectedKey string 28 }{ 29 { 30 name: "valid interface name", 31 iface: "memif0", 32 expectedKey: "vpp/config/v2/interface/memif0", 33 }, 34 { 35 name: "invalid interface name", 36 iface: "", 37 expectedKey: "vpp/config/v2/interface/<invalid>", 38 }, 39 { 40 name: "Gbe interface", 41 iface: "GigabitEthernet0/8/0", 42 expectedKey: "vpp/config/v2/interface/GigabitEthernet0/8/0", 43 }, 44 } 45 for _, test := range tests { 46 t.Run(test.name, func(t *testing.T) { 47 key := InterfaceKey(test.iface) 48 if key != test.expectedKey { 49 t.Errorf("failed for: iface=%s\n"+ 50 "expected key:\n\t%q\ngot key:\n\t%q", 51 test.iface, test.expectedKey, key) 52 } 53 }) 54 } 55 } 56 57 func TestParseNameFromKey(t *testing.T) { 58 tests := []struct { 59 name string 60 key string 61 expectedIface string 62 expectedIsIfaceKey bool 63 }{ 64 { 65 name: "valid interface name", 66 key: "vpp/config/v2/interface/memif0", 67 expectedIface: "memif0", 68 expectedIsIfaceKey: true, 69 }, 70 { 71 name: "invalid interface name", 72 key: "vpp/config/v2/interface/<invalid>", 73 expectedIface: "<invalid>", 74 expectedIsIfaceKey: true, 75 }, 76 { 77 name: "Gbe interface", 78 key: "vpp/config/v2/interface/GigabitEthernet0/8/0", 79 expectedIface: "GigabitEthernet0/8/0", 80 expectedIsIfaceKey: true, 81 }, 82 { 83 name: "not an interface key", 84 key: "vpp/config/v2/bd/bd1", 85 expectedIface: "", 86 expectedIsIfaceKey: false, 87 }, 88 { 89 name: "not an interface key (empty interface)", 90 key: "vpp/config/v2/interface/", 91 expectedIface: "", 92 expectedIsIfaceKey: false, 93 }, 94 } 95 for _, test := range tests { 96 t.Run(test.name, func(t *testing.T) { 97 iface, isInterfaceKey := models.Model(&Interface{}).ParseKey(test.key) 98 if isInterfaceKey != test.expectedIsIfaceKey { 99 t.Errorf("expected isInterfaceKey: %v\tgot: %v", test.expectedIsIfaceKey, isInterfaceKey) 100 } 101 if iface != test.expectedIface { 102 t.Errorf("expected iface: %s\tgot: %s", test.expectedIface, iface) 103 } 104 }) 105 } 106 }*/ 107 108 func TestInterfaceErrorKey(t *testing.T) { 109 tests := []struct { 110 name string 111 iface string 112 expectedKey string 113 }{ 114 { 115 name: "valid interface name", 116 iface: "memif0", 117 expectedKey: "vpp/status/v2/interface/error/memif0", 118 }, 119 { 120 name: "invalid interface name", 121 iface: "", 122 expectedKey: "vpp/status/v2/interface/error/<invalid>", 123 }, 124 { 125 name: "Gbe interface", 126 iface: "GigabitEthernet0/8/0", 127 expectedKey: "vpp/status/v2/interface/error/GigabitEthernet0/8/0", 128 }, 129 } 130 for _, test := range tests { 131 t.Run(test.name, func(t *testing.T) { 132 key := InterfaceErrorKey(test.iface) 133 if key != test.expectedKey { 134 t.Errorf("failed for: iface=%s\n"+ 135 "expected key:\n\t%q\ngot key:\n\t%q", 136 test.iface, test.expectedKey, key) 137 } 138 }) 139 } 140 } 141 142 func TestInterfaceStateKey(t *testing.T) { 143 tests := []struct { 144 name string 145 iface string 146 expectedKey string 147 }{ 148 { 149 name: "valid interface name", 150 iface: "memif0", 151 expectedKey: "vpp/status/v2/interface/memif0", 152 }, 153 { 154 name: "invalid interface name", 155 iface: "", 156 expectedKey: "vpp/status/v2/interface/<invalid>", 157 }, 158 { 159 name: "Gbe interface", 160 iface: "GigabitEthernet0/8/0", 161 expectedKey: "vpp/status/v2/interface/GigabitEthernet0/8/0", 162 }, 163 } 164 for _, test := range tests { 165 t.Run(test.name, func(t *testing.T) { 166 key := InterfaceStateKey(test.iface) 167 if key != test.expectedKey { 168 t.Errorf("failed for: iface=%s\n"+ 169 "expected key:\n\t%q\ngot key:\n\t%q", 170 test.iface, test.expectedKey, key) 171 } 172 }) 173 } 174 } 175 176 func TestInterfaceAddressKey(t *testing.T) { 177 tests := []struct { 178 name string 179 iface string 180 address string 181 source netalloc.IPAddressSource 182 expectedKey string 183 }{ 184 { 185 name: "IPv4 address", 186 iface: "memif0", 187 address: "192.168.1.12/24", 188 source: netalloc.IPAddressSource_STATIC, 189 expectedKey: "vpp/interface/memif0/address/static/192.168.1.12/24", 190 }, 191 { 192 name: "IPv4 address from DHCP", 193 iface: "memif0", 194 address: "192.168.1.12/24", 195 source: netalloc.IPAddressSource_FROM_DHCP, 196 expectedKey: "vpp/interface/memif0/address/from_dhcp/192.168.1.12/24", 197 }, 198 { 199 name: "IPv6 address", 200 iface: "memif0", 201 address: "2001:db8::/32", 202 source: netalloc.IPAddressSource_STATIC, 203 expectedKey: "vpp/interface/memif0/address/static/2001:db8::/32", 204 }, 205 { 206 name: "IPv6 address from DHCP", 207 iface: "memif0", 208 address: "2001:db8::/32", 209 source: netalloc.IPAddressSource_FROM_DHCP, 210 expectedKey: "vpp/interface/memif0/address/from_dhcp/2001:db8::/32", 211 }, 212 { 213 name: "invalid interface", 214 iface: "", 215 address: "10.10.10.10/32", 216 source: netalloc.IPAddressSource_STATIC, 217 expectedKey: "vpp/interface/<invalid>/address/static/10.10.10.10/32", 218 }, 219 { 220 name: "undefined source", 221 iface: "memif1", 222 address: "10.10.10.10/32", 223 expectedKey: "vpp/interface/memif1/address/undefined_source/10.10.10.10/32", 224 }, 225 { 226 name: "invalid address", 227 iface: "tap0", 228 address: "invalid-addr", 229 source: netalloc.IPAddressSource_STATIC, 230 expectedKey: "vpp/interface/tap0/address/static/invalid-addr", 231 }, 232 { 233 name: "missing mask", 234 iface: "tap1", 235 address: "10.10.10.10", 236 source: netalloc.IPAddressSource_STATIC, 237 expectedKey: "vpp/interface/tap1/address/static/10.10.10.10", 238 }, 239 { 240 name: "empty address", 241 iface: "tap1", 242 address: "", 243 source: netalloc.IPAddressSource_STATIC, 244 expectedKey: "vpp/interface/tap1/address/static/", 245 }, 246 { 247 name: "IPv4 address requested from netalloc", 248 iface: "memif0", 249 address: "alloc:net1", 250 source: netalloc.IPAddressSource_STATIC, 251 expectedKey: "vpp/interface/memif0/address/alloc_ref/alloc:net1", 252 }, 253 { 254 name: "IPv6 address requested from netalloc", 255 iface: "memif0", 256 address: "alloc:net1/IPV6_ADDR", 257 source: netalloc.IPAddressSource_STATIC, 258 expectedKey: "vpp/interface/memif0/address/alloc_ref/alloc:net1/IPV6_ADDR", 259 }, 260 } 261 for _, test := range tests { 262 t.Run(test.name, func(t *testing.T) { 263 key := InterfaceAddressKey(test.iface, test.address, test.source) 264 if key != test.expectedKey { 265 t.Errorf("failed for: iface=%s address=%s source=%s\n"+ 266 "expected key:\n\t%q\ngot key:\n\t%q", 267 test.iface, test.address, string(test.source), test.expectedKey, key) 268 } 269 }) 270 } 271 } 272 273 func TestParseInterfaceAddressKey(t *testing.T) { 274 tests := []struct { 275 name string 276 key string 277 expectedIface string 278 expectedIfaceAddr string 279 expectedSource netalloc.IPAddressSource 280 expectedInvalidKey bool 281 expectedIsAddrKey bool 282 }{ 283 { 284 name: "IPv4 address", 285 key: "vpp/interface/memif0/address/static/192.168.1.12/24", 286 expectedIface: "memif0", 287 expectedIfaceAddr: "192.168.1.12/24", 288 expectedSource: netalloc.IPAddressSource_STATIC, 289 expectedIsAddrKey: true, 290 }, 291 { 292 name: "IPv4 address from DHCP", 293 key: "vpp/interface/memif0/address/from_dhcp/192.168.1.12/24", 294 expectedIface: "memif0", 295 expectedIfaceAddr: "192.168.1.12/24", 296 expectedSource: netalloc.IPAddressSource_FROM_DHCP, 297 expectedIsAddrKey: true, 298 }, 299 { 300 name: "IPv4 address requested from Netalloc", 301 key: "vpp/interface/memif0/address/alloc_ref/alloc:net1", 302 expectedIface: "memif0", 303 expectedIfaceAddr: "alloc:net1", 304 expectedSource: netalloc.IPAddressSource_ALLOC_REF, 305 expectedIsAddrKey: true, 306 }, 307 { 308 name: "IPv6 address", 309 key: "vpp/interface/tap1/address/static/2001:db8:85a3::8a2e:370:7334/48", 310 expectedIface: "tap1", 311 expectedIfaceAddr: "2001:db8:85a3::8a2e:370:7334/48", 312 expectedSource: netalloc.IPAddressSource_STATIC, 313 expectedIsAddrKey: true, 314 }, 315 { 316 name: "IPv6 address requested from netalloc", 317 key: "vpp/interface/tap1/address/alloc_ref/alloc:net1/IPV6_ADDR", 318 expectedIface: "tap1", 319 expectedIfaceAddr: "alloc:net1/IPV6_ADDR", 320 expectedSource: netalloc.IPAddressSource_ALLOC_REF, 321 expectedIsAddrKey: true, 322 }, 323 { 324 name: "IPv6 address from DHCP", 325 key: "vpp/interface/tap1/address/from_dhcp/2001:db8:85a3::8a2e:370:7334/48", 326 expectedIface: "tap1", 327 expectedIfaceAddr: "2001:db8:85a3::8a2e:370:7334/48", 328 expectedSource: netalloc.IPAddressSource_FROM_DHCP, 329 expectedIsAddrKey: true, 330 }, 331 { 332 name: "invalid interface", 333 key: "vpp/interface/<invalid>/address/static/10.10.10.10/30", 334 expectedIface: "<invalid>", 335 expectedIfaceAddr: "10.10.10.10/30", 336 expectedSource: netalloc.IPAddressSource_STATIC, 337 expectedIsAddrKey: true, 338 }, 339 { 340 name: "gbe interface", 341 key: "vpp/interface/GigabitEthernet0/8/0/address/static/192.168.5.5/16", 342 expectedIface: "GigabitEthernet0/8/0", 343 expectedIfaceAddr: "192.168.5.5/16", 344 expectedSource: netalloc.IPAddressSource_STATIC, 345 expectedIsAddrKey: true, 346 }, 347 { 348 name: "missing interface", 349 key: "vpp/interface//address/static/192.168.5.5/16", 350 expectedIface: "<invalid>", 351 expectedIfaceAddr: "192.168.5.5/16", 352 expectedSource: netalloc.IPAddressSource_STATIC, 353 expectedInvalidKey: true, 354 expectedIsAddrKey: true, 355 }, 356 { 357 name: "missing interface (from DHCP)", 358 key: "vpp/interface//address/from_dhcp/192.168.5.5/16", 359 expectedIface: "<invalid>", 360 expectedIfaceAddr: "192.168.5.5/16", 361 expectedSource: netalloc.IPAddressSource_FROM_DHCP, 362 expectedInvalidKey: true, 363 expectedIsAddrKey: true, 364 }, 365 { 366 name: "missing IP", 367 key: "vpp/interface/tap3/address/static/", 368 expectedIface: "tap3", 369 expectedIfaceAddr: "", 370 expectedSource: netalloc.IPAddressSource_STATIC, 371 expectedInvalidKey: true, 372 expectedIsAddrKey: true, 373 }, 374 { 375 name: "missing IP (from DHCP)", 376 key: "vpp/interface/tap3/address/from_dhcp/", 377 expectedIface: "tap3", 378 expectedIfaceAddr: "", 379 expectedSource: netalloc.IPAddressSource_FROM_DHCP, 380 expectedInvalidKey: true, 381 expectedIsAddrKey: true, 382 }, 383 { 384 name: "missing IP for Gbe", 385 key: "vpp/interface/Gbe0/1/2/address/static/", 386 expectedIface: "Gbe0/1/2", 387 expectedIfaceAddr: "", 388 expectedSource: netalloc.IPAddressSource_STATIC, 389 expectedInvalidKey: true, 390 expectedIsAddrKey: true, 391 }, 392 { 393 name: "not interface address key", 394 key: "vpp/config/v2/interface/GigabitEthernet0/8/0", 395 expectedIface: "", 396 expectedIfaceAddr: "", 397 expectedIsAddrKey: false, 398 }, 399 { 400 name: "invalid address source", 401 key: "vpp/interface/memif0/address/<invalid>/192.168.1.12/24", 402 expectedIface: "memif0", 403 expectedInvalidKey: true, 404 expectedIsAddrKey: true, 405 }, 406 { 407 name: "empty address source", 408 key: "vpp/interface/memif0/address//192.168.1.12/24", 409 expectedIface: "memif0", 410 expectedInvalidKey: true, 411 expectedIsAddrKey: true, 412 }, 413 { 414 name: "missing address source", 415 key: "vpp/interface/memif0/address/192.168.1.12/24", 416 expectedIface: "memif0", 417 expectedInvalidKey: true, 418 expectedIsAddrKey: true, 419 }, 420 } 421 for _, test := range tests { 422 t.Run(test.name, func(t *testing.T) { 423 iface, ipAddr, source, invalidKey, isAddrKey := ParseInterfaceAddressKey(test.key) 424 if isAddrKey != test.expectedIsAddrKey { 425 t.Errorf("expected isAddrKey: %v\tgot: %v", test.expectedIsAddrKey, isAddrKey) 426 } 427 if source != test.expectedSource { 428 t.Errorf("expected source: %v\tgot: %v", test.expectedSource, source) 429 } 430 if invalidKey != test.expectedInvalidKey { 431 t.Errorf("expected invalidKey: %v\tgot: %v", test.expectedInvalidKey, invalidKey) 432 } 433 if iface != test.expectedIface { 434 t.Errorf("expected iface: %s\tgot: %s", test.expectedIface, iface) 435 } 436 if ipAddr != test.expectedIfaceAddr { 437 t.Errorf("expected ipAddr: %s\tgot: %s", test.expectedIfaceAddr, ipAddr) 438 } 439 }) 440 } 441 } 442 443 func TestInterfaceVrfTableKey(t *testing.T) { 444 tests := []struct { 445 name string 446 iface string 447 vrf int 448 ipv4 bool 449 ipv6 bool 450 expectedKey string 451 }{ 452 { 453 name: "default IPv4 VRF", 454 iface: "memif0", 455 vrf: 0, 456 ipv4: true, 457 expectedKey: "vpp/interface/memif0/vrf/0/ip-version/v4", 458 }, 459 { 460 name: "default IPv6 VRF", 461 iface: "memif0", 462 vrf: 0, 463 ipv6: true, 464 expectedKey: "vpp/interface/memif0/vrf/0/ip-version/v6", 465 }, 466 { 467 name: "default VRF for both versions", 468 iface: "memif0", 469 vrf: 0, 470 ipv4: true, 471 ipv6: true, 472 expectedKey: "vpp/interface/memif0/vrf/0/ip-version/both", 473 }, 474 { 475 name: "IPv4 VRF 1", 476 iface: "memif0", 477 vrf: 1, 478 ipv4: true, 479 expectedKey: "vpp/interface/memif0/vrf/1/ip-version/v4", 480 }, 481 { 482 name: "IPv6 VRF 1", 483 iface: "memif0", 484 vrf: 1, 485 ipv6: true, 486 expectedKey: "vpp/interface/memif0/vrf/1/ip-version/v6", 487 }, 488 { 489 name: "interface name with forward slashes", 490 iface: "Gbe0/2/1", 491 vrf: 10, 492 ipv4: true, 493 expectedKey: "vpp/interface/Gbe0/2/1/vrf/10/ip-version/v4", 494 }, 495 { 496 name: "missing interface name", 497 iface: "", 498 vrf: 10, 499 ipv4: true, 500 expectedKey: "vpp/interface/<invalid>/vrf/10/ip-version/v4", 501 }, 502 { 503 name: "undefined version", 504 iface: "memif0", 505 vrf: 10, 506 expectedKey: "vpp/interface/memif0/vrf/10/ip-version/<invalid>", 507 }, 508 { 509 name: "invalid VRF table ID", 510 iface: "memif0", 511 vrf: -5, 512 ipv4: true, 513 expectedKey: "vpp/interface/memif0/vrf/<invalid>/ip-version/v4", 514 }, 515 } 516 for _, test := range tests { 517 t.Run(test.name, func(t *testing.T) { 518 key := InterfaceVrfKey(test.iface, test.vrf, test.ipv4, test.ipv6) 519 if key != test.expectedKey { 520 t.Errorf("failed for: iface=%s vrf=%d ipv4=%t ipv6=%t\n"+ 521 "expected key:\n\t%q\ngot key:\n\t%q", 522 test.iface, test.vrf, test.ipv4, test.ipv6, test.expectedKey, key) 523 } 524 }) 525 } 526 } 527 528 func TestParseInterfaceVrfKey(t *testing.T) { 529 tests := []struct { 530 name string 531 key string 532 expectedIface string 533 expectedVrf int 534 expectedIpv4 bool 535 expectedIpv6 bool 536 expectedIsIfaceVrfKey bool 537 }{ 538 { 539 name: "default IPv4 VRF", 540 key: "vpp/interface/memif0/vrf/0/ip-version/v4", 541 expectedIface: "memif0", 542 expectedVrf: 0, 543 expectedIpv4: true, 544 expectedIsIfaceVrfKey: true, 545 }, 546 { 547 name: "default IPv6 VRF", 548 key: "vpp/interface/memif0/vrf/0/ip-version/v6", 549 expectedIface: "memif0", 550 expectedVrf: 0, 551 expectedIpv6: true, 552 expectedIsIfaceVrfKey: true, 553 }, 554 { 555 name: "IPv4 VRF 1", 556 key: "vpp/interface/memif0/vrf/1/ip-version/v4", 557 expectedIface: "memif0", 558 expectedVrf: 1, 559 expectedIpv4: true, 560 expectedIsIfaceVrfKey: true, 561 }, 562 { 563 name: "IPv6 VRF 1", 564 key: "vpp/interface/memif0/vrf/1/ip-version/v6", 565 expectedIface: "memif0", 566 expectedVrf: 1, 567 expectedIpv6: true, 568 expectedIsIfaceVrfKey: true, 569 }, 570 { 571 name: "invalid interface name", 572 key: "vpp/interface/<invalid>/vrf/1/ip-version/v6", 573 expectedIface: "<invalid>", 574 expectedVrf: 1, 575 expectedIpv6: true, 576 expectedIsIfaceVrfKey: true, 577 }, 578 { 579 name: "invalid ip version", 580 key: "vpp/interface/memif0/vrf/1/ip-version/<invalid>", 581 expectedIface: "memif0", 582 expectedVrf: 1, 583 expectedIsIfaceVrfKey: true, 584 }, 585 { 586 name: "missing table ID", 587 key: "vpp/interface/memif0/vrf//ip-version/v6", 588 expectedIface: "memif0", 589 expectedVrf: -1, 590 expectedIpv6: true, 591 expectedIsIfaceVrfKey: true, 592 }, 593 { 594 name: "invalid table ID", 595 key: "vpp/interface/memif0/vrf/<invalid>/ip-version/v6", 596 expectedIface: "memif0", 597 expectedVrf: -1, 598 expectedIpv6: true, 599 expectedIsIfaceVrfKey: true, 600 }, 601 { 602 name: "interface name with forward slashes", 603 key: "vpp/interface/Gbe1/2/3/vrf/12/ip-version/v6", 604 expectedIface: "Gbe1/2/3", 605 expectedVrf: 12, 606 expectedIpv6: true, 607 expectedIsIfaceVrfKey: true, 608 }, 609 { 610 name: "not vrf table key", 611 key: "vpp/config/v2/interface/GigabitEthernet0/8/0", 612 expectedIsIfaceVrfKey: false, 613 }, 614 { 615 name: "not vrf table key (inherited VRF)", 616 key: "vpp/interface/Gbe1/2/3/vrf/from-interface/memif0", 617 expectedIsIfaceVrfKey: false, 618 }, 619 } 620 for _, test := range tests { 621 t.Run(test.name, func(t *testing.T) { 622 iface, vrf, ipv4, ipv6, isIfaceVrfKey := ParseInterfaceVrfKey(test.key) 623 if isIfaceVrfKey != test.expectedIsIfaceVrfKey { 624 t.Errorf("expected isVrfTableKey: %v\tgot: %v", test.expectedIsIfaceVrfKey, isIfaceVrfKey) 625 } 626 if iface != test.expectedIface { 627 t.Errorf("expected iface: %s\tgot: %s", test.expectedIface, iface) 628 } 629 if vrf != test.expectedVrf { 630 t.Errorf("expected vrf: %d\tgot: %d", test.expectedVrf, vrf) 631 } 632 if ipv4 != test.expectedIpv4 { 633 t.Errorf("expected ipv4: %t\tgot: %t", test.expectedIpv4, ipv4) 634 } 635 if ipv6 != test.expectedIpv6 { 636 t.Errorf("expected ipv6: %t\tgot: %t", test.expectedIpv6, ipv6) 637 } 638 }) 639 } 640 } 641 642 func TestInterfaceInheritedVrfKey(t *testing.T) { 643 tests := []struct { 644 name string 645 iface string 646 fromIface string 647 expectedKey string 648 }{ 649 { 650 name: "memifs", 651 iface: "memif0", 652 fromIface: "memif1", 653 expectedKey: "vpp/interface/memif0/vrf/from-interface/memif1", 654 }, 655 { 656 name: "memif and Gbe", 657 iface: "memif0", 658 fromIface: "Gbe0/1/2", 659 expectedKey: "vpp/interface/memif0/vrf/from-interface/Gbe0/1/2", 660 }, 661 { 662 name: "Gbe-s", 663 iface: "Gbe3/4/5", 664 fromIface: "Gbe0/1/2", 665 expectedKey: "vpp/interface/Gbe3/4/5/vrf/from-interface/Gbe0/1/2", 666 }, 667 { 668 name: "missing interface", 669 iface: "", 670 fromIface: "memif1", 671 expectedKey: "vpp/interface/<invalid>/vrf/from-interface/memif1", 672 }, 673 { 674 name: "missing from-interface", 675 iface: "memif0", 676 fromIface: "", 677 expectedKey: "vpp/interface/memif0/vrf/from-interface/<invalid>", 678 }, 679 } 680 for _, test := range tests { 681 t.Run(test.name, func(t *testing.T) { 682 key := InterfaceInheritedVrfKey(test.iface, test.fromIface) 683 if key != test.expectedKey { 684 t.Errorf("failed for: iface=%s fromIface=%s\n"+ 685 "expected key:\n\t%q\ngot key:\n\t%q", 686 test.iface, test.fromIface, test.expectedKey, key) 687 } 688 }) 689 } 690 } 691 692 func TestParseInterfaceInheritedVrfKey(t *testing.T) { 693 tests := []struct { 694 name string 695 key string 696 expectedIface string 697 expectedFromIface string 698 expectedIsIfaceInherVrfKey bool 699 }{ 700 { 701 name: "memifs", 702 key: "vpp/interface/memif0/vrf/from-interface/memif1", 703 expectedIface: "memif0", 704 expectedFromIface: "memif1", 705 expectedIsIfaceInherVrfKey: true, 706 }, 707 { 708 name: "Gbe-s", 709 key: "vpp/interface/Gbe1/2/3/vrf/from-interface/Gbe4/5/6", 710 expectedIface: "Gbe1/2/3", 711 expectedFromIface: "Gbe4/5/6", 712 expectedIsIfaceInherVrfKey: true, 713 }, 714 { 715 name: "invalid interface", 716 key: "vpp/interface/<invalid>/vrf/from-interface/Gbe4/5/6", 717 expectedIface: "<invalid>", 718 expectedFromIface: "Gbe4/5/6", 719 expectedIsIfaceInherVrfKey: true, 720 }, 721 { 722 name: "invalid from-interface", 723 key: "vpp/interface/Gbe1/2/3/vrf/from-interface/<invalid>", 724 expectedIface: "Gbe1/2/3", 725 expectedFromIface: "<invalid>", 726 expectedIsIfaceInherVrfKey: true, 727 }, 728 { 729 name: "missing interface", 730 key: "vpp/interface//vrf/from-interface/Gbe4/5/6", 731 expectedIface: "<invalid>", 732 expectedFromIface: "Gbe4/5/6", 733 expectedIsIfaceInherVrfKey: true, 734 }, 735 { 736 name: "missing from-interface", 737 key: "vpp/interface/Gbe1/2/3/vrf/from-interface/", 738 expectedIface: "Gbe1/2/3", 739 expectedFromIface: "<invalid>", 740 expectedIsIfaceInherVrfKey: true, 741 }, 742 { 743 name: "not interface inherited-vrf key", 744 key: "vpp/interface/memif0/vrf/1/ip-version/v6", 745 expectedIsIfaceInherVrfKey: false, 746 }, 747 } 748 for _, test := range tests { 749 t.Run(test.name, func(t *testing.T) { 750 iface, fromIface, isIfaceInherVrfKey := ParseInterfaceInheritedVrfKey(test.key) 751 if isIfaceInherVrfKey != test.expectedIsIfaceInherVrfKey { 752 t.Errorf("expected isIfaceInherVrfKey: %v\tgot: %v", test.expectedIsIfaceInherVrfKey, isIfaceInherVrfKey) 753 } 754 if iface != test.expectedIface { 755 t.Errorf("expected iface: %s\tgot: %s", test.expectedIface, iface) 756 } 757 if fromIface != test.expectedFromIface { 758 t.Errorf("expected fromIface: %s\tgot: %s", test.expectedFromIface, fromIface) 759 } 760 }) 761 } 762 } 763 764 func TestUnnumberedKey(t *testing.T) { 765 tests := []struct { 766 name string 767 iface string 768 expectedKey string 769 }{ 770 { 771 name: "valid interface name", 772 iface: "memif0", 773 expectedKey: "vpp/interface/unnumbered/memif0", 774 }, 775 { 776 name: "invalid interface name", 777 iface: "", 778 expectedKey: "vpp/interface/unnumbered/<invalid>", 779 }, 780 { 781 name: "Gbe interface", 782 iface: "GigabitEthernet0/8/0", 783 expectedKey: "vpp/interface/unnumbered/GigabitEthernet0/8/0", 784 }, 785 } 786 for _, test := range tests { 787 t.Run(test.name, func(t *testing.T) { 788 key := UnnumberedKey(test.iface) 789 if key != test.expectedKey { 790 t.Errorf("failed for: iface=%s\n"+ 791 "expected key:\n\t%q\ngot key:\n\t%q", 792 test.iface, test.expectedKey, key) 793 } 794 }) 795 } 796 } 797 798 func TestDHCPClientKey(t *testing.T) { 799 tests := []struct { 800 name string 801 iface string 802 expectedKey string 803 }{ 804 { 805 name: "valid interface name", 806 iface: "memif0", 807 expectedKey: "vpp/interface/dhcp-client/memif0", 808 }, 809 { 810 name: "invalid interface name", 811 iface: "", 812 expectedKey: "vpp/interface/dhcp-client/<invalid>", 813 }, 814 { 815 name: "Gbe interface", 816 iface: "GigabitEthernet0/8/0", 817 expectedKey: "vpp/interface/dhcp-client/GigabitEthernet0/8/0", 818 }, 819 } 820 for _, test := range tests { 821 t.Run(test.name, func(t *testing.T) { 822 key := DHCPClientKey(test.iface) 823 if key != test.expectedKey { 824 t.Errorf("failed for: iface=%s\n"+ 825 "expected key:\n\t%q\ngot key:\n\t%q", 826 test.iface, test.expectedKey, key) 827 } 828 }) 829 } 830 } 831 832 func TestParseNameFromDHCPClientKey(t *testing.T) { 833 tests := []struct { 834 name string 835 key string 836 expectedIface string 837 expectedIsDHCPClientKey bool 838 }{ 839 { 840 name: "valid interface name", 841 key: "vpp/interface/dhcp-client/memif0", 842 expectedIface: "memif0", 843 expectedIsDHCPClientKey: true, 844 }, 845 { 846 name: "invalid interface name", 847 key: "vpp/interface/dhcp-client/<invalid>", 848 expectedIface: "<invalid>", 849 expectedIsDHCPClientKey: true, 850 }, 851 { 852 name: "Gbe interface", 853 key: "vpp/interface/dhcp-client/GigabitEthernet0/8/0", 854 expectedIface: "GigabitEthernet0/8/0", 855 expectedIsDHCPClientKey: true, 856 }, 857 { 858 name: "not DHCP client key", 859 key: "vpp/config/v2/bd/bd1", 860 expectedIface: "", 861 expectedIsDHCPClientKey: false, 862 }, 863 { 864 name: "not DHCP client key (empty interface)", 865 key: "vpp/interface/dhcp-client/", 866 expectedIface: "", 867 expectedIsDHCPClientKey: false, 868 }, 869 } 870 for _, test := range tests { 871 t.Run(test.name, func(t *testing.T) { 872 iface, isDHCPClientKey := ParseNameFromDHCPClientKey(test.key) 873 if isDHCPClientKey != test.expectedIsDHCPClientKey { 874 t.Errorf("expected isInterfaceKey: %v\tgot: %v", test.expectedIsDHCPClientKey, isDHCPClientKey) 875 } 876 if iface != test.expectedIface { 877 t.Errorf("expected iface: %s\tgot: %s", test.expectedIface, iface) 878 } 879 }) 880 } 881 } 882 883 func TestDHCPLeaseKey(t *testing.T) { 884 tests := []struct { 885 name string 886 iface string 887 expectedKey string 888 }{ 889 { 890 name: "valid interface name", 891 iface: "memif0", 892 expectedKey: "vpp/interface/dhcp-lease/memif0", 893 }, 894 { 895 name: "invalid interface name", 896 iface: "", 897 expectedKey: "vpp/interface/dhcp-lease/<invalid>", 898 }, 899 { 900 name: "Gbe interface", 901 iface: "GigabitEthernet0/8/0", 902 expectedKey: "vpp/interface/dhcp-lease/GigabitEthernet0/8/0", 903 }, 904 } 905 for _, test := range tests { 906 t.Run(test.name, func(t *testing.T) { 907 key := DHCPLeaseKey(test.iface) 908 if key != test.expectedKey { 909 t.Errorf("failed for: iface=%s\n"+ 910 "expected key:\n\t%q\ngot key:\n\t%q", 911 test.iface, test.expectedKey, key) 912 } 913 }) 914 } 915 } 916 917 func TestLinkStateKey(t *testing.T) { 918 tests := []struct { 919 name string 920 iface string 921 linkIsUp bool 922 expectedKey string 923 }{ 924 { 925 name: "link is UP", 926 iface: "memif0", 927 linkIsUp: true, 928 expectedKey: "vpp/interface/memif0/link-state/UP", 929 }, 930 { 931 name: "link is DOWN", 932 iface: "memif0", 933 linkIsUp: false, 934 expectedKey: "vpp/interface/memif0/link-state/DOWN", 935 }, 936 { 937 name: "invalid interface name", 938 iface: "", 939 linkIsUp: true, 940 expectedKey: "vpp/interface/<invalid>/link-state/UP", 941 }, 942 { 943 name: "Gbe interface", 944 iface: "GigabitEthernet0/8/0", 945 linkIsUp: false, 946 expectedKey: "vpp/interface/GigabitEthernet0/8/0/link-state/DOWN", 947 }, 948 } 949 for _, test := range tests { 950 t.Run(test.name, func(t *testing.T) { 951 key := LinkStateKey(test.iface, test.linkIsUp) 952 if key != test.expectedKey { 953 t.Errorf("failed for: iface=%s linkIsUp=%v\n"+ 954 "expected key:\n\t%q\ngot key:\n\t%q", 955 test.iface, test.linkIsUp, test.expectedKey, key) 956 } 957 }) 958 } 959 } 960 961 func TestParseLinkStateKey(t *testing.T) { 962 tests := []struct { 963 name string 964 key string 965 expectedIface string 966 expectedIsLinkUp bool 967 expectedIsLinkStateKey bool 968 }{ 969 { 970 name: "link is UP", 971 key: "vpp/interface/memif0/link-state/UP", 972 expectedIface: "memif0", 973 expectedIsLinkUp: true, 974 expectedIsLinkStateKey: true, 975 }, 976 { 977 name: "link is DOWN", 978 key: "vpp/interface/memif0/link-state/DOWN", 979 expectedIface: "memif0", 980 expectedIsLinkUp: false, 981 expectedIsLinkStateKey: true, 982 }, 983 { 984 name: "invalid interface name", 985 key: "vpp/interface/<invalid>/link-state/DOWN", 986 expectedIsLinkStateKey: false, 987 }, 988 { 989 name: "Gbe interface", 990 key: "vpp/interface/GigabitEthernet0/8/0/link-state/UP", 991 expectedIface: "GigabitEthernet0/8/0", 992 expectedIsLinkUp: true, 993 expectedIsLinkStateKey: true, 994 }, 995 { 996 name: "invalid link state", 997 key: "vpp/interface/GigabitEthernet0/8/0/link-state/<invalid>", 998 expectedIsLinkStateKey: false, 999 }, 1000 { 1001 name: "missing link state", 1002 key: "vpp/interface/GigabitEthernet0/8/0/link-state", 1003 expectedIsLinkStateKey: false, 1004 }, 1005 { 1006 name: "not link state key", 1007 key: "vpp/interface/unnumbered/GigabitEthernet0/8/0", 1008 expectedIsLinkStateKey: false, 1009 }, 1010 } 1011 for _, test := range tests { 1012 t.Run(test.name, func(t *testing.T) { 1013 iface, isLinkUp, isLinkStateKey := ParseLinkStateKey(test.key) 1014 if isLinkStateKey != test.expectedIsLinkStateKey { 1015 t.Errorf("expected isLinkStateKey: %v\tgot: %v", 1016 test.expectedIsLinkStateKey, isLinkStateKey) 1017 } 1018 if iface != test.expectedIface { 1019 t.Errorf("expected iface: %s\tgot: %s", test.expectedIface, iface) 1020 } 1021 if isLinkUp != test.expectedIsLinkUp { 1022 t.Errorf("expected isLinkUp: %t\tgot: %t", test.expectedIsLinkUp, isLinkUp) 1023 } 1024 }) 1025 } 1026 } 1027 1028 func TestRxPlacementKey(t *testing.T) { 1029 tests := []struct { 1030 name string 1031 iface string 1032 queue uint32 1033 expectedKey string 1034 }{ 1035 { 1036 name: "queue 0", 1037 iface: "memif0", 1038 queue: 0, 1039 expectedKey: "vpp/interface/memif0/rx-placement/queue/0", 1040 }, 1041 { 1042 name: "queue 1", 1043 iface: "memif0", 1044 queue: 1, 1045 expectedKey: "vpp/interface/memif0/rx-placement/queue/1", 1046 }, 1047 { 1048 name: "invalid interface name", 1049 iface: "", 1050 queue: 1, 1051 expectedKey: "vpp/interface/<invalid>/rx-placement/queue/1", 1052 }, 1053 { 1054 name: "Gbe interface", 1055 iface: "GigabitEthernet0/8/0", 1056 queue: 2, 1057 expectedKey: "vpp/interface/GigabitEthernet0/8/0/rx-placement/queue/2", 1058 }, 1059 } 1060 for _, test := range tests { 1061 t.Run(test.name, func(t *testing.T) { 1062 key := RxPlacementKey(test.iface, test.queue) 1063 if key != test.expectedKey { 1064 t.Errorf("failed for: iface=%s queue=%d\n"+ 1065 "expected key:\n\t%q\ngot key:\n\t%q", 1066 test.iface, test.queue, test.expectedKey, key) 1067 } 1068 }) 1069 } 1070 } 1071 1072 func TestParseRxPlacementKey(t *testing.T) { 1073 tests := []struct { 1074 name string 1075 key string 1076 expectedIface string 1077 expectedQueue uint32 1078 expectedIsRxPlacementKey bool 1079 }{ 1080 { 1081 name: "queue 0", 1082 key: "vpp/interface/memif0/rx-placement/queue/0", 1083 expectedIface: "memif0", 1084 expectedQueue: 0, 1085 expectedIsRxPlacementKey: true, 1086 }, 1087 { 1088 name: "queue 1", 1089 key: "vpp/interface/memif0/rx-placement/queue/1", 1090 expectedIface: "memif0", 1091 expectedQueue: 1, 1092 expectedIsRxPlacementKey: true, 1093 }, 1094 { 1095 name: "invalid interface name", 1096 key: "vpp/interface/<invalid>/rx-placement/queue/1", 1097 expectedIsRxPlacementKey: false, 1098 }, 1099 { 1100 name: "invalid queue", 1101 key: "vpp/interface/memif0/rx-placement/queue/<invalid>", 1102 expectedIsRxPlacementKey: false, 1103 }, 1104 { 1105 name: "missing queue", 1106 key: "vpp/interface/memif0/rx-placement/", 1107 expectedIsRxPlacementKey: false, 1108 }, 1109 { 1110 name: "missing queue ID", 1111 key: "vpp/interface/memif0/rx-placement/queue", 1112 expectedIsRxPlacementKey: false, 1113 }, 1114 { 1115 name: "Gbe interface", 1116 key: "vpp/interface/GigabitEthernet0/8/0/rx-placement/queue/3", 1117 expectedIface: "GigabitEthernet0/8/0", 1118 expectedQueue: 3, 1119 expectedIsRxPlacementKey: true, 1120 }, 1121 { 1122 name: "not rx placement key", 1123 key: "vpp/interface/memif0/link-state/DOWN", 1124 expectedIsRxPlacementKey: false, 1125 }, 1126 } 1127 for _, test := range tests { 1128 t.Run(test.name, func(t *testing.T) { 1129 iface, queue, isRxPlacementKey := ParseRxPlacementKey(test.key) 1130 if isRxPlacementKey != test.expectedIsRxPlacementKey { 1131 t.Errorf("expected isRxPlacementKey: %v\tgot: %v", 1132 test.expectedIsRxPlacementKey, isRxPlacementKey) 1133 } 1134 if queue != test.expectedQueue { 1135 t.Errorf("expected queue: %d\tgot: %d", test.expectedQueue, queue) 1136 } 1137 if iface != test.expectedIface { 1138 t.Errorf("expected iface: %s\tgot: %s", test.expectedIface, iface) 1139 } 1140 }) 1141 } 1142 } 1143 1144 func TestRxModesKey(t *testing.T) { 1145 tests := []struct { 1146 name string 1147 iface string 1148 expectedKey string 1149 }{ 1150 { 1151 name: "memif", 1152 iface: "memif0", 1153 expectedKey: "vpp/interface/memif0/rx-modes", 1154 }, 1155 { 1156 name: "Gbe", 1157 iface: "GigabitEthernet0/8/0", 1158 expectedKey: "vpp/interface/GigabitEthernet0/8/0/rx-modes", 1159 }, 1160 { 1161 name: "invalid interface name", 1162 iface: "", 1163 expectedKey: "vpp/interface/<invalid>/rx-modes", 1164 }, 1165 } 1166 for _, test := range tests { 1167 t.Run(test.name, func(t *testing.T) { 1168 key := RxModesKey(test.iface) 1169 if key != test.expectedKey { 1170 t.Errorf("failed for: iface=%s\n"+ 1171 "expected key:\n\t%q\ngot key:\n\t%q", 1172 test.iface, test.expectedKey, key) 1173 } 1174 }) 1175 } 1176 } 1177 1178 func TestParseRxModesKey(t *testing.T) { 1179 tests := []struct { 1180 name string 1181 key string 1182 expectedIface string 1183 expectedIsRxModesKey bool 1184 }{ 1185 { 1186 name: "memif", 1187 key: "vpp/interface/memif0/rx-modes", 1188 expectedIface: "memif0", 1189 expectedIsRxModesKey: true, 1190 }, 1191 { 1192 name: "Gbe", 1193 key: "vpp/interface/GigabitEthernet0/8/0/rx-modes", 1194 expectedIface: "GigabitEthernet0/8/0", 1195 expectedIsRxModesKey: true, 1196 }, 1197 { 1198 name: "invalid interface name", 1199 key: "vpp/interface/<invalid>/rx-modes", 1200 expectedIsRxModesKey: false, 1201 }, 1202 { 1203 name: "missing rx-mode suffix", 1204 key: "vpp/interface/<invalid>", 1205 expectedIsRxModesKey: false, 1206 }, 1207 { 1208 name: "not rx-mode key", 1209 key: "vpp/interface/memif0/address/192.168.1.12/24", 1210 expectedIsRxModesKey: false, 1211 }, 1212 } 1213 for _, test := range tests { 1214 t.Run(test.name, func(t *testing.T) { 1215 iface, isRxModesKey := ParseRxModesKey(test.key) 1216 if isRxModesKey != test.expectedIsRxModesKey { 1217 t.Errorf("expected isRxModesKey: %v\tgot: %v", 1218 test.expectedIsRxModesKey, isRxModesKey) 1219 } 1220 if iface != test.expectedIface { 1221 t.Errorf("expected iface: %s\tgot: %s", test.expectedIface, iface) 1222 } 1223 }) 1224 } 1225 } 1226 1227 func TestInterfaceWithIPKey(t *testing.T) { 1228 tests := []struct { 1229 name string 1230 iface string 1231 expectedKey string 1232 }{ 1233 { 1234 name: "memif", 1235 iface: "memif0", 1236 expectedKey: "vpp/interface/memif0/has-IP-address", 1237 }, 1238 { 1239 name: "invalid interface name", 1240 iface: "", 1241 expectedKey: "vpp/interface/<invalid>/has-IP-address", 1242 }, 1243 { 1244 name: "Gbe interface", 1245 iface: "GigabitEthernet0/8/0", 1246 expectedKey: "vpp/interface/GigabitEthernet0/8/0/has-IP-address", 1247 }, 1248 } 1249 for _, test := range tests { 1250 t.Run(test.name, func(t *testing.T) { 1251 key := InterfaceWithIPKey(test.iface) 1252 if key != test.expectedKey { 1253 t.Errorf("failed for: iface=%s\n"+ 1254 "expected key:\n\t%q\ngot key:\n\t%q", 1255 test.iface, test.expectedKey, key) 1256 } 1257 }) 1258 } 1259 } 1260 1261 func TestParseInterfaceWithIPKey(t *testing.T) { 1262 tests := []struct { 1263 name string 1264 key string 1265 expectedIface string 1266 expectedIsIfaceWithIPKey bool 1267 }{ 1268 { 1269 name: "memif", 1270 key: "vpp/interface/memif0/has-IP-address", 1271 expectedIface: "memif0", 1272 expectedIsIfaceWithIPKey: true, 1273 }, 1274 { 1275 name: "Gbe", 1276 key: "vpp/interface/GigabitEthernet0/8/0/has-IP-address", 1277 expectedIface: "GigabitEthernet0/8/0", 1278 expectedIsIfaceWithIPKey: true, 1279 }, 1280 { 1281 name: "invalid interface name", 1282 key: "vpp/interface/<invalid>/has-IP-address", 1283 expectedIsIfaceWithIPKey: false, 1284 }, 1285 { 1286 name: "missing has-IP-address suffix", 1287 key: "vpp/interface/<invalid>", 1288 expectedIsIfaceWithIPKey: false, 1289 }, 1290 { 1291 name: "not has-IP-address key", 1292 key: "vpp/interface/memif0/address/192.168.1.12/24", 1293 expectedIsIfaceWithIPKey: false, 1294 }, 1295 } 1296 for _, test := range tests { 1297 t.Run(test.name, func(t *testing.T) { 1298 iface, isInterfaceWithIPKey := ParseInterfaceWithIPKey(test.key) 1299 if isInterfaceWithIPKey != test.expectedIsIfaceWithIPKey { 1300 t.Errorf("expected isInterfaceWithIPKey: %v\tgot: %v", 1301 test.expectedIsIfaceWithIPKey, isInterfaceWithIPKey) 1302 } 1303 if iface != test.expectedIface { 1304 t.Errorf("expected iface: %s\tgot: %s", test.expectedIface, iface) 1305 } 1306 }) 1307 } 1308 }