Best Mock code snippet using source.One
max_attachable_volume_predicate_test.go
Source:max_attachable_volume_predicate_test.go
1/*2Copyright 2018 The Kubernetes Authors.3Licensed under the Apache License, Version 2.0 (the "License");4you may not use this file except in compliance with the License.5You may obtain a copy of the License at6 http://www.apache.org/licenses/LICENSE-2.07Unless required by applicable law or agreed to in writing, software8distributed under the License is distributed on an "AS IS" BASIS,9WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.10See the License for the specific language governing permissions and11limitations under the License.12*/13package predicates14import (15 "os"16 "reflect"17 "strconv"18 "strings"19 "testing"20 v1 "k8s.io/api/core/v1"21 "k8s.io/api/storage/v1beta1"22 "k8s.io/apimachinery/pkg/api/resource"23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"24 utilfeature "k8s.io/apiserver/pkg/util/feature"25 featuregatetesting "k8s.io/component-base/featuregate/testing"26 csilibplugins "k8s.io/csi-translation-lib/plugins"27 "k8s.io/kubernetes/pkg/features"28 schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"29 volumeutil "k8s.io/kubernetes/pkg/volume/util"30 utilpointer "k8s.io/utils/pointer"31)32func onePVCPod(filterName string) *v1.Pod {33 return &v1.Pod{34 Spec: v1.PodSpec{35 Volumes: []v1.Volume{36 {37 VolumeSource: v1.VolumeSource{38 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{39 ClaimName: "some" + filterName + "Vol",40 },41 },42 },43 },44 },45 }46}47func splitPVCPod(filterName string) *v1.Pod {48 return &v1.Pod{49 Spec: v1.PodSpec{50 Volumes: []v1.Volume{51 {52 VolumeSource: v1.VolumeSource{53 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{54 ClaimName: "someNon" + filterName + "Vol",55 },56 },57 },58 {59 VolumeSource: v1.VolumeSource{60 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{61 ClaimName: "some" + filterName + "Vol",62 },63 },64 },65 },66 },67 }68}69func TestVolumeCountConflicts(t *testing.T) {70 oneVolPod := &v1.Pod{71 Spec: v1.PodSpec{72 Volumes: []v1.Volume{73 {74 VolumeSource: v1.VolumeSource{75 AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ovp"},76 },77 },78 },79 },80 }81 twoVolPod := &v1.Pod{82 Spec: v1.PodSpec{83 Volumes: []v1.Volume{84 {85 VolumeSource: v1.VolumeSource{86 AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp1"},87 },88 },89 {90 VolumeSource: v1.VolumeSource{91 AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp2"},92 },93 },94 },95 },96 }97 unboundPVCwithInvalidSCPod := &v1.Pod{98 Spec: v1.PodSpec{99 Volumes: []v1.Volume{100 {101 VolumeSource: v1.VolumeSource{102 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{103 ClaimName: "unboundPVCwithInvalidSCPod",104 },105 },106 },107 },108 },109 }110 unboundPVCwithDefaultSCPod := &v1.Pod{111 Spec: v1.PodSpec{112 Volumes: []v1.Volume{113 {114 VolumeSource: v1.VolumeSource{115 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{116 ClaimName: "unboundPVCwithDefaultSCPod",117 },118 },119 },120 },121 },122 }123 splitVolsPod := &v1.Pod{124 Spec: v1.PodSpec{125 Volumes: []v1.Volume{126 {127 VolumeSource: v1.VolumeSource{128 HostPath: &v1.HostPathVolumeSource{},129 },130 },131 {132 VolumeSource: v1.VolumeSource{133 AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "svp"},134 },135 },136 },137 },138 }139 nonApplicablePod := &v1.Pod{140 Spec: v1.PodSpec{141 Volumes: []v1.Volume{142 {143 VolumeSource: v1.VolumeSource{144 HostPath: &v1.HostPathVolumeSource{},145 },146 },147 },148 },149 }150 deletedPVCPod := &v1.Pod{151 Spec: v1.PodSpec{152 Volumes: []v1.Volume{153 {154 VolumeSource: v1.VolumeSource{155 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{156 ClaimName: "deletedPVC",157 },158 },159 },160 },161 },162 }163 twoDeletedPVCPod := &v1.Pod{164 Spec: v1.PodSpec{165 Volumes: []v1.Volume{166 {167 VolumeSource: v1.VolumeSource{168 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{169 ClaimName: "deletedPVC",170 },171 },172 },173 {174 VolumeSource: v1.VolumeSource{175 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{176 ClaimName: "anotherDeletedPVC",177 },178 },179 },180 },181 },182 }183 deletedPVPod := &v1.Pod{184 Spec: v1.PodSpec{185 Volumes: []v1.Volume{186 {187 VolumeSource: v1.VolumeSource{188 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{189 ClaimName: "pvcWithDeletedPV",190 },191 },192 },193 },194 },195 }196 // deletedPVPod2 is a different pod than deletedPVPod but using the same PVC197 deletedPVPod2 := &v1.Pod{198 Spec: v1.PodSpec{199 Volumes: []v1.Volume{200 {201 VolumeSource: v1.VolumeSource{202 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{203 ClaimName: "pvcWithDeletedPV",204 },205 },206 },207 },208 },209 }210 // anotherDeletedPVPod is a different pod than deletedPVPod and uses another PVC211 anotherDeletedPVPod := &v1.Pod{212 Spec: v1.PodSpec{213 Volumes: []v1.Volume{214 {215 VolumeSource: v1.VolumeSource{216 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{217 ClaimName: "anotherPVCWithDeletedPV",218 },219 },220 },221 },222 },223 }224 emptyPod := &v1.Pod{225 Spec: v1.PodSpec{},226 }227 unboundPVCPod := &v1.Pod{228 Spec: v1.PodSpec{229 Volumes: []v1.Volume{230 {231 VolumeSource: v1.VolumeSource{232 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{233 ClaimName: "unboundPVC",234 },235 },236 },237 },238 },239 }240 // Different pod than unboundPVCPod, but using the same unbound PVC241 unboundPVCPod2 := &v1.Pod{242 Spec: v1.PodSpec{243 Volumes: []v1.Volume{244 {245 VolumeSource: v1.VolumeSource{246 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{247 ClaimName: "unboundPVC",248 },249 },250 },251 },252 },253 }254 // pod with unbound PVC that's different to unboundPVC255 anotherUnboundPVCPod := &v1.Pod{256 Spec: v1.PodSpec{257 Volumes: []v1.Volume{258 {259 VolumeSource: v1.VolumeSource{260 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{261 ClaimName: "anotherUnboundPVC",262 },263 },264 },265 },266 },267 }268 twoVolCinderPod := &v1.Pod{269 Spec: v1.PodSpec{270 Volumes: []v1.Volume{271 {272 VolumeSource: v1.VolumeSource{273 Cinder: &v1.CinderVolumeSource{VolumeID: "tvp1"},274 },275 },276 {277 VolumeSource: v1.VolumeSource{278 Cinder: &v1.CinderVolumeSource{VolumeID: "tvp2"},279 },280 },281 },282 },283 }284 oneVolCinderPod := &v1.Pod{285 Spec: v1.PodSpec{286 Volumes: []v1.Volume{287 {288 VolumeSource: v1.VolumeSource{289 Cinder: &v1.CinderVolumeSource{VolumeID: "ovp"},290 },291 },292 },293 },294 }295 tests := []struct {296 newPod *v1.Pod297 existingPods []*v1.Pod298 filterName string299 maxVols int300 fits bool301 test string302 }{303 // filterName:EBSVolumeFilterType304 {305 newPod: oneVolPod,306 existingPods: []*v1.Pod{twoVolPod, oneVolPod},307 filterName: EBSVolumeFilterType,308 maxVols: 4,309 fits: true,310 test: "fits when node capacity >= new pod's EBS volumes",311 },312 {313 newPod: twoVolPod,314 existingPods: []*v1.Pod{oneVolPod},315 filterName: EBSVolumeFilterType,316 maxVols: 2,317 fits: false,318 test: "doesn't fit when node capacity < new pod's EBS volumes",319 },320 {321 newPod: splitVolsPod,322 existingPods: []*v1.Pod{twoVolPod},323 filterName: EBSVolumeFilterType,324 maxVols: 3,325 fits: true,326 test: "new pod's count ignores non-EBS volumes",327 },328 {329 newPod: twoVolPod,330 existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod},331 filterName: EBSVolumeFilterType,332 maxVols: 3,333 fits: true,334 test: "existing pods' counts ignore non-EBS volumes",335 },336 {337 newPod: onePVCPod(EBSVolumeFilterType),338 existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod},339 filterName: EBSVolumeFilterType,340 maxVols: 3,341 fits: true,342 test: "new pod's count considers PVCs backed by EBS volumes",343 },344 {345 newPod: splitPVCPod(EBSVolumeFilterType),346 existingPods: []*v1.Pod{splitVolsPod, oneVolPod},347 filterName: EBSVolumeFilterType,348 maxVols: 3,349 fits: true,350 test: "new pod's count ignores PVCs not backed by EBS volumes",351 },352 {353 newPod: twoVolPod,354 existingPods: []*v1.Pod{oneVolPod, onePVCPod(EBSVolumeFilterType)},355 filterName: EBSVolumeFilterType,356 maxVols: 3,357 fits: false,358 test: "existing pods' counts considers PVCs backed by EBS volumes",359 },360 {361 newPod: twoVolPod,362 existingPods: []*v1.Pod{oneVolPod, twoVolPod, onePVCPod(EBSVolumeFilterType)},363 filterName: EBSVolumeFilterType,364 maxVols: 4,365 fits: true,366 test: "already-mounted EBS volumes are always ok to allow",367 },368 {369 newPod: splitVolsPod,370 existingPods: []*v1.Pod{oneVolPod, oneVolPod, onePVCPod(EBSVolumeFilterType)},371 filterName: EBSVolumeFilterType,372 maxVols: 3,373 fits: true,374 test: "the same EBS volumes are not counted multiple times",375 },376 {377 newPod: onePVCPod(EBSVolumeFilterType),378 existingPods: []*v1.Pod{oneVolPod, deletedPVCPod},379 filterName: EBSVolumeFilterType,380 maxVols: 1,381 fits: false,382 test: "missing PVC is not counted towards the PV limit",383 },384 {385 newPod: onePVCPod(EBSVolumeFilterType),386 existingPods: []*v1.Pod{oneVolPod, deletedPVCPod},387 filterName: EBSVolumeFilterType,388 maxVols: 2,389 fits: true,390 test: "missing PVC is not counted towards the PV limit",391 },392 {393 newPod: onePVCPod(EBSVolumeFilterType),394 existingPods: []*v1.Pod{oneVolPod, twoDeletedPVCPod},395 filterName: EBSVolumeFilterType,396 maxVols: 2,397 fits: true,398 test: "two missing PVCs are not counted towards the PV limit twice",399 },400 {401 newPod: unboundPVCwithInvalidSCPod,402 existingPods: []*v1.Pod{oneVolPod},403 filterName: EBSVolumeFilterType,404 maxVols: 1,405 fits: true,406 test: "unbound PVC with invalid SC is not counted towards the PV limit",407 },408 {409 newPod: unboundPVCwithDefaultSCPod,410 existingPods: []*v1.Pod{oneVolPod},411 filterName: EBSVolumeFilterType,412 maxVols: 1,413 fits: true,414 test: "unbound PVC from different provisioner is not counted towards the PV limit",415 },416 {417 newPod: onePVCPod(EBSVolumeFilterType),418 existingPods: []*v1.Pod{oneVolPod, deletedPVPod},419 filterName: EBSVolumeFilterType,420 maxVols: 2,421 fits: false,422 test: "pod with missing PV is counted towards the PV limit",423 },424 {425 newPod: onePVCPod(EBSVolumeFilterType),426 existingPods: []*v1.Pod{oneVolPod, deletedPVPod},427 filterName: EBSVolumeFilterType,428 maxVols: 3,429 fits: true,430 test: "pod with missing PV is counted towards the PV limit",431 },432 {433 newPod: deletedPVPod2,434 existingPods: []*v1.Pod{oneVolPod, deletedPVPod},435 filterName: EBSVolumeFilterType,436 maxVols: 2,437 fits: true,438 test: "two pods missing the same PV are counted towards the PV limit only once",439 },440 {441 newPod: anotherDeletedPVPod,442 existingPods: []*v1.Pod{oneVolPod, deletedPVPod},443 filterName: EBSVolumeFilterType,444 maxVols: 2,445 fits: false,446 test: "two pods missing different PVs are counted towards the PV limit twice",447 },448 {449 newPod: onePVCPod(EBSVolumeFilterType),450 existingPods: []*v1.Pod{oneVolPod, unboundPVCPod},451 filterName: EBSVolumeFilterType,452 maxVols: 2,453 fits: false,454 test: "pod with unbound PVC is counted towards the PV limit",455 },456 {457 newPod: onePVCPod(EBSVolumeFilterType),458 existingPods: []*v1.Pod{oneVolPod, unboundPVCPod},459 filterName: EBSVolumeFilterType,460 maxVols: 3,461 fits: true,462 test: "pod with unbound PVC is counted towards the PV limit",463 },464 {465 newPod: unboundPVCPod2,466 existingPods: []*v1.Pod{oneVolPod, unboundPVCPod},467 filterName: EBSVolumeFilterType,468 maxVols: 2,469 fits: true,470 test: "the same unbound PVC in multiple pods is counted towards the PV limit only once",471 },472 {473 newPod: anotherUnboundPVCPod,474 existingPods: []*v1.Pod{oneVolPod, unboundPVCPod},475 filterName: EBSVolumeFilterType,476 maxVols: 2,477 fits: false,478 test: "two different unbound PVCs are counted towards the PV limit as two volumes",479 },480 // filterName:GCEPDVolumeFilterType481 {482 newPod: oneVolPod,483 existingPods: []*v1.Pod{twoVolPod, oneVolPod},484 filterName: GCEPDVolumeFilterType,485 maxVols: 4,486 fits: true,487 test: "fits when node capacity >= new pod's GCE volumes",488 },489 {490 newPod: twoVolPod,491 existingPods: []*v1.Pod{oneVolPod},492 filterName: GCEPDVolumeFilterType,493 maxVols: 2,494 fits: true,495 test: "fit when node capacity < new pod's GCE volumes",496 },497 {498 newPod: splitVolsPod,499 existingPods: []*v1.Pod{twoVolPod},500 filterName: GCEPDVolumeFilterType,501 maxVols: 3,502 fits: true,503 test: "new pod's count ignores non-GCE volumes",504 },505 {506 newPod: twoVolPod,507 existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod},508 filterName: GCEPDVolumeFilterType,509 maxVols: 3,510 fits: true,511 test: "existing pods' counts ignore non-GCE volumes",512 },513 {514 newPod: onePVCPod(GCEPDVolumeFilterType),515 existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod},516 filterName: GCEPDVolumeFilterType,517 maxVols: 3,518 fits: true,519 test: "new pod's count considers PVCs backed by GCE volumes",520 },521 {522 newPod: splitPVCPod(GCEPDVolumeFilterType),523 existingPods: []*v1.Pod{splitVolsPod, oneVolPod},524 filterName: GCEPDVolumeFilterType,525 maxVols: 3,526 fits: true,527 test: "new pod's count ignores PVCs not backed by GCE volumes",528 },529 {530 newPod: twoVolPod,531 existingPods: []*v1.Pod{oneVolPod, onePVCPod(GCEPDVolumeFilterType)},532 filterName: GCEPDVolumeFilterType,533 maxVols: 3,534 fits: true,535 test: "existing pods' counts considers PVCs backed by GCE volumes",536 },537 {538 newPod: twoVolPod,539 existingPods: []*v1.Pod{oneVolPod, twoVolPod, onePVCPod(GCEPDVolumeFilterType)},540 filterName: GCEPDVolumeFilterType,541 maxVols: 4,542 fits: true,543 test: "already-mounted EBS volumes are always ok to allow",544 },545 {546 newPod: splitVolsPod,547 existingPods: []*v1.Pod{oneVolPod, oneVolPod, onePVCPod(GCEPDVolumeFilterType)},548 filterName: GCEPDVolumeFilterType,549 maxVols: 3,550 fits: true,551 test: "the same GCE volumes are not counted multiple times",552 },553 {554 newPod: onePVCPod(GCEPDVolumeFilterType),555 existingPods: []*v1.Pod{oneVolPod, deletedPVCPod},556 filterName: GCEPDVolumeFilterType,557 maxVols: 2,558 fits: true,559 test: "pod with missing PVC is counted towards the PV limit",560 },561 {562 newPod: onePVCPod(GCEPDVolumeFilterType),563 existingPods: []*v1.Pod{oneVolPod, deletedPVCPod},564 filterName: GCEPDVolumeFilterType,565 maxVols: 3,566 fits: true,567 test: "pod with missing PVC is counted towards the PV limit",568 },569 {570 newPod: onePVCPod(GCEPDVolumeFilterType),571 existingPods: []*v1.Pod{oneVolPod, twoDeletedPVCPod},572 filterName: GCEPDVolumeFilterType,573 maxVols: 3,574 fits: true,575 test: "pod with missing two PVCs is counted towards the PV limit twice",576 },577 {578 newPod: onePVCPod(GCEPDVolumeFilterType),579 existingPods: []*v1.Pod{oneVolPod, deletedPVPod},580 filterName: GCEPDVolumeFilterType,581 maxVols: 2,582 fits: true,583 test: "pod with missing PV is counted towards the PV limit",584 },585 {586 newPod: onePVCPod(GCEPDVolumeFilterType),587 existingPods: []*v1.Pod{oneVolPod, deletedPVPod},588 filterName: GCEPDVolumeFilterType,589 maxVols: 3,590 fits: true,591 test: "pod with missing PV is counted towards the PV limit",592 },593 {594 newPod: deletedPVPod2,595 existingPods: []*v1.Pod{oneVolPod, deletedPVPod},596 filterName: GCEPDVolumeFilterType,597 maxVols: 2,598 fits: true,599 test: "two pods missing the same PV are counted towards the PV limit only once",600 },601 {602 newPod: anotherDeletedPVPod,603 existingPods: []*v1.Pod{oneVolPod, deletedPVPod},604 filterName: GCEPDVolumeFilterType,605 maxVols: 2,606 fits: true,607 test: "two pods missing different PVs are counted towards the PV limit twice",608 },609 {610 newPod: onePVCPod(GCEPDVolumeFilterType),611 existingPods: []*v1.Pod{oneVolPod, unboundPVCPod},612 filterName: GCEPDVolumeFilterType,613 maxVols: 2,614 fits: true,615 test: "pod with unbound PVC is counted towards the PV limit",616 },617 {618 newPod: onePVCPod(GCEPDVolumeFilterType),619 existingPods: []*v1.Pod{oneVolPod, unboundPVCPod},620 filterName: GCEPDVolumeFilterType,621 maxVols: 3,622 fits: true,623 test: "pod with unbound PVC is counted towards the PV limit",624 },625 {626 newPod: unboundPVCPod2,627 existingPods: []*v1.Pod{oneVolPod, unboundPVCPod},628 filterName: GCEPDVolumeFilterType,629 maxVols: 2,630 fits: true,631 test: "the same unbound PVC in multiple pods is counted towards the PV limit only once",632 },633 {634 newPod: anotherUnboundPVCPod,635 existingPods: []*v1.Pod{oneVolPod, unboundPVCPod},636 filterName: GCEPDVolumeFilterType,637 maxVols: 2,638 fits: true,639 test: "two different unbound PVCs are counted towards the PV limit as two volumes",640 },641 // filterName:AzureDiskVolumeFilterType642 {643 newPod: oneVolPod,644 existingPods: []*v1.Pod{twoVolPod, oneVolPod},645 filterName: AzureDiskVolumeFilterType,646 maxVols: 4,647 fits: true,648 test: "fits when node capacity >= new pod's AzureDisk volumes",649 },650 {651 newPod: twoVolPod,652 existingPods: []*v1.Pod{oneVolPod},653 filterName: AzureDiskVolumeFilterType,654 maxVols: 2,655 fits: true,656 test: "fit when node capacity < new pod's AzureDisk volumes",657 },658 {659 newPod: splitVolsPod,660 existingPods: []*v1.Pod{twoVolPod},661 filterName: AzureDiskVolumeFilterType,662 maxVols: 3,663 fits: true,664 test: "new pod's count ignores non-AzureDisk volumes",665 },666 {667 newPod: twoVolPod,668 existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod},669 filterName: AzureDiskVolumeFilterType,670 maxVols: 3,671 fits: true,672 test: "existing pods' counts ignore non-AzureDisk volumes",673 },674 {675 newPod: onePVCPod(AzureDiskVolumeFilterType),676 existingPods: []*v1.Pod{splitVolsPod, nonApplicablePod, emptyPod},677 filterName: AzureDiskVolumeFilterType,678 maxVols: 3,679 fits: true,680 test: "new pod's count considers PVCs backed by AzureDisk volumes",681 },682 {683 newPod: splitPVCPod(AzureDiskVolumeFilterType),684 existingPods: []*v1.Pod{splitVolsPod, oneVolPod},685 filterName: AzureDiskVolumeFilterType,686 maxVols: 3,687 fits: true,688 test: "new pod's count ignores PVCs not backed by AzureDisk volumes",689 },690 {691 newPod: twoVolPod,692 existingPods: []*v1.Pod{oneVolPod, onePVCPod(AzureDiskVolumeFilterType)},693 filterName: AzureDiskVolumeFilterType,694 maxVols: 3,695 fits: true,696 test: "existing pods' counts considers PVCs backed by AzureDisk volumes",697 },698 {699 newPod: twoVolPod,700 existingPods: []*v1.Pod{oneVolPod, twoVolPod, onePVCPod(AzureDiskVolumeFilterType)},701 filterName: AzureDiskVolumeFilterType,702 maxVols: 4,703 fits: true,704 test: "already-mounted AzureDisk volumes are always ok to allow",705 },706 {707 newPod: splitVolsPod,708 existingPods: []*v1.Pod{oneVolPod, oneVolPod, onePVCPod(AzureDiskVolumeFilterType)},709 filterName: AzureDiskVolumeFilterType,710 maxVols: 3,711 fits: true,712 test: "the same AzureDisk volumes are not counted multiple times",713 },714 {715 newPod: onePVCPod(AzureDiskVolumeFilterType),716 existingPods: []*v1.Pod{oneVolPod, deletedPVCPod},717 filterName: AzureDiskVolumeFilterType,718 maxVols: 2,719 fits: true,720 test: "pod with missing PVC is counted towards the PV limit",721 },722 {723 newPod: onePVCPod(AzureDiskVolumeFilterType),724 existingPods: []*v1.Pod{oneVolPod, deletedPVCPod},725 filterName: AzureDiskVolumeFilterType,726 maxVols: 3,727 fits: true,728 test: "pod with missing PVC is counted towards the PV limit",729 },730 {731 newPod: onePVCPod(AzureDiskVolumeFilterType),732 existingPods: []*v1.Pod{oneVolPod, twoDeletedPVCPod},733 filterName: AzureDiskVolumeFilterType,734 maxVols: 3,735 fits: true,736 test: "pod with missing two PVCs is counted towards the PV limit twice",737 },738 {739 newPod: onePVCPod(AzureDiskVolumeFilterType),740 existingPods: []*v1.Pod{oneVolPod, deletedPVPod},741 filterName: AzureDiskVolumeFilterType,742 maxVols: 2,743 fits: true,744 test: "pod with missing PV is counted towards the PV limit",745 },746 {747 newPod: onePVCPod(AzureDiskVolumeFilterType),748 existingPods: []*v1.Pod{oneVolPod, deletedPVPod},749 filterName: AzureDiskVolumeFilterType,750 maxVols: 3,751 fits: true,752 test: "pod with missing PV is counted towards the PV limit",753 },754 {755 newPod: deletedPVPod2,756 existingPods: []*v1.Pod{oneVolPod, deletedPVPod},757 filterName: AzureDiskVolumeFilterType,758 maxVols: 2,759 fits: true,760 test: "two pods missing the same PV are counted towards the PV limit only once",761 },762 {763 newPod: anotherDeletedPVPod,764 existingPods: []*v1.Pod{oneVolPod, deletedPVPod},765 filterName: AzureDiskVolumeFilterType,766 maxVols: 2,767 fits: true,768 test: "two pods missing different PVs are counted towards the PV limit twice",769 },770 {771 newPod: onePVCPod(AzureDiskVolumeFilterType),772 existingPods: []*v1.Pod{oneVolPod, unboundPVCPod},773 filterName: AzureDiskVolumeFilterType,774 maxVols: 2,775 fits: true,776 test: "pod with unbound PVC is counted towards the PV limit",777 },778 {779 newPod: onePVCPod(AzureDiskVolumeFilterType),780 existingPods: []*v1.Pod{oneVolPod, unboundPVCPod},781 filterName: AzureDiskVolumeFilterType,782 maxVols: 3,783 fits: true,784 test: "pod with unbound PVC is counted towards the PV limit",785 },786 {787 newPod: unboundPVCPod2,788 existingPods: []*v1.Pod{oneVolPod, unboundPVCPod},789 filterName: AzureDiskVolumeFilterType,790 maxVols: 2,791 fits: true,792 test: "the same unbound PVC in multiple pods is counted towards the PV limit only once",793 },794 {795 newPod: anotherUnboundPVCPod,796 existingPods: []*v1.Pod{oneVolPod, unboundPVCPod},797 filterName: AzureDiskVolumeFilterType,798 maxVols: 2,799 fits: true,800 test: "two different unbound PVCs are counted towards the PV limit as two volumes",801 },802 // filterName:CinderVolumeFilterType803 {804 newPod: oneVolCinderPod,805 existingPods: []*v1.Pod{twoVolCinderPod},806 filterName: CinderVolumeFilterType,807 maxVols: 4,808 fits: true,809 test: "fits when node capacity >= new pod's Cinder volumes",810 },811 {812 newPod: oneVolCinderPod,813 existingPods: []*v1.Pod{twoVolCinderPod},814 filterName: CinderVolumeFilterType,815 maxVols: 2,816 fits: false,817 test: "not fit when node capacity < new pod's Cinder volumes",818 },819 }820 expectedFailureReasons := []PredicateFailureReason{ErrMaxVolumeCountExceeded}821 // running attachable predicate tests without feature gate and no limit present on nodes822 for _, test := range tests {823 os.Setenv(KubeMaxPDVols, strconv.Itoa(test.maxVols))824 node, csiNode := getNodeWithPodAndVolumeLimits("node", test.existingPods, int64(test.maxVols), test.filterName)825 pred := NewMaxPDVolumeCountPredicate(test.filterName,826 getFakeCSINodeInfo(csiNode),827 getFakeStorageClassInfo(test.filterName),828 getFakePVInfo(test.filterName),829 getFakePVCInfo(test.filterName))830 fits, reasons, err := pred(test.newPod, GetPredicateMetadata(test.newPod, nil), node)831 if err != nil {832 t.Errorf("[%s]%s: unexpected error: %v", test.filterName, test.test, err)833 }834 if !fits && !reflect.DeepEqual(reasons, expectedFailureReasons) {835 t.Errorf("[%s]%s: unexpected failure reasons: %v, want: %v", test.filterName, test.test, reasons, expectedFailureReasons)836 }837 if fits != test.fits {838 t.Errorf("[%s]%s: expected %v, got %v", test.filterName, test.test, test.fits, fits)839 }840 }841 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AttachVolumeLimit, true)()842 // running attachable predicate tests with feature gate and limit present on nodes843 for _, test := range tests {844 node, csiNode := getNodeWithPodAndVolumeLimits("node", test.existingPods, int64(test.maxVols), test.filterName)845 pred := NewMaxPDVolumeCountPredicate(test.filterName,846 getFakeCSINodeInfo(csiNode),847 getFakeStorageClassInfo(test.filterName),848 getFakePVInfo(test.filterName),849 getFakePVCInfo(test.filterName))850 fits, reasons, err := pred(test.newPod, GetPredicateMetadata(test.newPod, nil), node)851 if err != nil {852 t.Errorf("Using allocatable [%s]%s: unexpected error: %v", test.filterName, test.test, err)853 }854 if !fits && !reflect.DeepEqual(reasons, expectedFailureReasons) {855 t.Errorf("Using allocatable [%s]%s: unexpected failure reasons: %v, want: %v", test.filterName, test.test, reasons, expectedFailureReasons)856 }857 if fits != test.fits {858 t.Errorf("Using allocatable [%s]%s: expected %v, got %v", test.filterName, test.test, test.fits, fits)859 }860 }861}862func getFakeStorageClassInfo(sc string) FakeStorageClassInfo {863 var provisioner string864 switch sc {865 case EBSVolumeFilterType:866 provisioner = csilibplugins.AWSEBSInTreePluginName867 case GCEPDVolumeFilterType:868 provisioner = csilibplugins.GCEPDInTreePluginName869 case AzureDiskVolumeFilterType:870 provisioner = csilibplugins.AzureDiskInTreePluginName871 case CinderVolumeFilterType:872 provisioner = csilibplugins.CinderInTreePluginName873 default:874 return FakeStorageClassInfo{}875 }876 return FakeStorageClassInfo{877 {878 ObjectMeta: metav1.ObjectMeta{Name: sc},879 Provisioner: provisioner,880 },881 {882 ObjectMeta: metav1.ObjectMeta{Name: "standard-sc"},883 Provisioner: "standard-sc",884 },885 }886}887func getFakePVInfo(filterName string) FakePersistentVolumeInfo {888 return FakePersistentVolumeInfo{889 {890 ObjectMeta: metav1.ObjectMeta{Name: "some" + filterName + "Vol"},891 Spec: v1.PersistentVolumeSpec{892 PersistentVolumeSource: v1.PersistentVolumeSource{893 AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: strings.ToLower(filterName) + "Vol"},894 },895 },896 },897 {898 ObjectMeta: metav1.ObjectMeta{Name: "someNon" + filterName + "Vol"},899 Spec: v1.PersistentVolumeSpec{900 PersistentVolumeSource: v1.PersistentVolumeSource{},901 },902 },903 }904}905func getFakePVCInfo(filterName string) FakePersistentVolumeClaimInfo {906 return FakePersistentVolumeClaimInfo{907 {908 ObjectMeta: metav1.ObjectMeta{Name: "some" + filterName + "Vol"},909 Spec: v1.PersistentVolumeClaimSpec{910 VolumeName: "some" + filterName + "Vol",911 StorageClassName: &filterName,912 },913 },914 {915 ObjectMeta: metav1.ObjectMeta{Name: "someNon" + filterName + "Vol"},916 Spec: v1.PersistentVolumeClaimSpec{917 VolumeName: "someNon" + filterName + "Vol",918 StorageClassName: &filterName,919 },920 },921 {922 ObjectMeta: metav1.ObjectMeta{Name: "pvcWithDeletedPV"},923 Spec: v1.PersistentVolumeClaimSpec{924 VolumeName: "pvcWithDeletedPV",925 StorageClassName: &filterName,926 },927 },928 {929 ObjectMeta: metav1.ObjectMeta{Name: "anotherPVCWithDeletedPV"},930 Spec: v1.PersistentVolumeClaimSpec{931 VolumeName: "anotherPVCWithDeletedPV",932 StorageClassName: &filterName,933 },934 },935 {936 ObjectMeta: metav1.ObjectMeta{Name: "unboundPVC"},937 Spec: v1.PersistentVolumeClaimSpec{938 VolumeName: "",939 StorageClassName: &filterName,940 },941 },942 {943 ObjectMeta: metav1.ObjectMeta{Name: "anotherUnboundPVC"},944 Spec: v1.PersistentVolumeClaimSpec{945 VolumeName: "",946 StorageClassName: &filterName,947 },948 },949 {950 ObjectMeta: metav1.ObjectMeta{Name: "unboundPVCwithDefaultSCPod"},951 Spec: v1.PersistentVolumeClaimSpec{952 VolumeName: "",953 StorageClassName: utilpointer.StringPtr("standard-sc"),954 },955 },956 {957 ObjectMeta: metav1.ObjectMeta{Name: "unboundPVCwithInvalidSCPod"},958 Spec: v1.PersistentVolumeClaimSpec{959 VolumeName: "",960 StorageClassName: utilpointer.StringPtr("invalid-sc"),961 },962 },963 }964}965func TestMaxVolumeFuncM5(t *testing.T) {966 node := &v1.Node{967 ObjectMeta: metav1.ObjectMeta{968 Name: "node-for-m5-instance",969 Labels: map[string]string{970 v1.LabelInstanceType: "m5.large",971 },972 },973 }974 os.Unsetenv(KubeMaxPDVols)975 maxVolumeFunc := getMaxVolumeFunc(EBSVolumeFilterType)976 maxVolume := maxVolumeFunc(node)977 if maxVolume != volumeutil.DefaultMaxEBSNitroVolumeLimit {978 t.Errorf("Expected max volume to be %d got %d", volumeutil.DefaultMaxEBSNitroVolumeLimit, maxVolume)979 }980}981func TestMaxVolumeFuncT3(t *testing.T) {982 node := &v1.Node{983 ObjectMeta: metav1.ObjectMeta{984 Name: "node-for-t3-instance",985 Labels: map[string]string{986 v1.LabelInstanceType: "t3.medium",987 },988 },989 }990 os.Unsetenv(KubeMaxPDVols)991 maxVolumeFunc := getMaxVolumeFunc(EBSVolumeFilterType)992 maxVolume := maxVolumeFunc(node)993 if maxVolume != volumeutil.DefaultMaxEBSNitroVolumeLimit {994 t.Errorf("Expected max volume to be %d got %d", volumeutil.DefaultMaxEBSNitroVolumeLimit, maxVolume)995 }996}997func TestMaxVolumeFuncR5(t *testing.T) {998 node := &v1.Node{999 ObjectMeta: metav1.ObjectMeta{1000 Name: "node-for-r5-instance",1001 Labels: map[string]string{1002 v1.LabelInstanceType: "r5d.xlarge",1003 },1004 },1005 }1006 os.Unsetenv(KubeMaxPDVols)1007 maxVolumeFunc := getMaxVolumeFunc(EBSVolumeFilterType)1008 maxVolume := maxVolumeFunc(node)1009 if maxVolume != volumeutil.DefaultMaxEBSNitroVolumeLimit {1010 t.Errorf("Expected max volume to be %d got %d", volumeutil.DefaultMaxEBSNitroVolumeLimit, maxVolume)1011 }1012}1013func TestMaxVolumeFuncM4(t *testing.T) {1014 node := &v1.Node{1015 ObjectMeta: metav1.ObjectMeta{1016 Name: "node-for-m4-instance",1017 Labels: map[string]string{1018 v1.LabelInstanceType: "m4.2xlarge",1019 },1020 },1021 }1022 os.Unsetenv(KubeMaxPDVols)1023 maxVolumeFunc := getMaxVolumeFunc(EBSVolumeFilterType)1024 maxVolume := maxVolumeFunc(node)1025 if maxVolume != volumeutil.DefaultMaxEBSVolumes {1026 t.Errorf("Expected max volume to be %d got %d", volumeutil.DefaultMaxEBSVolumes, maxVolume)1027 }1028}1029func getNodeWithPodAndVolumeLimits(limitSource string, pods []*v1.Pod, limit int64, driverNames ...string) (*schedulernodeinfo.NodeInfo, *v1beta1.CSINode) {1030 nodeInfo := schedulernodeinfo.NewNodeInfo(pods...)1031 node := &v1.Node{1032 ObjectMeta: metav1.ObjectMeta{Name: "node-for-max-pd-test-1"},1033 Status: v1.NodeStatus{1034 Allocatable: v1.ResourceList{},1035 },1036 }1037 var csiNode *v1beta1.CSINode1038 addLimitToNode := func() {1039 for _, driver := range driverNames {1040 node.Status.Allocatable[getVolumeLimitKey(driver)] = *resource.NewQuantity(limit, resource.DecimalSI)1041 }1042 }1043 initCSINode := func() {1044 csiNode = &v1beta1.CSINode{1045 ObjectMeta: metav1.ObjectMeta{Name: "csi-node-for-max-pd-test-1"},1046 Spec: v1beta1.CSINodeSpec{1047 Drivers: []v1beta1.CSINodeDriver{},1048 },1049 }1050 }1051 addDriversCSINode := func(addLimits bool) {1052 initCSINode()1053 for _, driver := range driverNames {1054 driver := v1beta1.CSINodeDriver{1055 Name: driver,1056 NodeID: "node-for-max-pd-test-1",1057 }1058 if addLimits {1059 driver.Allocatable = &v1beta1.VolumeNodeResources{1060 Count: utilpointer.Int32Ptr(int32(limit)),1061 }1062 }1063 csiNode.Spec.Drivers = append(csiNode.Spec.Drivers, driver)1064 }1065 }1066 switch limitSource {1067 case "node":1068 addLimitToNode()1069 case "csinode":1070 addDriversCSINode(true)1071 case "both":1072 addLimitToNode()1073 addDriversCSINode(true)1074 case "csinode-with-no-limit":1075 addDriversCSINode(false)1076 case "no-csi-driver":1077 initCSINode()1078 default:1079 // Do nothing.1080 }1081 nodeInfo.SetNode(node)1082 return nodeInfo, csiNode1083}1084func getVolumeLimitKey(filterType string) v1.ResourceName {1085 switch filterType {1086 case EBSVolumeFilterType:1087 return v1.ResourceName(volumeutil.EBSVolumeLimitKey)1088 case GCEPDVolumeFilterType:1089 return v1.ResourceName(volumeutil.GCEVolumeLimitKey)1090 case AzureDiskVolumeFilterType:1091 return v1.ResourceName(volumeutil.AzureVolumeLimitKey)1092 case CinderVolumeFilterType:1093 return v1.ResourceName(volumeutil.CinderVolumeLimitKey)1094 default:1095 return v1.ResourceName(volumeutil.GetCSIAttachLimitKey(filterType))1096 }1097}...
mutate_test.go
Source:mutate_test.go
...18 "sigs.k8s.io/controller-runtime/pkg/webhook/admission"19)20const (21 namespace = "test"22 bindingNameOne = "binding-test-one"23 bindingNameTwo = "binding-test-two"24 bindingNameThree = "binding-test-three"25 secretNameOne = "secret-test-one"26 secretNameTwo = "secret-test-two"27 configMapName = "config-map-test"28 secretEnvOneKey = "PASSWORD"29 secretEnvTwoKey = "TOKEN"30 configMapEnvKey = "CONFIG"31)32func TestMutationHandler_Handle(t *testing.T) {33 // given34 sch, err := v1alpha1.SchemeBuilder.Build()35 require.NoError(t, err)36 err = scheme.AddToScheme(sch)37 require.NoError(t, err)38 request := admission.Request{39 AdmissionRequest: v1beta1.AdmissionRequest{40 UID: "1234-abcd",41 Operation: v1beta1.Create,42 Name: "test-pod",43 Namespace: namespace,44 Kind: metav1.GroupVersionKind{45 Kind: "Pod",46 Version: "v1",47 Group: "",48 },49 Object: runtime.RawExtension{Raw: rawPod()},50 },51 }52 fakeClient := fake.NewFakeClientWithScheme(sch, fixBindingOne(), fixBindingTwo(), fixBindingThree(), fixSecretOne(), fixSecretTwo(), fixConfigMap())53 decoder, err := admission.NewDecoder(scheme.Scheme)54 require.NoError(t, err)55 handler := NewMutationHandler(webhook.NewClient(fakeClient), logrus.New())56 err = handler.InjectDecoder(decoder)57 require.NoError(t, err)58 // when59 response := handler.Handle(context.TODO(), request)60 // then61 assert.True(t, response.Allowed)62 // filtering out status cause k8s api-server will discard this too63 patches := filterOutStatusPatch(response.Patches)64 assert.Len(t, patches, 2)65 for _, patch := range patches {66 assert.Equal(t, "add", patch.Operation)67 assert.Contains(t, []string{"/spec/containers/0/env", "/spec/containers/1/env"}, patch.Path)68 assert.Len(t, patch.Value, 3)69 assert.ElementsMatch(t, patch.Value, []interface{}{70 map[string]interface{}{71 "name": secretEnvOneKey,72 "valueFrom": map[string]interface{}{73 "secretKeyRef": map[string]interface{}{74 "key": secretEnvOneKey,75 "name": secretNameOne,76 },77 },78 },79 map[string]interface{}{80 "name": secretEnvTwoKey,81 "valueFrom": map[string]interface{}{82 "secretKeyRef": map[string]interface{}{83 "key": secretEnvTwoKey,84 "name": secretNameTwo,85 },86 },87 },88 map[string]interface{}{89 "name": configMapEnvKey,90 "valueFrom": map[string]interface{}{91 "configMapKeyRef": map[string]interface{}{92 "key": configMapEnvKey,93 "name": configMapName,94 },95 },96 },97 })98 }99}100func fixBindingOne() *v1alpha1.Binding {101 return &v1alpha1.Binding{102 ObjectMeta: metav1.ObjectMeta{103 Name: bindingNameOne,104 Namespace: namespace,105 },106 Spec: v1alpha1.BindingSpec{107 Source: v1alpha1.Source{108 Kind: v1alpha1.SourceKindSecret,109 Name: secretNameOne,110 },111 },112 Status: v1alpha1.BindingStatus{113 Phase: v1alpha1.BindingReady,114 Message: "la loza lorem ipsum dolores sit onface",115 Source: fmt.Sprintf("%s/%s", v1alpha1.SourceKindSecret, secretNameOne),116 },117 }118}119func fixBindingTwo() *v1alpha1.Binding {120 return &v1alpha1.Binding{121 ObjectMeta: metav1.ObjectMeta{122 Name: bindingNameTwo,123 Namespace: namespace,124 },125 Spec: v1alpha1.BindingSpec{126 Source: v1alpha1.Source{127 Kind: v1alpha1.SourceKindSecret,128 Name: secretNameTwo,129 },130 },131 Status: v1alpha1.BindingStatus{132 Phase: v1alpha1.BindingReady,133 Message: "lorem ipsum dolor sit amet",134 Source: fmt.Sprintf("%s/%s", v1alpha1.SourceKindSecret, secretNameTwo),135 },136 }137}138func fixBindingThree() *v1alpha1.Binding {139 return &v1alpha1.Binding{140 ObjectMeta: metav1.ObjectMeta{141 Name: bindingNameThree,142 Namespace: namespace,143 },144 Spec: v1alpha1.BindingSpec{145 Source: v1alpha1.Source{146 Kind: v1alpha1.SourceKindConfigMap,147 Name: configMapName,148 },149 },150 Status: v1alpha1.BindingStatus{151 Phase: v1alpha1.BindingReady,152 Message: "consectetur adipiscing elit, sed do eiusmod tempor incididunt",153 Source: fmt.Sprintf("%s/%s", v1alpha1.SourceKindConfigMap, configMapName),154 },155 }156}157func fixSecretOne() *corev1.Secret {158 return &corev1.Secret{159 ObjectMeta: metav1.ObjectMeta{160 Name: secretNameOne,161 Namespace: namespace,162 },163 Data: map[string][]byte{164 secretEnvOneKey: []byte("superSecretPassword"),165 },166 }167}168func fixSecretTwo() *corev1.Secret {169 return &corev1.Secret{170 ObjectMeta: metav1.ObjectMeta{171 Name: secretNameTwo,172 Namespace: namespace,173 },174 Data: map[string][]byte{175 secretEnvTwoKey: []byte("superSecretToken"),176 },177 }178}179func fixConfigMap() *corev1.ConfigMap {180 return &corev1.ConfigMap{181 ObjectMeta: metav1.ObjectMeta{182 Name: configMapName,183 Namespace: namespace,184 },185 Data: map[string]string{186 configMapEnvKey: "configForPod",187 },188 }189}190func rawPod() []byte {191 return []byte(fmt.Sprintf(`{192 "apiVersion": "v1",193 "kind": "Pod",194 "metadata": {195 "creationTimestamp": null,196 "name": "test-pod",197 "labels": {198 "%s/%s": "1234",199 "%s/%s": "4567",200 "%s/%s": "9875"201 }202 },203 "spec": {204 "containers": [205 {206 "name": "test",207 "image": "test",208 "resources": {}209 },210 {211 "name": "test2",212 "image": "test2",213 "resources": {}214 }215 ]216 }217 }`, v1alpha1.BindingLabelKey, bindingNameOne, v1alpha1.BindingLabelKey, bindingNameTwo, v1alpha1.BindingLabelKey, bindingNameThree))218}219func filterOutStatusPatch(operations []jsonpatch.JsonPatchOperation) []jsonpatch.JsonPatchOperation {220 var filtered []jsonpatch.JsonPatchOperation221 for _, op := range operations {222 if op.Path != "/status" {223 filtered = append(filtered, op)224 }225 }226 return filtered227}...
render_test.go
Source:render_test.go
1package render2import (3 "bytes"4 "fmt"5 "strings"6 "testing"7 "github.com/mlctrez/mystace/context"8 "github.com/mlctrez/mystace/internal/mocks"9 "github.com/mlctrez/mystace/internal/spec"10 "github.com/mlctrez/mystace/internal/testify"11 "github.com/mlctrez/mystace/lexer"12 "github.com/mlctrez/mystace/source"13)14func TestNew(t *testing.T) {15 _, require := testify.New(t)16 r := New()17 require.NotNil(r)18 require.NotNil(r.(*render).sources)19}20func TestRender_AddSource(t *testing.T) {21 _, require := testify.New(t)22 src, err := source.FromString("one")23 require.Nil(err)24 require.NotNil(src)25 r := New()26 err = r.AddSource(src)27 require.ErrorIs(source.ErrEmptySourceName, err)28 src, err = source.FromString("one", source.WithName("one"))29 require.Nil(err)30 require.NotNil(src)31 require.Nil(r.AddSource(src))32 require.ErrorIs(r.AddSource(src), source.ErrDuplicateSourceName)33}34func TestRender_Writer(t *testing.T) {35 _, require := testify.New(t)36 r := New()37 writer := &bytes.Buffer{}38 r.Writer(writer)39 require.Equal(writer, r.(*render).writer)40}41func TestRender_Render(t *testing.T) {42 _, require := testify.New(t)43 r := New()44 err := r.Render("foo", context.New(nil))45 require.ErrorIs(err, ErrNoWriter)46 buf := &bytes.Buffer{}47 r.Writer(buf)48 err = r.Render("foo", context.New(nil))49 require.ErrorIs(err, ErrSourceNameNotFound)50 var src source.Source51 src, err = source.FromString("content", source.WithName("foo"))52 require.Nil(err)53 err = r.AddSource(src)54 require.Nil(err)55 err = r.Render("foo", context.New(nil))56 require.Nil(err)57 // testing bad token source58 src, err = source.FromString("{{", source.WithName("bad"))59 require.Nil(err)60 err = r.AddSource(src)61 require.Nil(err)62 err = r.Render("bad", context.New(nil))63 require.NotNil(err)64}65func Test_render(t *testing.T) {66 _, require := testify.New(t)67 buf := &bytes.Buffer{}68 r := render{writer: buf}69 tokens := []lexer.Token{{Data: source.Data{Str: "simple"}}}70 err := r.render(tokens, context.New(nil))71 require.Nil(err)72 require.Equal("simple", buf.String())73}74func Test_render_writerErr(t *testing.T) {75 _, require := testify.New(t)76 buf := &mocks.BadWriter{WriteErr: mocks.ErrBadWriterMockError}77 r := render{writer: buf}78 tokens := []lexer.Token{{Data: source.Data{Str: "simple"}}}79 err := r.render(tokens, context.New(nil))80 require.ErrorIs(err, mocks.ErrBadWriterMockError)81}82func TestRender_MustacheSpecs(t *testing.T) {83 _, require := testify.New(t)84 specFiles := []string{85 "../mustache/specs/comments.json",86 //"../mustache/specs/delimiters.json",87 "../mustache/specs/interpolation.json",88 //"../mustache/specs/inverted.json",89 //"../mustache/specs/partials.json",90 "../mustache/specs/sections.json",91 }92 for _, file := range specFiles {93 if !strings.HasSuffix(file, ".json") {94 continue95 }96 spec, err := spec.Read(file)97 require.Nil(err)98 for i, test := range spec.Tests {99 if test.Name != "Deeply Nested Contexts" {100 //continue101 }102 // since we normalize all line endings to \n, fix up spec tests \r\n -> \n103 test.Expected = strings.ReplaceAll(test.Expected, "\r", "")104 var src source.Source105 name := fmt.Sprintf("interpolation%d", i)106 src, err = source.FromString(test.Template, source.WithName(name))107 require.Nil(err)108 r := New()109 buf := &bytes.Buffer{}110 r.Writer(buf)111 err = r.AddSource(src)112 require.Nil(err)113 vars := make(map[string]interface{})114 if tryVars, ok := test.Data.(map[string]interface{}); ok {115 vars = tryVars116 } else {117 vars["."] = test.Data118 }119 err = r.Render(name, context.New(vars))120 message := fmt.Sprintf("specFile=%s testName=%s template=%q data=%v", file, test.Name, test.Template, test.Data)121 require.Nil(err, message)122 require.Equal(test.Expected, buf.String(), message)123 }124 }125}126func TestRender_modsAt(t *testing.T) {127 require := testify.Require(t)128 require.True(true)129 src, err := source.FromString(`some data{{!comment}}other data130more data131{{!comment}}132more more data133`)134 require.Nil(err)135 var tokens []lexer.Token136 tokens, err = lexer.New(src).Parse()137 require.Nil(err)138 // out of range should not blow up139 require.False(canRemoveWhitespace(tokens, 1, -1))140 require.False(canRemoveWhitespace(tokens, 1, 10))141 // comments on same line should not be treated as whitespace removal142 require.False(canRemoveWhitespace(tokens, 0, 1))143 require.False(canRemoveWhitespace(tokens, 2, 1))144 // comment on different line145 require.True(canRemoveWhitespace(tokens, 2, 3))146 require.True(canRemoveWhitespace(tokens, 4, 3))147 // comparison with non comments148 require.False(canRemoveWhitespace(tokens, 0, 0))149}150/*151{{#a}}152 {{one}}153 {{#b}}154 {{one}}{{two}}{{one}}155 {{#c}}156 {{one}}{{two}}{{three}}{{two}}{{one}}157 {{#d}}158 {{one}}{{two}}{{three}}{{four}}{{three}}{{two}}{{one}}159 {{#five}}160 {{one}}{{two}}{{three}}{{four}}{{five}}{{four}}{{three}}{{two}}{{one}}161 {{one}}{{two}}{{three}}{{four}}{{.}}6{{.}}{{four}}{{three}}{{two}}{{one}}162 {{one}}{{two}}{{three}}{{four}}{{five}}{{four}}{{three}}{{two}}{{one}}163 {{/five}}164 {{one}}{{two}}{{three}}{{four}}{{three}}{{two}}{{one}}165 {{/d}}166 {{one}}{{two}}{{three}}{{two}}{{one}}167 {{/c}}168 {{one}}{{two}}{{one}}169 {{/b}}170 {{one}}171{{/a}}172*/...
config_test.go
Source:config_test.go
...16 "testing"17)18func TestConfigurationChannels(t *testing.T) {19 mux := NewMux(nil)20 channelOne := mux.Channel("one")21 if channelOne != mux.Channel("one") {22 t.Error("Didn't get the same muxuration channel back with the same name")23 }24 channelTwo := mux.Channel("two")25 if channelOne == channelTwo {26 t.Error("Got back the same muxuration channel for different names")27 }28}29type MergeMock struct {30 source string31 update interface{}32 t *testing.T33}34func (m MergeMock) Merge(source string, update interface{}) error {35 if m.source != source {36 m.t.Errorf("Expected %s, Got %s", m.source, source)37 }38 if !reflect.DeepEqual(m.update, update) {39 m.t.Errorf("Expected %s, Got %s", m.update, update)...
One
Using AI Code Generation
1import "source"2func main() {3source.One()4}5import "source"6func main() {7source.Two()8}9import "source"10func main() {11source.Three()12}
One
Using AI Code Generation
1import "test/one"2func main() {3 one.One()4}5import "test/two"6func main() {7 two.Two()8}9import "test/three"10func main() {11 three.Three()12}13import "test/four"14func main() {15 four.Four()16}17import "test/five"18func main() {19 five.Five()20}21import "test/six"22func main() {23 six.Six()24}25import "test/seven"26func main() {27 seven.Seven()28}29import "test/eight"30func main() {31 eight.Eight()32}33import "test/nine"34func main() {35 nine.Nine()36}37import "test/ten"38func main() {39 ten.Ten()40}41import "test/eleven"42func main() {43 eleven.Eleven()44}45import "test/twelve"46func main() {47 twelve.Twelve()48}49import "test/thirteen"50func main() {51 thirteen.Thirteen()52}53import "test/fourteen"54func main() {55 fourteen.Fourteen()56}
One
Using AI Code Generation
1import "fmt"2import "./source"3func main() {4 fmt.Println(source.One())5}6func One() string {7}
One
Using AI Code Generation
1import (2func main() {3 source.One()4 fmt.Println("This is main package")5}6import (7func main() {8 One()9 fmt.Println("This is main package")10}11func One() {12 fmt.Println("This is main package")13}14import (15func main() {16 source.One()17 fmt.Println("This is main package")18}19import "sub-directory/package-name"20import (21func main() {22 source.One()23 fmt.Println("This is main package")24}
One
Using AI Code Generation
1import "fmt"2import "github.com/username/repositoryname/source"3func main(){4 fmt.Println(source.One())5}6import "fmt"7import "github.com/username/repositoryname/source"8func main(){9 fmt.Println(source.Two())10}
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!!