Best Ginkgo code snippet using internal.Is
validation_test.go
Source:validation_test.go
1package k8s2import (3 "fmt"4 "reflect"5 "strings"6 "testing"7 v1 "k8s.io/api/core/v1"8 networking "k8s.io/api/networking/v1"9 meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"10 "k8s.io/apimachinery/pkg/util/validation/field"11)12func TestValidateIngress(t *testing.T) {13 tests := []struct {14 ing *networking.Ingress15 isPlus bool16 appProtectEnabled bool17 internalRoutesEnabled bool18 expectedErrors []string19 msg string20 }{21 {22 ing: &networking.Ingress{23 Spec: networking.IngressSpec{24 Rules: []networking.IngressRule{25 {26 Host: "example.com",27 },28 },29 },30 },31 isPlus: false,32 appProtectEnabled: false,33 internalRoutesEnabled: false,34 expectedErrors: nil,35 msg: "valid input",36 },37 {38 ing: &networking.Ingress{39 ObjectMeta: meta_v1.ObjectMeta{40 Annotations: map[string]string{41 "nginx.org/mergeable-ingress-type": "invalid",42 },43 },44 Spec: networking.IngressSpec{45 Rules: []networking.IngressRule{46 {47 Host: "",48 },49 },50 },51 },52 isPlus: false,53 appProtectEnabled: false,54 internalRoutesEnabled: false,55 expectedErrors: []string{56 `annotations.nginx.org/mergeable-ingress-type: Invalid value: "invalid": must be one of: 'master' or 'minion'`,57 "spec.rules[0].host: Required value",58 },59 msg: "invalid ingress",60 },61 {62 ing: &networking.Ingress{63 ObjectMeta: meta_v1.ObjectMeta{64 Annotations: map[string]string{65 "nginx.org/mergeable-ingress-type": "master",66 },67 },68 Spec: networking.IngressSpec{69 Rules: []networking.IngressRule{70 {71 Host: "example.com",72 IngressRuleValue: networking.IngressRuleValue{73 HTTP: &networking.HTTPIngressRuleValue{74 Paths: []networking.HTTPIngressPath{75 {76 Path: "/",77 },78 },79 },80 },81 },82 },83 },84 },85 isPlus: false,86 appProtectEnabled: false,87 internalRoutesEnabled: false,88 expectedErrors: []string{89 "spec.rules[0].http.paths: Too many: 1: must have at most 0 items",90 },91 msg: "invalid master",92 },93 {94 ing: &networking.Ingress{95 ObjectMeta: meta_v1.ObjectMeta{96 Annotations: map[string]string{97 "nginx.org/mergeable-ingress-type": "minion",98 },99 },100 Spec: networking.IngressSpec{101 Rules: []networking.IngressRule{102 {103 Host: "example.com",104 IngressRuleValue: networking.IngressRuleValue{},105 },106 },107 },108 },109 isPlus: false,110 appProtectEnabled: false,111 internalRoutesEnabled: false,112 expectedErrors: []string{113 "spec.rules[0].http.paths: Required value: must include at least one path",114 },115 msg: "invalid minion",116 },117 }118 for _, test := range tests {119 allErrs := validateIngress(test.ing, test.isPlus, test.appProtectEnabled, test.internalRoutesEnabled)120 assertion := assertErrors("validateIngress()", test.msg, allErrs, test.expectedErrors)121 if assertion != "" {122 t.Error(assertion)123 }124 }125}126func TestValidateNginxIngressAnnotations(t *testing.T) {127 tests := []struct {128 annotations map[string]string129 specServices map[string]bool130 isPlus bool131 appProtectEnabled bool132 internalRoutesEnabled bool133 expectedErrors []string134 msg string135 }{136 {137 annotations: map[string]string{},138 specServices: map[string]bool{},139 isPlus: false,140 appProtectEnabled: false,141 internalRoutesEnabled: false,142 expectedErrors: nil,143 msg: "valid no annotations",144 },145 {146 annotations: map[string]string{147 "nginx.org/lb-method": "invalid_method",148 "nginx.org/mergeable-ingress-type": "invalid",149 },150 specServices: map[string]bool{},151 isPlus: false,152 appProtectEnabled: false,153 internalRoutesEnabled: false,154 expectedErrors: []string{155 `annotations.nginx.org/lb-method: Invalid value: "invalid_method": Invalid load balancing method: "invalid_method"`,156 `annotations.nginx.org/mergeable-ingress-type: Invalid value: "invalid": must be one of: 'master' or 'minion'`,157 },158 msg: "invalid multiple annotations messages in alphabetical order",159 },160 {161 annotations: map[string]string{162 "nginx.org/mergeable-ingress-type": "master",163 },164 specServices: map[string]bool{},165 isPlus: false,166 appProtectEnabled: false,167 internalRoutesEnabled: false,168 expectedErrors: nil,169 msg: "valid input with master annotation",170 },171 {172 annotations: map[string]string{173 "nginx.org/mergeable-ingress-type": "minion",174 },175 specServices: map[string]bool{},176 isPlus: false,177 appProtectEnabled: false,178 internalRoutesEnabled: false,179 expectedErrors: nil,180 msg: "valid input with minion annotation",181 },182 {183 annotations: map[string]string{184 "nginx.org/mergeable-ingress-type": "",185 },186 specServices: map[string]bool{},187 isPlus: false,188 appProtectEnabled: false,189 internalRoutesEnabled: false,190 expectedErrors: []string{191 "annotations.nginx.org/mergeable-ingress-type: Required value",192 },193 msg: "invalid mergeable type annotation 1",194 },195 {196 annotations: map[string]string{197 "nginx.org/mergeable-ingress-type": "abc",198 },199 specServices: map[string]bool{},200 isPlus: false,201 appProtectEnabled: false,202 internalRoutesEnabled: false,203 expectedErrors: []string{204 `annotations.nginx.org/mergeable-ingress-type: Invalid value: "abc": must be one of: 'master' or 'minion'`,205 },206 msg: "invalid mergeable type annotation 2",207 },208 {209 annotations: map[string]string{210 "nginx.org/lb-method": "random",211 },212 specServices: map[string]bool{},213 isPlus: false,214 appProtectEnabled: false,215 internalRoutesEnabled: false,216 expectedErrors: nil,217 msg: "valid nginx.org/lb-method annotation, nginx normal",218 },219 {220 annotations: map[string]string{221 "nginx.org/lb-method": "least_time header",222 },223 specServices: map[string]bool{},224 isPlus: false,225 appProtectEnabled: false,226 internalRoutesEnabled: false,227 expectedErrors: []string{228 `annotations.nginx.org/lb-method: Invalid value: "least_time header": Invalid load balancing method: "least_time header"`,229 },230 msg: "invalid nginx.org/lb-method annotation, nginx plus only",231 },232 {233 annotations: map[string]string{234 "nginx.org/lb-method": "invalid_method",235 },236 specServices: map[string]bool{},237 isPlus: false,238 appProtectEnabled: false,239 internalRoutesEnabled: false,240 expectedErrors: []string{241 `annotations.nginx.org/lb-method: Invalid value: "invalid_method": Invalid load balancing method: "invalid_method"`,242 },243 msg: "invalid nginx.org/lb-method annotation",244 },245 {246 annotations: map[string]string{247 "nginx.com/health-checks": "true",248 },249 specServices: map[string]bool{},250 isPlus: false,251 appProtectEnabled: false,252 internalRoutesEnabled: false,253 expectedErrors: []string{254 "annotations.nginx.com/health-checks: Forbidden: annotation requires NGINX Plus",255 },256 msg: "invalid nginx.com/health-checks annotation, nginx plus only",257 },258 {259 annotations: map[string]string{260 "nginx.com/health-checks": "true",261 },262 specServices: map[string]bool{},263 isPlus: true,264 appProtectEnabled: false,265 internalRoutesEnabled: false,266 expectedErrors: nil,267 msg: "valid nginx.com/health-checks annotation",268 },269 {270 annotations: map[string]string{271 "nginx.com/health-checks": "not_a_boolean",272 },273 specServices: map[string]bool{},274 isPlus: true,275 appProtectEnabled: false,276 internalRoutesEnabled: false,277 expectedErrors: []string{278 `annotations.nginx.com/health-checks: Invalid value: "not_a_boolean": must be a boolean`,279 },280 msg: "invalid nginx.com/health-checks annotation",281 },282 {283 annotations: map[string]string{284 "nginx.com/health-checks-mandatory": "true",285 },286 specServices: map[string]bool{},287 isPlus: false,288 appProtectEnabled: false,289 internalRoutesEnabled: false,290 expectedErrors: []string{291 "annotations.nginx.com/health-checks-mandatory: Forbidden: annotation requires NGINX Plus",292 },293 msg: "invalid nginx.com/health-checks-mandatory annotation, nginx plus only",294 },295 {296 annotations: map[string]string{297 "nginx.com/health-checks": "true",298 "nginx.com/health-checks-mandatory": "true",299 },300 specServices: map[string]bool{},301 isPlus: true,302 appProtectEnabled: false,303 internalRoutesEnabled: false,304 expectedErrors: nil,305 msg: "valid nginx.com/health-checks-mandatory annotation",306 },307 {308 annotations: map[string]string{309 "nginx.com/health-checks": "true",310 "nginx.com/health-checks-mandatory": "not_a_boolean",311 },312 specServices: map[string]bool{},313 isPlus: true,314 appProtectEnabled: false,315 internalRoutesEnabled: false,316 expectedErrors: []string{317 `annotations.nginx.com/health-checks-mandatory: Invalid value: "not_a_boolean": must be a boolean`,318 },319 msg: "invalid nginx.com/health-checks-mandatory, must be a boolean",320 },321 {322 annotations: map[string]string{323 "nginx.com/health-checks-mandatory": "true",324 },325 specServices: map[string]bool{},326 isPlus: true,327 appProtectEnabled: false,328 internalRoutesEnabled: false,329 expectedErrors: []string{330 "annotations.nginx.com/health-checks-mandatory: Forbidden: related annotation nginx.com/health-checks: must be set",331 },332 msg: "invalid nginx.com/health-checks-mandatory, related annotation nginx.com/health-checks not set",333 },334 {335 annotations: map[string]string{336 "nginx.com/health-checks": "false",337 "nginx.com/health-checks-mandatory": "true",338 },339 specServices: map[string]bool{},340 isPlus: true,341 appProtectEnabled: false,342 internalRoutesEnabled: false,343 expectedErrors: []string{344 "annotations.nginx.com/health-checks-mandatory: Forbidden: related annotation nginx.com/health-checks: must be true",345 },346 msg: "invalid nginx.com/health-checks-mandatory nginx.com/health-checks is not true",347 },348 {349 annotations: map[string]string{350 "nginx.com/health-checks-mandatory-queue": "true",351 },352 specServices: map[string]bool{},353 isPlus: false,354 appProtectEnabled: false,355 internalRoutesEnabled: false,356 expectedErrors: []string{357 "annotations.nginx.com/health-checks-mandatory-queue: Forbidden: annotation requires NGINX Plus",358 },359 msg: "invalid nginx.com/health-checks-mandatory-queue annotation, nginx plus only",360 },361 {362 annotations: map[string]string{363 "nginx.com/health-checks": "true",364 "nginx.com/health-checks-mandatory": "true",365 "nginx.com/health-checks-mandatory-queue": "5",366 },367 specServices: map[string]bool{},368 isPlus: true,369 appProtectEnabled: false,370 internalRoutesEnabled: false,371 expectedErrors: nil,372 msg: "valid nginx.com/health-checks-mandatory-queue annotation",373 },374 {375 annotations: map[string]string{376 "nginx.com/health-checks": "true",377 "nginx.com/health-checks-mandatory": "true",378 "nginx.com/health-checks-mandatory-queue": "not_a_number",379 },380 specServices: map[string]bool{},381 isPlus: true,382 appProtectEnabled: false,383 internalRoutesEnabled: false,384 expectedErrors: []string{385 `annotations.nginx.com/health-checks-mandatory-queue: Invalid value: "not_a_number": must be a non-negative integer`,386 },387 msg: "invalid nginx.com/health-checks-mandatory-queue, must be a number",388 },389 {390 annotations: map[string]string{391 "nginx.com/health-checks-mandatory-queue": "5",392 },393 specServices: map[string]bool{},394 isPlus: true,395 appProtectEnabled: false,396 internalRoutesEnabled: false,397 expectedErrors: []string{398 "annotations.nginx.com/health-checks-mandatory-queue: Forbidden: related annotation nginx.com/health-checks-mandatory: must be set",399 },400 msg: "invalid nginx.com/health-checks-mandatory-queue, related annotation nginx.com/health-checks-mandatory not set",401 },402 {403 annotations: map[string]string{404 "nginx.com/health-checks": "true",405 "nginx.com/health-checks-mandatory": "false",406 "nginx.com/health-checks-mandatory-queue": "5",407 },408 specServices: map[string]bool{},409 isPlus: true,410 appProtectEnabled: false,411 internalRoutesEnabled: false,412 expectedErrors: []string{413 "annotations.nginx.com/health-checks-mandatory-queue: Forbidden: related annotation nginx.com/health-checks-mandatory: must be true",414 },415 msg: "invalid nginx.com/health-checks-mandatory-queue nginx.com/health-checks-mandatory is not true",416 },417 {418 annotations: map[string]string{419 "nginx.com/slow-start": "true",420 },421 specServices: map[string]bool{},422 isPlus: false,423 appProtectEnabled: false,424 internalRoutesEnabled: false,425 expectedErrors: []string{426 "annotations.nginx.com/slow-start: Forbidden: annotation requires NGINX Plus",427 },428 msg: "invalid nginx.com/slow-start annotation, nginx plus only",429 },430 {431 annotations: map[string]string{432 "nginx.com/slow-start": "60s",433 },434 specServices: map[string]bool{},435 isPlus: true,436 appProtectEnabled: false,437 internalRoutesEnabled: false,438 expectedErrors: nil,439 msg: "valid nginx.com/slow-start annotation",440 },441 {442 annotations: map[string]string{443 "nginx.com/slow-start": "not_a_time",444 },445 specServices: map[string]bool{},446 isPlus: true,447 appProtectEnabled: false,448 internalRoutesEnabled: false,449 expectedErrors: []string{450 `annotations.nginx.com/slow-start: Invalid value: "not_a_time": must be a time`,451 },452 msg: "invalid nginx.com/slow-start annotation",453 },454 {455 annotations: map[string]string{456 "nginx.org/server-tokens": "true",457 },458 specServices: map[string]bool{},459 isPlus: false,460 appProtectEnabled: false,461 internalRoutesEnabled: false,462 expectedErrors: nil,463 msg: "valid nginx.org/server-tokens annotation, nginx",464 },465 {466 annotations: map[string]string{467 "nginx.org/server-tokens": "custom_setting",468 },469 specServices: map[string]bool{},470 isPlus: true,471 appProtectEnabled: false,472 internalRoutesEnabled: false,473 expectedErrors: nil,474 msg: "valid nginx.org/server-tokens annotation, nginx plus",475 },476 {477 annotations: map[string]string{478 "nginx.org/server-tokens": "custom_setting",479 },480 specServices: map[string]bool{},481 isPlus: false,482 appProtectEnabled: false,483 internalRoutesEnabled: false,484 expectedErrors: []string{485 `annotations.nginx.org/server-tokens: Invalid value: "custom_setting": must be a boolean`,486 },487 msg: "invalid nginx.org/server-tokens annotation, must be a boolean",488 },489 {490 annotations: map[string]string{491 "nginx.org/server-snippets": "snippet-1",492 },493 specServices: map[string]bool{},494 isPlus: false,495 appProtectEnabled: false,496 internalRoutesEnabled: false,497 expectedErrors: nil,498 msg: "valid nginx.org/server-snippets annotation, single-value",499 },500 {501 annotations: map[string]string{502 "nginx.org/server-snippets": "snippet-1\nsnippet-2\nsnippet-3",503 },504 specServices: map[string]bool{},505 isPlus: false,506 appProtectEnabled: false,507 internalRoutesEnabled: false,508 expectedErrors: nil,509 msg: "valid nginx.org/server-snippets annotation, multi-value",510 },511 {512 annotations: map[string]string{513 "nginx.org/location-snippets": "snippet-1",514 },515 specServices: map[string]bool{},516 isPlus: false,517 appProtectEnabled: false,518 internalRoutesEnabled: false,519 expectedErrors: nil,520 msg: "valid nginx.org/location-snippets annotation, single-value",521 },522 {523 annotations: map[string]string{524 "nginx.org/location-snippets": "snippet-1\nsnippet-2\nsnippet-3",525 },526 specServices: map[string]bool{},527 isPlus: false,528 appProtectEnabled: false,529 internalRoutesEnabled: false,530 expectedErrors: nil,531 msg: "valid nginx.org/location-snippets annotation, multi-value",532 },533 {534 annotations: map[string]string{535 "nginx.org/proxy-connect-timeout": "10s",536 },537 specServices: map[string]bool{},538 isPlus: false,539 appProtectEnabled: false,540 internalRoutesEnabled: false,541 expectedErrors: nil,542 msg: "valid nginx.org/proxy-connect-timeout annotation",543 },544 {545 annotations: map[string]string{546 "nginx.org/proxy-connect-timeout": "not_a_time",547 },548 specServices: map[string]bool{},549 isPlus: false,550 appProtectEnabled: false,551 internalRoutesEnabled: false,552 expectedErrors: []string{553 `annotations.nginx.org/proxy-connect-timeout: Invalid value: "not_a_time": must be a time`,554 },555 msg: "invalid nginx.org/proxy-connect-timeout annotation",556 },557 {558 annotations: map[string]string{559 "nginx.org/proxy-read-timeout": "10s",560 },561 specServices: map[string]bool{},562 isPlus: false,563 appProtectEnabled: false,564 internalRoutesEnabled: false,565 expectedErrors: nil,566 msg: "valid nginx.org/proxy-read-timeout annotation",567 },568 {569 annotations: map[string]string{570 "nginx.org/proxy-read-timeout": "not_a_time",571 },572 specServices: map[string]bool{},573 isPlus: false,574 appProtectEnabled: false,575 internalRoutesEnabled: false,576 expectedErrors: []string{577 `annotations.nginx.org/proxy-read-timeout: Invalid value: "not_a_time": must be a time`,578 },579 msg: "invalid nginx.org/proxy-read-timeout annotation",580 },581 {582 annotations: map[string]string{583 "nginx.org/proxy-send-timeout": "10s",584 },585 specServices: map[string]bool{},586 isPlus: false,587 appProtectEnabled: false,588 internalRoutesEnabled: false,589 expectedErrors: nil,590 msg: "valid nginx.org/proxy-send-timeout annotation",591 },592 {593 annotations: map[string]string{594 "nginx.org/proxy-send-timeout": "not_a_time",595 },596 specServices: map[string]bool{},597 isPlus: false,598 appProtectEnabled: false,599 internalRoutesEnabled: false,600 expectedErrors: []string{601 `annotations.nginx.org/proxy-send-timeout: Invalid value: "not_a_time": must be a time`,602 },603 msg: "invalid nginx.org/proxy-send-timeout annotation",604 },605 {606 annotations: map[string]string{607 "nginx.org/proxy-hide-headers": "header-1",608 },609 specServices: map[string]bool{},610 isPlus: false,611 appProtectEnabled: false,612 internalRoutesEnabled: false,613 expectedErrors: nil,614 msg: "valid nginx.org/proxy-hide-headers annotation, single-value",615 },616 {617 annotations: map[string]string{618 "nginx.org/proxy-hide-headers": "header-1,header-2,header-3",619 },620 specServices: map[string]bool{},621 isPlus: false,622 appProtectEnabled: false,623 internalRoutesEnabled: false,624 expectedErrors: nil,625 msg: "valid nginx.org/proxy-hide-headers annotation, multi-value",626 },627 {628 annotations: map[string]string{629 "nginx.org/proxy-pass-headers": "header-1",630 },631 specServices: map[string]bool{},632 isPlus: false,633 appProtectEnabled: false,634 internalRoutesEnabled: false,635 expectedErrors: nil,636 msg: "valid nginx.org/proxy-pass-headers annotation, single-value",637 },638 {639 annotations: map[string]string{640 "nginx.org/proxy-pass-headers": "header-1,header-2,header-3",641 },642 specServices: map[string]bool{},643 isPlus: false,644 appProtectEnabled: false,645 internalRoutesEnabled: false,646 expectedErrors: nil,647 msg: "valid nginx.org/proxy-pass-headers annotation, multi-value",648 },649 {650 annotations: map[string]string{651 "nginx.org/client-max-body-size": "16M",652 },653 specServices: map[string]bool{},654 isPlus: false,655 appProtectEnabled: false,656 internalRoutesEnabled: false,657 expectedErrors: nil,658 msg: "valid nginx.org/client-max-body-size annotation",659 },660 {661 annotations: map[string]string{662 "nginx.org/client-max-body-size": "not_an_offset",663 },664 specServices: map[string]bool{},665 isPlus: false,666 appProtectEnabled: false,667 internalRoutesEnabled: false,668 expectedErrors: []string{669 `annotations.nginx.org/client-max-body-size: Invalid value: "not_an_offset": must be an offset`,670 },671 msg: "invalid nginx.org/client-max-body-size annotation",672 },673 {674 annotations: map[string]string{675 "nginx.org/redirect-to-https": "true",676 },677 specServices: map[string]bool{},678 isPlus: false,679 appProtectEnabled: false,680 internalRoutesEnabled: false,681 expectedErrors: nil,682 msg: "valid nginx.org/redirect-to-https annotation",683 },684 {685 annotations: map[string]string{686 "nginx.org/redirect-to-https": "not_a_boolean",687 },688 specServices: map[string]bool{},689 isPlus: false,690 appProtectEnabled: false,691 internalRoutesEnabled: false,692 expectedErrors: []string{693 `annotations.nginx.org/redirect-to-https: Invalid value: "not_a_boolean": must be a boolean`,694 },695 msg: "invalid nginx.org/redirect-to-https annotation",696 },697 {698 annotations: map[string]string{699 "ingress.kubernetes.io/ssl-redirect": "true",700 },701 specServices: map[string]bool{},702 isPlus: false,703 appProtectEnabled: false,704 internalRoutesEnabled: false,705 expectedErrors: nil,706 msg: "valid ingress.kubernetes.io/ssl-redirect annotation",707 },708 {709 annotations: map[string]string{710 "ingress.kubernetes.io/ssl-redirect": "not_a_boolean",711 },712 specServices: map[string]bool{},713 isPlus: false,714 appProtectEnabled: false,715 internalRoutesEnabled: false,716 expectedErrors: []string{717 `annotations.ingress.kubernetes.io/ssl-redirect: Invalid value: "not_a_boolean": must be a boolean`,718 },719 msg: "invalid ingress.kubernetes.io/ssl-redirect annotation",720 },721 {722 annotations: map[string]string{723 "nginx.org/proxy-buffering": "true",724 },725 specServices: map[string]bool{},726 isPlus: false,727 appProtectEnabled: false,728 internalRoutesEnabled: false,729 expectedErrors: nil,730 msg: "valid nginx.org/proxy-buffering annotation",731 },732 {733 annotations: map[string]string{734 "nginx.org/proxy-buffering": "not_a_boolean",735 },736 specServices: map[string]bool{},737 isPlus: false,738 appProtectEnabled: false,739 internalRoutesEnabled: false,740 expectedErrors: []string{741 `annotations.nginx.org/proxy-buffering: Invalid value: "not_a_boolean": must be a boolean`,742 },743 msg: "invalid nginx.org/proxy-buffering annotation",744 },745 {746 annotations: map[string]string{747 "nginx.org/hsts": "true",748 },749 specServices: map[string]bool{},750 isPlus: false,751 appProtectEnabled: false,752 internalRoutesEnabled: false,753 expectedErrors: nil,754 msg: "valid nginx.org/hsts annotation",755 },756 {757 annotations: map[string]string{758 "nginx.org/hsts": "not_a_boolean",759 },760 specServices: map[string]bool{},761 isPlus: false,762 appProtectEnabled: false,763 internalRoutesEnabled: false,764 expectedErrors: []string{765 `annotations.nginx.org/hsts: Invalid value: "not_a_boolean": must be a boolean`,766 },767 msg: "invalid nginx.org/hsts annotation",768 },769 {770 annotations: map[string]string{771 "nginx.org/hsts": "true",772 "nginx.org/hsts-max-age": "120",773 },774 specServices: map[string]bool{},775 isPlus: false,776 appProtectEnabled: false,777 internalRoutesEnabled: false,778 expectedErrors: nil,779 msg: "valid nginx.org/hsts-max-age annotation",780 },781 {782 annotations: map[string]string{783 "nginx.org/hsts": "false",784 "nginx.org/hsts-max-age": "120",785 },786 specServices: map[string]bool{},787 isPlus: false,788 appProtectEnabled: false,789 internalRoutesEnabled: false,790 expectedErrors: nil,791 msg: "valid nginx.org/hsts-max-age nginx.org/hsts can be false",792 },793 {794 annotations: map[string]string{795 "nginx.org/hsts": "true",796 "nginx.org/hsts-max-age": "not_a_number",797 },798 specServices: map[string]bool{},799 isPlus: false,800 appProtectEnabled: false,801 internalRoutesEnabled: false,802 expectedErrors: []string{803 `annotations.nginx.org/hsts-max-age: Invalid value: "not_a_number": must be an integer`,804 },805 msg: "invalid nginx.org/hsts-max-age, must be a number",806 },807 {808 annotations: map[string]string{809 "nginx.org/hsts-max-age": "true",810 },811 specServices: map[string]bool{},812 isPlus: false,813 appProtectEnabled: false,814 internalRoutesEnabled: false,815 expectedErrors: []string{816 "annotations.nginx.org/hsts-max-age: Forbidden: related annotation nginx.org/hsts: must be set",817 },818 msg: "invalid nginx.org/hsts-max-age, related annotation nginx.org/hsts not set",819 },820 {821 annotations: map[string]string{822 "nginx.org/hsts": "true",823 "nginx.org/hsts-include-subdomains": "true",824 },825 specServices: map[string]bool{},826 isPlus: false,827 appProtectEnabled: false,828 internalRoutesEnabled: false,829 expectedErrors: nil,830 msg: "valid nginx.org/hsts-include-subdomains annotation",831 },832 {833 annotations: map[string]string{834 "nginx.org/hsts": "false",835 "nginx.org/hsts-include-subdomains": "true",836 },837 specServices: map[string]bool{},838 isPlus: false,839 appProtectEnabled: false,840 internalRoutesEnabled: false,841 expectedErrors: nil,842 msg: "valid nginx.org/hsts-include-subdomains, nginx.org/hsts can be false",843 },844 {845 annotations: map[string]string{846 "nginx.org/hsts": "true",847 "nginx.org/hsts-include-subdomains": "not_a_boolean",848 },849 specServices: map[string]bool{},850 isPlus: false,851 appProtectEnabled: false,852 internalRoutesEnabled: false,853 expectedErrors: []string{854 `annotations.nginx.org/hsts-include-subdomains: Invalid value: "not_a_boolean": must be a boolean`,855 },856 msg: "invalid nginx.org/hsts-include-subdomains, must be a boolean",857 },858 {859 annotations: map[string]string{860 "nginx.org/hsts-include-subdomains": "true",861 },862 specServices: map[string]bool{},863 isPlus: false,864 appProtectEnabled: false,865 internalRoutesEnabled: false,866 expectedErrors: []string{867 "annotations.nginx.org/hsts-include-subdomains: Forbidden: related annotation nginx.org/hsts: must be set",868 },869 msg: "invalid nginx.org/hsts-include-subdomains, related annotation nginx.org/hsts not set",870 },871 {872 annotations: map[string]string{873 "nginx.org/hsts": "true",874 "nginx.org/hsts-behind-proxy": "true",875 },876 specServices: map[string]bool{},877 isPlus: false,878 appProtectEnabled: false,879 internalRoutesEnabled: false,880 expectedErrors: nil,881 msg: "valid nginx.org/hsts-behind-proxy annotation",882 },883 {884 annotations: map[string]string{885 "nginx.org/hsts": "false",886 "nginx.org/hsts-behind-proxy": "true",887 },888 specServices: map[string]bool{},889 isPlus: false,890 appProtectEnabled: false,891 internalRoutesEnabled: false,892 expectedErrors: nil,893 msg: "valid nginx.org/hsts-behind-proxy, nginx.org/hsts can be false",894 },895 {896 annotations: map[string]string{897 "nginx.org/hsts": "true",898 "nginx.org/hsts-behind-proxy": "not_a_boolean",899 },900 specServices: map[string]bool{},901 isPlus: false,902 appProtectEnabled: false,903 internalRoutesEnabled: false,904 expectedErrors: []string{905 `annotations.nginx.org/hsts-behind-proxy: Invalid value: "not_a_boolean": must be a boolean`,906 },907 msg: "invalid nginx.org/hsts-behind-proxy, must be a boolean",908 },909 {910 annotations: map[string]string{911 "nginx.org/hsts-behind-proxy": "true",912 },913 specServices: map[string]bool{},914 isPlus: false,915 appProtectEnabled: false,916 internalRoutesEnabled: false,917 expectedErrors: []string{918 "annotations.nginx.org/hsts-behind-proxy: Forbidden: related annotation nginx.org/hsts: must be set",919 },920 msg: "invalid nginx.org/hsts-behind-proxy, related annotation nginx.org/hsts not set",921 },922 {923 annotations: map[string]string{924 "nginx.org/proxy-buffers": "8 8k",925 },926 specServices: map[string]bool{},927 isPlus: false,928 appProtectEnabled: false,929 internalRoutesEnabled: false,930 expectedErrors: nil,931 msg: "valid nginx.org/proxy-buffers annotation",932 },933 {934 annotations: map[string]string{935 "nginx.org/proxy-buffers": "not_a_proxy_buffers_spec",936 },937 specServices: map[string]bool{},938 isPlus: false,939 appProtectEnabled: false,940 internalRoutesEnabled: false,941 expectedErrors: []string{942 `annotations.nginx.org/proxy-buffers: Invalid value: "not_a_proxy_buffers_spec": must be a proxy buffer spec`,943 },944 msg: "invalid nginx.org/proxy-buffers annotation",945 },946 {947 annotations: map[string]string{948 "nginx.org/proxy-buffer-size": "16k",949 },950 specServices: map[string]bool{},951 isPlus: false,952 appProtectEnabled: false,953 internalRoutesEnabled: false,954 expectedErrors: nil,955 msg: "valid nginx.org/proxy-buffer-size annotation",956 },957 {958 annotations: map[string]string{959 "nginx.org/proxy-buffer-size": "not_a_size",960 },961 specServices: map[string]bool{},962 isPlus: false,963 appProtectEnabled: false,964 internalRoutesEnabled: false,965 expectedErrors: []string{966 `annotations.nginx.org/proxy-buffer-size: Invalid value: "not_a_size": must be a size`,967 },968 msg: "invalid nginx.org/proxy-buffer-size annotation",969 },970 {971 annotations: map[string]string{972 "nginx.org/proxy-max-temp-file-size": "128M",973 },974 specServices: map[string]bool{},975 isPlus: false,976 appProtectEnabled: false,977 internalRoutesEnabled: false,978 expectedErrors: nil,979 msg: "valid nginx.org/proxy-max-temp-file-size annotation",980 },981 {982 annotations: map[string]string{983 "nginx.org/proxy-max-temp-file-size": "not_a_size",984 },985 specServices: map[string]bool{},986 isPlus: false,987 appProtectEnabled: false,988 internalRoutesEnabled: false,989 expectedErrors: []string{990 `annotations.nginx.org/proxy-max-temp-file-size: Invalid value: "not_a_size": must be a size`,991 },992 msg: "invalid nginx.org/proxy-max-temp-file-size annotation",993 },994 {995 annotations: map[string]string{996 "nginx.org/upstream-zone-size": "512k",997 },998 specServices: map[string]bool{},999 isPlus: false,1000 appProtectEnabled: false,1001 internalRoutesEnabled: false,1002 expectedErrors: nil,1003 msg: "valid nginx.org/upstream-zone-size annotation",1004 },1005 {1006 annotations: map[string]string{1007 "nginx.org/upstream-zone-size": "not a size",1008 },1009 specServices: map[string]bool{},1010 isPlus: false,1011 appProtectEnabled: false,1012 internalRoutesEnabled: false,1013 expectedErrors: []string{1014 `annotations.nginx.org/upstream-zone-size: Invalid value: "not a size": must be a size`,1015 },1016 msg: "invalid nginx.org/upstream-zone-size annotation",1017 },1018 {1019 annotations: map[string]string{1020 "nginx.com/jwt-realm": "true",1021 },1022 specServices: map[string]bool{},1023 isPlus: false,1024 appProtectEnabled: false,1025 internalRoutesEnabled: false,1026 expectedErrors: []string{1027 "annotations.nginx.com/jwt-realm: Forbidden: annotation requires NGINX Plus",1028 },1029 msg: "invalid nginx.com/jwt-realm annotation, nginx plus only",1030 },1031 {1032 annotations: map[string]string{1033 "nginx.com/jwt-realm": "my-jwt-realm",1034 },1035 specServices: map[string]bool{},1036 isPlus: true,1037 appProtectEnabled: false,1038 internalRoutesEnabled: false,1039 expectedErrors: nil,1040 msg: "valid nginx.com/jwt-realm annotation",1041 },1042 {1043 annotations: map[string]string{1044 "nginx.com/jwt-key": "true",1045 },1046 specServices: map[string]bool{},1047 isPlus: false,1048 appProtectEnabled: false,1049 internalRoutesEnabled: false,1050 expectedErrors: []string{1051 "annotations.nginx.com/jwt-key: Forbidden: annotation requires NGINX Plus",1052 },1053 msg: "invalid nginx.com/jwt-key annotation, nginx plus only",1054 },1055 {1056 annotations: map[string]string{1057 "nginx.com/jwt-key": "my-jwk",1058 },1059 specServices: map[string]bool{},1060 isPlus: true,1061 appProtectEnabled: false,1062 internalRoutesEnabled: false,1063 expectedErrors: nil,1064 msg: "valid nginx.com/jwt-key annotation",1065 },1066 {1067 annotations: map[string]string{1068 "nginx.com/jwt-token": "true",1069 },1070 specServices: map[string]bool{},1071 isPlus: false,1072 appProtectEnabled: false,1073 internalRoutesEnabled: false,1074 expectedErrors: []string{1075 "annotations.nginx.com/jwt-token: Forbidden: annotation requires NGINX Plus",1076 },1077 msg: "invalid nginx.com/jwt-token annotation, nginx plus only",1078 },1079 {1080 annotations: map[string]string{1081 "nginx.com/jwt-token": "$cookie_auth_token",1082 },1083 specServices: map[string]bool{},1084 isPlus: true,1085 appProtectEnabled: false,1086 internalRoutesEnabled: false,1087 expectedErrors: nil,1088 msg: "valid nginx.com/jwt-token annotation",1089 },1090 {1091 annotations: map[string]string{1092 "nginx.com/jwt-login-url": "true",1093 },1094 specServices: map[string]bool{},1095 isPlus: false,1096 appProtectEnabled: false,1097 internalRoutesEnabled: false,1098 expectedErrors: []string{1099 "annotations.nginx.com/jwt-login-url: Forbidden: annotation requires NGINX Plus",1100 },1101 msg: "invalid nginx.com/jwt-login-url annotation, nginx plus only",1102 },1103 {1104 annotations: map[string]string{1105 "nginx.com/jwt-login-url": "https://login.example.com",1106 },1107 specServices: map[string]bool{},1108 isPlus: true,1109 appProtectEnabled: false,1110 internalRoutesEnabled: false,1111 expectedErrors: nil,1112 msg: "valid nginx.com/jwt-login-url annotation",1113 },1114 {1115 annotations: map[string]string{1116 "nginx.org/listen-ports": "80,8080,9090",1117 },1118 specServices: map[string]bool{},1119 isPlus: false,1120 appProtectEnabled: false,1121 internalRoutesEnabled: false,1122 expectedErrors: nil,1123 msg: "valid nginx.org/listen-ports annotation",1124 },1125 {1126 annotations: map[string]string{1127 "nginx.org/listen-ports": "not_a_port_list",1128 },1129 specServices: map[string]bool{},1130 isPlus: false,1131 appProtectEnabled: false,1132 internalRoutesEnabled: false,1133 expectedErrors: []string{1134 `annotations.nginx.org/listen-ports: Invalid value: "not_a_port_list": must be a comma-separated list of port numbers`,1135 },1136 msg: "invalid nginx.org/listen-ports annotation",1137 },1138 {1139 annotations: map[string]string{1140 "nginx.org/listen-ports-ssl": "443,8443",1141 },1142 specServices: map[string]bool{},1143 isPlus: false,1144 appProtectEnabled: false,1145 internalRoutesEnabled: false,1146 expectedErrors: nil,1147 msg: "valid nginx.org/listen-ports-ssl annotation",1148 },1149 {1150 annotations: map[string]string{1151 "nginx.org/listen-ports-ssl": "not_a_port_list",1152 },1153 specServices: map[string]bool{},1154 isPlus: false,1155 appProtectEnabled: false,1156 internalRoutesEnabled: false,1157 expectedErrors: []string{1158 `annotations.nginx.org/listen-ports-ssl: Invalid value: "not_a_port_list": must be a comma-separated list of port numbers`,1159 },1160 msg: "invalid nginx.org/listen-ports-ssl annotation",1161 },1162 {1163 annotations: map[string]string{1164 "nginx.org/keepalive": "1000",1165 },1166 specServices: map[string]bool{},1167 isPlus: false,1168 appProtectEnabled: false,1169 internalRoutesEnabled: false,1170 expectedErrors: nil,1171 msg: "valid nginx.org/keepalive annotation",1172 },1173 {1174 annotations: map[string]string{1175 "nginx.org/keepalive": "not_a_number",1176 },1177 specServices: map[string]bool{},1178 isPlus: false,1179 appProtectEnabled: false,1180 internalRoutesEnabled: false,1181 expectedErrors: []string{1182 `annotations.nginx.org/keepalive: Invalid value: "not_a_number": must be an integer`,1183 },1184 msg: "invalid nginx.org/keepalive annotation",1185 },1186 {1187 annotations: map[string]string{1188 "nginx.org/max-fails": "5",1189 },1190 specServices: map[string]bool{},1191 isPlus: false,1192 appProtectEnabled: false,1193 internalRoutesEnabled: false,1194 expectedErrors: nil,1195 msg: "valid nginx.org/max-fails annotation",1196 },1197 {1198 annotations: map[string]string{1199 "nginx.org/max-fails": "-100",1200 },1201 specServices: map[string]bool{},1202 isPlus: false,1203 appProtectEnabled: false,1204 internalRoutesEnabled: false,1205 expectedErrors: []string{1206 `annotations.nginx.org/max-fails: Invalid value: "-100": must be a non-negative integer`,1207 },1208 msg: "invalid nginx.org/max-fails annotation, negative number",1209 },1210 {1211 annotations: map[string]string{1212 "nginx.org/max-fails": "not_a_number",1213 },1214 specServices: map[string]bool{},1215 isPlus: false,1216 appProtectEnabled: false,1217 internalRoutesEnabled: false,1218 expectedErrors: []string{1219 `annotations.nginx.org/max-fails: Invalid value: "not_a_number": must be a non-negative integer`,1220 },1221 msg: "invalid nginx.org/max-fails annotation, not a number",1222 },1223 {1224 annotations: map[string]string{1225 "nginx.org/max-conns": "10",1226 },1227 specServices: map[string]bool{},1228 isPlus: false,1229 appProtectEnabled: false,1230 internalRoutesEnabled: false,1231 expectedErrors: nil,1232 msg: "valid nginx.org/max-conns annotation",1233 },1234 {1235 annotations: map[string]string{1236 "nginx.org/max-conns": "-100",1237 },1238 specServices: map[string]bool{},1239 isPlus: false,1240 appProtectEnabled: false,1241 internalRoutesEnabled: false,1242 expectedErrors: []string{1243 `annotations.nginx.org/max-conns: Invalid value: "-100": must be a non-negative integer`,1244 },1245 msg: "invalid nginx.org/max-conns annotation, negative number",1246 },1247 {1248 annotations: map[string]string{1249 "nginx.org/max-conns": "not_a_number",1250 },1251 specServices: map[string]bool{},1252 isPlus: false,1253 appProtectEnabled: false,1254 internalRoutesEnabled: false,1255 expectedErrors: []string{1256 `annotations.nginx.org/max-conns: Invalid value: "not_a_number": must be a non-negative integer`,1257 },1258 msg: "invalid nginx.org/max-conns annotation",1259 },1260 {1261 annotations: map[string]string{1262 "nginx.org/fail-timeout": "10s",1263 },1264 specServices: map[string]bool{},1265 isPlus: false,1266 appProtectEnabled: false,1267 internalRoutesEnabled: false,1268 expectedErrors: nil,1269 msg: "valid nginx.org/fail-timeout annotation",1270 },1271 {1272 annotations: map[string]string{1273 "nginx.org/fail-timeout": "not_a_time",1274 },1275 specServices: map[string]bool{},1276 isPlus: false,1277 appProtectEnabled: false,1278 internalRoutesEnabled: false,1279 expectedErrors: []string{1280 `annotations.nginx.org/fail-timeout: Invalid value: "not_a_time": must be a time`,1281 },1282 msg: "invalid nginx.org/fail-timeout annotation",1283 },1284 {1285 annotations: map[string]string{1286 "appprotect.f5.com/app-protect-enable": "true",1287 },1288 specServices: map[string]bool{},1289 isPlus: true,1290 appProtectEnabled: false,1291 internalRoutesEnabled: false,1292 expectedErrors: []string{1293 "annotations.appprotect.f5.com/app-protect-enable: Forbidden: annotation requires AppProtect",1294 },1295 msg: "invalid appprotect.f5.com/app-protect-enable annotation, requires app protect",1296 },1297 {1298 annotations: map[string]string{1299 "appprotect.f5.com/app-protect-enable": "true",1300 },1301 specServices: map[string]bool{},1302 isPlus: true,1303 appProtectEnabled: true,1304 internalRoutesEnabled: false,1305 expectedErrors: nil,1306 msg: "valid appprotect.f5.com/app-protect-enable annotation",1307 },1308 {1309 annotations: map[string]string{1310 "appprotect.f5.com/app-protect-enable": "not_a_boolean",1311 },1312 specServices: map[string]bool{},1313 isPlus: true,1314 appProtectEnabled: true,1315 internalRoutesEnabled: false,1316 expectedErrors: []string{1317 `annotations.appprotect.f5.com/app-protect-enable: Invalid value: "not_a_boolean": must be a boolean`,1318 },1319 msg: "invalid appprotect.f5.com/app-protect-enable annotation",1320 },1321 {1322 annotations: map[string]string{1323 "appprotect.f5.com/app-protect-security-log-enable": "true",1324 },1325 specServices: map[string]bool{},1326 isPlus: true,1327 appProtectEnabled: false,1328 internalRoutesEnabled: false,1329 expectedErrors: []string{1330 "annotations.appprotect.f5.com/app-protect-security-log-enable: Forbidden: annotation requires AppProtect",1331 },1332 msg: "invalid appprotect.f5.com/app-protect-security-log-enable annotation, requires app protect",1333 },1334 {1335 annotations: map[string]string{1336 "appprotect.f5.com/app-protect-security-log-enable": "true",1337 },1338 specServices: map[string]bool{},1339 isPlus: true,1340 appProtectEnabled: true,1341 internalRoutesEnabled: false,1342 expectedErrors: nil,1343 msg: "valid appprotect.f5.com/app-protect-security-log-enable annotation",1344 },1345 {1346 annotations: map[string]string{1347 "appprotect.f5.com/app-protect-security-log-enable": "not_a_boolean",1348 },1349 specServices: map[string]bool{},1350 isPlus: true,1351 appProtectEnabled: true,1352 internalRoutesEnabled: false,1353 expectedErrors: []string{1354 `annotations.appprotect.f5.com/app-protect-security-log-enable: Invalid value: "not_a_boolean": must be a boolean`,1355 },1356 msg: "invalid appprotect.f5.com/app-protect-security-log-enable annotation",1357 },1358 {1359 annotations: map[string]string{1360 "nsm.nginx.com/internal-route": "true",1361 },1362 specServices: map[string]bool{},1363 isPlus: true,1364 appProtectEnabled: false,1365 internalRoutesEnabled: false,1366 expectedErrors: []string{1367 "annotations.nsm.nginx.com/internal-route: Forbidden: annotation requires Internal Routes enabled",1368 },1369 msg: "invalid nsm.nginx.com/internal-route annotation, requires internal routes",1370 },1371 {1372 annotations: map[string]string{1373 "nsm.nginx.com/internal-route": "true",1374 },1375 specServices: map[string]bool{},1376 isPlus: true,1377 appProtectEnabled: false,1378 internalRoutesEnabled: true,1379 expectedErrors: nil,1380 msg: "valid nsm.nginx.com/internal-route annotation",1381 },1382 {1383 annotations: map[string]string{1384 "nsm.nginx.com/internal-route": "not_a_boolean",1385 },1386 specServices: map[string]bool{},1387 isPlus: true,1388 appProtectEnabled: false,1389 internalRoutesEnabled: true,1390 expectedErrors: []string{1391 `annotations.nsm.nginx.com/internal-route: Invalid value: "not_a_boolean": must be a boolean`,1392 },1393 msg: "invalid nsm.nginx.com/internal-route annotation",1394 },1395 {1396 annotations: map[string]string{1397 "nginx.org/websocket-services": "service-1",1398 },1399 specServices: map[string]bool{1400 "service-1": true,1401 },1402 isPlus: false,1403 appProtectEnabled: false,1404 internalRoutesEnabled: false,1405 expectedErrors: nil,1406 msg: "valid nginx.org/websocket-services annotation, single-value",1407 },1408 {1409 annotations: map[string]string{1410 "nginx.org/websocket-services": "service-1,service-2",1411 },1412 specServices: map[string]bool{1413 "service-1": true,1414 "service-2": true,1415 },1416 isPlus: false,1417 appProtectEnabled: false,1418 internalRoutesEnabled: false,1419 expectedErrors: nil,1420 msg: "valid nginx.org/websocket-services annotation, multi-value",1421 },1422 {1423 annotations: map[string]string{1424 "nginx.org/websocket-services": "service-1,service-2",1425 },1426 specServices: map[string]bool{1427 "service-1": true,1428 },1429 isPlus: false,1430 appProtectEnabled: false,1431 internalRoutesEnabled: false,1432 expectedErrors: []string{1433 `annotations.nginx.org/websocket-services: Invalid value: "service-1,service-2": must be a comma-separated list of services. The following services were not found: service-2`,1434 },1435 msg: "invalid nginx.org/websocket-services annotation, service does not exist",1436 },1437 {1438 annotations: map[string]string{1439 "nginx.org/ssl-services": "service-1",1440 },1441 specServices: map[string]bool{1442 "service-1": true,1443 },1444 isPlus: false,1445 appProtectEnabled: false,1446 internalRoutesEnabled: false,1447 expectedErrors: nil,1448 msg: "valid nginx.org/ssl-services annotation, single-value",1449 },1450 {1451 annotations: map[string]string{1452 "nginx.org/ssl-services": "service-1,service-2",1453 },1454 specServices: map[string]bool{1455 "service-1": true,1456 "service-2": true,1457 },1458 isPlus: false,1459 appProtectEnabled: false,1460 internalRoutesEnabled: false,1461 expectedErrors: nil,1462 msg: "valid nginx.org/ssl-services annotation, multi-value",1463 },1464 {1465 annotations: map[string]string{1466 "nginx.org/ssl-services": "service-1,service-2",1467 },1468 specServices: map[string]bool{1469 "service-1": true,1470 },1471 isPlus: false,1472 appProtectEnabled: false,1473 internalRoutesEnabled: false,1474 expectedErrors: []string{1475 `annotations.nginx.org/ssl-services: Invalid value: "service-1,service-2": must be a comma-separated list of services. The following services were not found: service-2`,1476 },1477 msg: "invalid nginx.org/ssl-services annotation, service does not exist",1478 },1479 {1480 annotations: map[string]string{1481 "nginx.org/grpc-services": "service-1",1482 },1483 specServices: map[string]bool{1484 "service-1": true,1485 },1486 isPlus: false,1487 appProtectEnabled: false,1488 internalRoutesEnabled: false,1489 expectedErrors: nil,1490 msg: "valid nginx.org/grpc-services annotation, single-value",1491 },1492 {1493 annotations: map[string]string{1494 "nginx.org/grpc-services": "service-1,service-2",1495 },1496 specServices: map[string]bool{1497 "service-1": true,1498 "service-2": true,1499 },1500 isPlus: false,1501 appProtectEnabled: false,1502 internalRoutesEnabled: false,1503 expectedErrors: nil,1504 msg: "valid nginx.org/grpc-services annotation, multi-value",1505 },1506 {1507 annotations: map[string]string{1508 "nginx.org/grpc-services": "service-1,service-2",1509 },1510 specServices: map[string]bool{1511 "service-1": true,1512 },1513 isPlus: false,1514 appProtectEnabled: false,1515 internalRoutesEnabled: false,1516 expectedErrors: []string{1517 `annotations.nginx.org/grpc-services: Invalid value: "service-1,service-2": must be a comma-separated list of services. The following services were not found: service-2`,1518 },1519 msg: "invalid nginx.org/grpc-services annotation, service does not exist",1520 },1521 {1522 annotations: map[string]string{1523 "nginx.org/rewrites": "serviceName=service-1 rewrite=rewrite-1",1524 },1525 specServices: map[string]bool{},1526 isPlus: false,1527 appProtectEnabled: false,1528 internalRoutesEnabled: false,1529 expectedErrors: nil,1530 msg: "valid nginx.org/rewrites annotation, single-value",1531 },1532 {1533 annotations: map[string]string{1534 "nginx.org/rewrites": "serviceName=service-1 rewrite=rewrite-1;serviceName=service-2 rewrite=rewrite-2",1535 },1536 specServices: map[string]bool{},1537 isPlus: false,1538 appProtectEnabled: false,1539 internalRoutesEnabled: false,1540 expectedErrors: nil,1541 msg: "valid nginx.org/rewrites annotation, multi-value",1542 },1543 {1544 annotations: map[string]string{1545 "nginx.org/rewrites": "not_a_rewrite",1546 },1547 specServices: map[string]bool{},1548 isPlus: true,1549 appProtectEnabled: false,1550 internalRoutesEnabled: true,1551 expectedErrors: []string{1552 `annotations.nginx.org/rewrites: Invalid value: "not_a_rewrite": must be a semicolon-separated list of rewrites`,1553 },1554 msg: "invalid nginx.org/rewrites annotation",1555 },1556 {1557 annotations: map[string]string{1558 "nginx.com/sticky-cookie-services": "true",1559 },1560 specServices: map[string]bool{},1561 isPlus: false,1562 appProtectEnabled: false,1563 internalRoutesEnabled: false,1564 expectedErrors: []string{1565 "annotations.nginx.com/sticky-cookie-services: Forbidden: annotation requires NGINX Plus",1566 },1567 msg: "invalid nginx.com/sticky-cookie-services annotation, nginx plus only",1568 },1569 {1570 annotations: map[string]string{1571 "nginx.com/sticky-cookie-services": "serviceName=service-1 srv_id expires=1h path=/service-1",1572 },1573 specServices: map[string]bool{},1574 isPlus: true,1575 appProtectEnabled: false,1576 internalRoutesEnabled: false,1577 expectedErrors: nil,1578 msg: "valid nginx.com/sticky-cookie-services annotation, single-value",1579 },1580 {1581 annotations: map[string]string{1582 "nginx.com/sticky-cookie-services": "serviceName=service-1 srv_id expires=1h path=/service-1;serviceName=service-2 srv_id expires=2h path=/service-2",1583 },1584 specServices: map[string]bool{},1585 isPlus: true,1586 appProtectEnabled: false,1587 internalRoutesEnabled: false,1588 expectedErrors: nil,1589 msg: "valid nginx.com/sticky-cookie-services annotation, multi-value",1590 },1591 {1592 annotations: map[string]string{1593 "nginx.com/sticky-cookie-services": "not_a_rewrite",1594 },1595 specServices: map[string]bool{},1596 isPlus: true,1597 appProtectEnabled: false,1598 internalRoutesEnabled: false,1599 expectedErrors: []string{1600 `annotations.nginx.com/sticky-cookie-services: Invalid value: "not_a_rewrite": must be a semicolon-separated list of sticky services`,1601 },1602 msg: "invalid nginx.com/sticky-cookie-services annotation",1603 },1604 }1605 for _, test := range tests {1606 t.Run(test.msg, func(t *testing.T) {1607 allErrs := validateIngressAnnotations(1608 test.annotations,1609 test.specServices,1610 test.isPlus,1611 test.appProtectEnabled,1612 test.internalRoutesEnabled,1613 field.NewPath("annotations"),1614 )1615 assertion := assertErrors("validateIngressAnnotations()", test.msg, allErrs, test.expectedErrors)1616 if assertion != "" {1617 t.Error(assertion)1618 }1619 })1620 }1621}1622func TestValidateIngressSpec(t *testing.T) {1623 tests := []struct {1624 spec *networking.IngressSpec1625 expectedErrors []string1626 msg string1627 }{1628 {1629 spec: &networking.IngressSpec{1630 Rules: []networking.IngressRule{1631 {1632 Host: "foo.example.com",1633 IngressRuleValue: networking.IngressRuleValue{1634 HTTP: &networking.HTTPIngressRuleValue{1635 Paths: []networking.HTTPIngressPath{1636 {1637 Path: "/",1638 Backend: networking.IngressBackend{1639 Service: &networking.IngressServiceBackend{},1640 },1641 },1642 },1643 },1644 },1645 },1646 },1647 },1648 expectedErrors: nil,1649 msg: "valid input",1650 },1651 {1652 spec: &networking.IngressSpec{1653 DefaultBackend: &networking.IngressBackend{1654 Service: &networking.IngressServiceBackend{},1655 },1656 Rules: []networking.IngressRule{1657 {1658 Host: "foo.example.com",1659 },1660 },1661 },1662 expectedErrors: nil,1663 msg: "valid input with default backend",1664 },1665 {1666 spec: &networking.IngressSpec{1667 Rules: []networking.IngressRule{},1668 },1669 expectedErrors: []string{1670 "spec.rules: Required value",1671 },1672 msg: "zero rules",1673 },1674 {1675 spec: &networking.IngressSpec{1676 Rules: []networking.IngressRule{1677 {1678 Host: "",1679 },1680 },1681 },1682 expectedErrors: []string{1683 "spec.rules[0].host: Required value",1684 },1685 msg: "empty host",1686 },1687 {1688 spec: &networking.IngressSpec{1689 Rules: []networking.IngressRule{1690 {1691 Host: "foo.example.com",1692 },1693 {1694 Host: "foo.example.com",1695 },1696 },1697 },1698 expectedErrors: []string{1699 `spec.rules[1].host: Duplicate value: "foo.example.com"`,1700 },1701 msg: "duplicated host",1702 },1703 {1704 spec: &networking.IngressSpec{1705 DefaultBackend: &networking.IngressBackend{1706 Resource: &v1.TypedLocalObjectReference{},1707 },1708 Rules: []networking.IngressRule{1709 {1710 Host: "foo.example.com",1711 },1712 },1713 },1714 expectedErrors: []string{1715 "spec.defaultBackend.resource: Forbidden: resource backends are not supported",1716 },1717 msg: "invalid default backend",1718 },1719 {1720 spec: &networking.IngressSpec{1721 Rules: []networking.IngressRule{1722 {1723 Host: "foo.example.com",1724 IngressRuleValue: networking.IngressRuleValue{1725 HTTP: &networking.HTTPIngressRuleValue{1726 Paths: []networking.HTTPIngressPath{1727 {1728 Path: "/",1729 Backend: networking.IngressBackend{1730 Resource: &v1.TypedLocalObjectReference{},1731 },1732 },1733 },1734 },1735 },1736 },1737 },1738 },1739 expectedErrors: []string{1740 "spec.rules[0].http.path[0].backend.resource: Forbidden: resource backends are not supported",1741 },1742 msg: "invalid backend",1743 },1744 }1745 for _, test := range tests {1746 allErrs := validateIngressSpec(test.spec, field.NewPath("spec"))1747 assertion := assertErrors("validateIngressSpec()", test.msg, allErrs, test.expectedErrors)1748 if assertion != "" {1749 t.Error(assertion)1750 }1751 }1752}1753func TestValidateMasterSpec(t *testing.T) {1754 tests := []struct {1755 spec *networking.IngressSpec1756 expectedErrors []string1757 msg string1758 }{1759 {1760 spec: &networking.IngressSpec{1761 Rules: []networking.IngressRule{1762 {1763 Host: "foo.example.com",1764 IngressRuleValue: networking.IngressRuleValue{1765 HTTP: &networking.HTTPIngressRuleValue{1766 Paths: []networking.HTTPIngressPath{},1767 },1768 },1769 },1770 },1771 },1772 expectedErrors: nil,1773 msg: "valid input",1774 },1775 {1776 spec: &networking.IngressSpec{1777 Rules: []networking.IngressRule{1778 {1779 Host: "foo.example.com",1780 },1781 {1782 Host: "bar.example.com",1783 },1784 },1785 },1786 expectedErrors: []string{1787 "spec.rules: Too many: 2: must have at most 1 items",1788 },1789 msg: "too many hosts",1790 },1791 {1792 spec: &networking.IngressSpec{1793 Rules: []networking.IngressRule{1794 {1795 Host: "foo.example.com",1796 IngressRuleValue: networking.IngressRuleValue{1797 HTTP: &networking.HTTPIngressRuleValue{1798 Paths: []networking.HTTPIngressPath{1799 {1800 Path: "/",1801 },1802 },1803 },1804 },1805 },1806 },1807 },1808 expectedErrors: []string{1809 "spec.rules[0].http.paths: Too many: 1: must have at most 0 items",1810 },1811 msg: "too many paths",1812 },1813 }1814 for _, test := range tests {1815 allErrs := validateMasterSpec(test.spec, field.NewPath("spec"))1816 assertion := assertErrors("validateMasterSpec()", test.msg, allErrs, test.expectedErrors)1817 if assertion != "" {1818 t.Error(assertion)1819 }1820 }1821}1822func TestValidateMinionSpec(t *testing.T) {1823 tests := []struct {1824 spec *networking.IngressSpec1825 expectedErrors []string1826 msg string1827 }{1828 {1829 spec: &networking.IngressSpec{1830 Rules: []networking.IngressRule{1831 {1832 Host: "foo.example.com",1833 IngressRuleValue: networking.IngressRuleValue{1834 HTTP: &networking.HTTPIngressRuleValue{1835 Paths: []networking.HTTPIngressPath{1836 {1837 Path: "/",1838 },1839 },1840 },1841 },1842 },1843 },1844 },1845 expectedErrors: nil,1846 msg: "valid input",1847 },1848 {1849 spec: &networking.IngressSpec{1850 Rules: []networking.IngressRule{1851 {1852 Host: "foo.example.com",1853 },1854 {1855 Host: "bar.example.com",1856 },1857 },1858 },1859 expectedErrors: []string{1860 "spec.rules: Too many: 2: must have at most 1 items",1861 },1862 msg: "too many hosts",1863 },1864 {1865 spec: &networking.IngressSpec{1866 Rules: []networking.IngressRule{1867 {1868 Host: "foo.example.com",1869 IngressRuleValue: networking.IngressRuleValue{1870 HTTP: &networking.HTTPIngressRuleValue{1871 Paths: []networking.HTTPIngressPath{},1872 },1873 },1874 },1875 },1876 },1877 expectedErrors: []string{1878 "spec.rules[0].http.paths: Required value: must include at least one path",1879 },1880 msg: "too few paths",1881 },1882 {1883 spec: &networking.IngressSpec{1884 TLS: []networking.IngressTLS{1885 {1886 Hosts: []string{"foo.example.com"},1887 },1888 },1889 Rules: []networking.IngressRule{1890 {1891 Host: "foo.example.com",1892 IngressRuleValue: networking.IngressRuleValue{1893 HTTP: &networking.HTTPIngressRuleValue{1894 Paths: []networking.HTTPIngressPath{1895 {1896 Path: "/",1897 },1898 },1899 },1900 },1901 },1902 },1903 },1904 expectedErrors: []string{1905 "spec.tls: Too many: 1: must have at most 0 items",1906 },1907 msg: "tls is forbidden",1908 },1909 }1910 for _, test := range tests {1911 allErrs := validateMinionSpec(test.spec, field.NewPath("spec"))1912 assertion := assertErrors("validateMinionSpec()", test.msg, allErrs, test.expectedErrors)1913 if assertion != "" {1914 t.Error(assertion)1915 }1916 }1917}1918func assertErrors(funcName string, msg string, allErrs field.ErrorList, expectedErrors []string) string {1919 errors := errorListToStrings(allErrs)1920 if !reflect.DeepEqual(errors, expectedErrors) {1921 result := strings.Join(errors, "\n")1922 expected := strings.Join(expectedErrors, "\n")1923 return fmt.Sprintf("%s returned \n%s \nbut expected \n%s \nfor the case of %s", funcName, result, expected, msg)1924 }1925 return ""1926}1927func errorListToStrings(list field.ErrorList) []string {1928 var result []string1929 for _, e := range list {1930 result = append(result, e.Error())1931 }1932 return result1933}1934func TestGetSpecServices(t *testing.T) {1935 tests := []struct {1936 spec networking.IngressSpec1937 expected map[string]bool1938 msg string1939 }{1940 {1941 spec: networking.IngressSpec{1942 DefaultBackend: &networking.IngressBackend{1943 Service: &networking.IngressServiceBackend{1944 Name: "svc1",1945 },1946 },1947 Rules: []networking.IngressRule{1948 {1949 IngressRuleValue: networking.IngressRuleValue{1950 HTTP: &networking.HTTPIngressRuleValue{1951 Paths: []networking.HTTPIngressPath{1952 {1953 Path: "/",1954 Backend: networking.IngressBackend{1955 Service: &networking.IngressServiceBackend{1956 Name: "svc2",1957 },1958 },1959 },1960 },1961 },1962 },1963 },1964 },1965 },1966 expected: map[string]bool{1967 "svc1": true,1968 "svc2": true,1969 },1970 msg: "services are referenced",1971 },1972 {1973 spec: networking.IngressSpec{1974 DefaultBackend: &networking.IngressBackend{},1975 Rules: []networking.IngressRule{1976 {1977 IngressRuleValue: networking.IngressRuleValue{1978 HTTP: &networking.HTTPIngressRuleValue{1979 Paths: []networking.HTTPIngressPath{1980 {1981 Path: "/",1982 Backend: networking.IngressBackend{},1983 },1984 },1985 },1986 },1987 },1988 },1989 },1990 expected: map[string]bool{},1991 msg: "services are not referenced",1992 },1993 }1994 for _, test := range tests {1995 result := getSpecServices(test.spec)1996 if !reflect.DeepEqual(result, test.expected) {1997 t.Errorf("getSpecServices() returned %v but expected %v for the case of %s", result, test.expected, test.msg)1998 }1999 }2000}...
fmt_test.go
Source:fmt_test.go
...69func TestFormats(t *testing.T) {70 testenv.MustHaveGoBuild(t) // more restrictive than necessary, but that's ok71 // process all directories72 filepath.Walk(".", func(path string, info os.FileInfo, err error) error {73 if info.IsDir() {74 if info.Name() == "testdata" {75 return filepath.SkipDir76 }77 importPath := filepath.Join("cmd/compile", path)78 if blacklistedPackages[filepath.ToSlash(importPath)] {79 return filepath.SkipDir80 }81 pkg, err := build.Import(importPath, path, 0)82 if err != nil {83 if _, ok := err.(*build.NoGoError); ok {84 return nil // nothing to do here85 }86 t.Fatal(err)87 }88 collectPkgFormats(t, pkg)89 }90 return nil91 })92 // test and rewrite formats93 updatedFiles := make(map[string]File) // files that were rewritten94 for _, p := range callSites {95 // test current format literal and determine updated one96 out := formatReplace(p.str, func(index int, in string) string {97 if in == "*" {98 return in // cannot rewrite '*' (as in "%*d")99 }100 // in != '*'101 typ := p.types[index]102 format := typ + " " + in // e.g., "*Node %n"103 // check if format is known104 out, known := knownFormats[format]105 // record format if not yet found106 _, found := foundFormats[format]107 if !found {108 foundFormats[format] = true109 }110 // report an error if the format is unknown and this is the first111 // time we see it; ignore "%v" and "%T" which are always valid112 if !known && !found && in != "%v" && in != "%T" {113 t.Errorf("%s: unknown format %q for %s argument", posString(p.arg), in, typ)114 }115 if out == "" {116 out = in117 }118 return out119 })120 // replace existing format literal if it changed121 if out != p.str {122 // we cannot replace the argument if it's not a string literal for now123 // (e.g., it may be "foo" + "bar")124 lit, ok := p.arg.(*ast.BasicLit)125 if !ok {126 delete(callSites, p.call) // treat as if we hadn't found this site127 continue128 }129 if testing.Verbose() {130 fmt.Printf("%s:\n\t- %q\n\t+ %q\n", posString(p.arg), p.str, out)131 }132 // find argument index of format argument133 index := -1134 for i, arg := range p.call.Args {135 if p.arg == arg {136 index = i137 break138 }139 }140 if index < 0 {141 // we may have processed the same call site twice,142 // but that shouldn't happen143 panic("internal error: matching argument not found")144 }145 // replace literal146 new := *lit // make a copy147 new.Value = strconv.Quote(out) // this may introduce "-quotes where there were `-quotes148 p.call.Args[index] = &new149 updatedFiles[p.file.name] = p.file150 }151 }152 // write dirty files back153 var filesUpdated bool154 if len(updatedFiles) > 0 && *update {155 for _, file := range updatedFiles {156 var buf bytes.Buffer157 if err := format.Node(&buf, fset, file.ast); err != nil {158 t.Errorf("WARNING: formatting %s failed: %v", file.name, err)159 continue160 }161 if err := ioutil.WriteFile(file.name, buf.Bytes(), 0x666); err != nil {162 t.Errorf("WARNING: writing %s failed: %v", file.name, err)163 continue164 }165 fmt.Printf("updated %s\n", file.name)166 filesUpdated = true167 }168 }169 // report all function names containing a format string170 if len(callSites) > 0 && testing.Verbose() {171 set := make(map[string]bool)172 for _, p := range callSites {173 set[nodeString(p.call.Fun)] = true174 }175 var list []string176 for s := range set {177 list = append(list, s)178 }179 fmt.Println("\nFunctions")180 printList(list)181 }182 // report all formats found183 if len(foundFormats) > 0 && testing.Verbose() {184 var list []string185 for s := range foundFormats {186 list = append(list, fmt.Sprintf("%q: \"\",", s))187 }188 fmt.Println("\nvar knownFormats = map[string]string{")189 printList(list)190 fmt.Println("}")191 }192 // check that knownFormats is up to date193 if !testing.Verbose() && !*update {194 var mismatch bool195 for s := range foundFormats {196 if _, ok := knownFormats[s]; !ok {197 mismatch = true198 break199 }200 }201 if !mismatch {202 for s := range knownFormats {203 if _, ok := foundFormats[s]; !ok {204 mismatch = true205 break206 }207 }208 }209 if mismatch {210 t.Errorf("knownFormats is out of date; please run with -v to regenerate")211 }212 }213 // all format strings of calls must be in the formatStrings set (self-verification)214 for _, p := range callSites {215 if lit, ok := p.arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {216 if formatStrings[lit] {217 // ok218 delete(formatStrings, lit)219 } else {220 // this should never happen221 panic(fmt.Sprintf("internal error: format string not found (%s)", posString(lit)))222 }223 }224 }225 // if we have any strings left, we may need to update them manually226 if len(formatStrings) > 0 && filesUpdated {227 var list []string228 for lit := range formatStrings {229 list = append(list, fmt.Sprintf("%s: %s", posString(lit), nodeString(lit)))230 }231 fmt.Println("\nWARNING: Potentially missed format strings")232 printList(list)233 t.Fail()234 }235 fmt.Println()236}237// A callSite describes a function call that appears to contain238// a format string.239type callSite struct {240 file File241 call *ast.CallExpr // call containing the format string242 arg ast.Expr // format argument (string literal or constant)243 str string // unquoted format string244 types []string // argument types245}246func collectPkgFormats(t *testing.T, pkg *build.Package) {247 // collect all files248 var filenames []string249 filenames = append(filenames, pkg.GoFiles...)250 filenames = append(filenames, pkg.CgoFiles...)251 filenames = append(filenames, pkg.TestGoFiles...)252 // TODO(gri) verify _test files outside package253 for _, name := range pkg.XTestGoFiles {254 // don't process this test itself255 if name != "fmt_test.go" && testing.Verbose() {256 fmt.Printf("WARNING: %s not processed\n", filepath.Join(pkg.Dir, name))257 }258 }259 // make filenames relative to .260 for i, name := range filenames {261 filenames[i] = filepath.Join(pkg.Dir, name)262 }263 // parse all files264 files := make([]*ast.File, len(filenames))265 for i, filename := range filenames {266 f, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)267 if err != nil {268 t.Fatal(err)269 }270 files[i] = f271 }272 // typecheck package273 conf := types.Config{Importer: importer.Default()}274 etypes := make(map[ast.Expr]types.TypeAndValue)275 if _, err := conf.Check(pkg.ImportPath, fset, files, &types.Info{Types: etypes}); err != nil {276 t.Fatal(err)277 }278 // collect all potential format strings (for extra verification later)279 for _, file := range files {280 ast.Inspect(file, func(n ast.Node) bool {281 if s, ok := stringLit(n); ok && isFormat(s) {282 formatStrings[n.(*ast.BasicLit)] = true283 }284 return true285 })286 }287 // collect all formats/arguments of calls with format strings288 for index, file := range files {289 ast.Inspect(file, func(n ast.Node) bool {290 if call, ok := n.(*ast.CallExpr); ok {291 // ignore blacklisted functions292 if blacklistedFunctions[nodeString(call.Fun)] {293 return true294 }295 // look for an arguments that might be a format string296 for i, arg := range call.Args {297 if s, ok := stringVal(etypes[arg]); ok && isFormat(s) {298 // make sure we have enough arguments299 n := numFormatArgs(s)300 if i+1+n > len(call.Args) {301 t.Errorf("%s: not enough format args (blacklist %s?)", posString(call), nodeString(call.Fun))302 break // ignore this call303 }304 // assume last n arguments are to be formatted;305 // determine their types306 argTypes := make([]string, n)307 for i, arg := range call.Args[len(call.Args)-n:] {308 if tv, ok := etypes[arg]; ok {309 argTypes[i] = typeString(tv.Type)310 }311 }312 // collect call site313 if callSites[call] != nil {314 panic("internal error: file processed twice?")315 }316 callSites[call] = &callSite{317 file: File{filenames[index], file},318 call: call,319 arg: arg,320 str: s,321 types: argTypes,322 }323 break // at most one format per argument list324 }325 }326 }327 return true328 })329 }330}331// printList prints list in sorted order.332func printList(list []string) {333 sort.Strings(list)334 for _, s := range list {335 fmt.Println("\t", s)336 }337}338// posString returns a string representation of n's position339// in the form filename:line:col: .340func posString(n ast.Node) string {341 if n == nil {342 return ""343 }344 return fset.Position(n.Pos()).String()345}346// nodeString returns a string representation of n.347func nodeString(n ast.Node) string {348 var buf bytes.Buffer349 if err := format.Node(&buf, fset, n); err != nil {350 log.Fatal(err) // should always succeed351 }352 return buf.String()353}354// typeString returns a string representation of n.355func typeString(typ types.Type) string {356 return filepath.ToSlash(typ.String())357}358// stringLit returns the unquoted string value and true if359// n represents a string literal; otherwise it returns ""360// and false.361func stringLit(n ast.Node) (string, bool) {362 if lit, ok := n.(*ast.BasicLit); ok && lit.Kind == token.STRING {363 s, err := strconv.Unquote(lit.Value)364 if err != nil {365 log.Fatal(err) // should not happen with correct ASTs366 }367 return s, true368 }369 return "", false370}371// stringVal returns the (unquoted) string value and true if372// tv is a string constant; otherwise it returns "" and false.373func stringVal(tv types.TypeAndValue) (string, bool) {374 if tv.IsValue() && tv.Value != nil && tv.Value.Kind() == constant.String {375 return constant.StringVal(tv.Value), true376 }377 return "", false378}379// formatIter iterates through the string s in increasing380// index order and calls f for each format specifier '%..v'.381// The arguments for f describe the specifier's index range.382// If a format specifier contains a "*", f is called with383// the index range for "*" alone, before being called for384// the entire specifier. The result of f is the index of385// the rune at which iteration continues.386func formatIter(s string, f func(i, j int) int) {387 i := 0 // index after current rune388 var r rune // current rune...
errors.go
Source:errors.go
...129 case 'q':130 fmt.Fprintf(s, "%q", e.Error())131 }132}133// IsCode is a helper to determine if the error is of a specific code134func IsCode(code string, err error) bool {135 if argoErr, ok := err.(argoerr); ok {136 return argoErr.code == code137 }138 return false139}...
Is
Using AI Code Generation
1import (2func main() {3 fmt.Println(internal.Is(1))4}5import (6func main() {7 fmt.Println(internal.Is(1))8}9import (10func main() {11 fmt.Println(internal.Is(1))12}13import (14func main() {15 fmt.Println(internal.Is(1))16}17import (18func main() {19 fmt.Println(internal.Is(1))20}21import (22func main() {23 fmt.Println(internal.Is(1))24}25import (
Is
Using AI Code Generation
1import "fmt"2func main() {3 var i interface{} = 14 if _, ok := i.(internal); ok {5 fmt.Println("i is internal")6 } else {7 fmt.Println("i is not internal")8 }9}10import "fmt"11func main() {12 var i interface{} = 113 if _, ok := i.(internal); ok {14 fmt.Println("i is internal")15 } else {16 fmt.Println("i is not internal")17 }18}19import "fmt"20func main() {21 var i interface{} = 122 if _, ok := i.(internal); ok {23 fmt.Println("i is internal")24 } else {25 fmt.Println("i is not internal")26 }27}28import "fmt"29func main() {30 var i interface{} = 131 if _, ok := i.(internal); ok {32 fmt.Println("i is internal")33 } else {34 fmt.Println("i is not internal")35 }36}37import "fmt"38func main() {39 var i interface{} = 140 if _, ok := i.(internal); ok {41 fmt.Println("i is internal")42 } else {43 fmt.Println("i is not internal")44 }45}46import "fmt"47func main() {48 var i interface{} = 149 if _, ok := i.(internal); ok {50 fmt.Println("i is internal")51 } else {52 fmt.Println("i is not internal")53 }54}55import "fmt"56func main() {57 var i interface{} = 158 if _, ok := i.(internal); ok {59 fmt.Println("i is internal")60 } else {61 fmt.Println("i is not internal")62 }63}
Is
Using AI Code Generation
1import (2func main() {3 fmt.Println(internal.Is(1))4}5import (6func main() {7 fmt.Println(internal.Is(2))8}9import (10func main() {11 fmt.Println(internal.Is(3))12}
Is
Using AI Code Generation
1import (2func main() {3 fmt.Println(reflect.ValueOf(a).Is(reflect.ValueOf(b)))4}5import (6func main() {7 fmt.Println(reflect.ValueOf(a).Is(reflect.ValueOf(b)))8}9import (10func main() {11 fmt.Println(reflect.ValueOf(a).IsNil())12}13import (14func main() {15 fmt.Println(reflect.ValueOf(a).IsNil())16}17import (18func main() {19 fmt.Println(reflect.ValueOf(a).IsValid())20}
Is
Using AI Code Generation
1import (2func main() {3 fmt.Println(internal.Is())4}5func Is() bool {6}7func Is() bool {8}9func Is() bool {10}
Is
Using AI Code Generation
1import (2func main() {3 if _1.Is(1) {4 fmt.Println("1 is 1")5 }6}
Is
Using AI Code Generation
1import (2func main() {3 if _2.Is(a, b, c) {4 fmt.Println("a, b, c are in geometric progression")5 } else {6 fmt.Println("a, b, c are not in geometric progression")7 }8}9func Is(a, b, c int) bool {10}
Is
Using AI Code Generation
1func main() {2 var a = A{1}3 var b = A{1}4}5func main() {6 var a = A{1}7 var b = A{1}8}9func main() {10 var a = A{1}11 var b = A{1}12}13./3.go:7: a.Is undefined (type A has no field or method Is)14./3.go:8: a.Is undefined (type A has no field or method Is)15I am trying to figure out how to use the go tool to list only the packages that are used by a specific package. For example, if I have a package called foo/bar/baz , how would I use the go tool to list all of the packages that are imported by this package?16I have a package that I want to use in another package, but I want to use the package as if it were a subpackage of the other package. For example, if I have a package called foo/bar/baz , how would I use the go tool to import this package as if it were foo/bar/baz/qux ?17I am trying to figure out how to use the go tool to list only the packages that are used by a specific package. For example, if I have a package called foo/bar/baz , how would I use the go tool to list all of the packages that are imported by this package?18I have a package that I want to use in another package, but I want to use the package as if it were a subpackage of the other package. For example, if I have a package called foo/bar/baz , how would I use the go tool to import this package as if it were foo
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!