k8s.io/kubernetes@v1.29.3/pkg/controller/deployment/util/hash_test.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package util 18 19 import ( 20 "encoding/json" 21 "hash/adler32" 22 "strconv" 23 "strings" 24 "testing" 25 26 v1 "k8s.io/api/core/v1" 27 "k8s.io/kubernetes/pkg/controller" 28 hashutil "k8s.io/kubernetes/pkg/util/hash" 29 ) 30 31 var podSpec = ` 32 { 33 "metadata": { 34 "creationTimestamp": null, 35 "labels": { 36 "app": "cats" 37 } 38 }, 39 "spec": { 40 "containers": [ 41 { 42 "name": "cats", 43 "image": "registry/test/cats:v0.@@VERSION@@.0", 44 "ports": [ 45 { 46 "name": "http", 47 "containerPort": 9077, 48 "protocol": "TCP" 49 } 50 ], 51 "env": [ 52 { 53 "name": "DEPLOYMENT_ENVIRONMENT", 54 "value": "cats-stubbed-functional" 55 }, 56 { 57 "name": "APP_NAME", 58 "value": "cats" 59 } 60 ], 61 "resources": { 62 "limits": { 63 "cpu": "1", 64 "memory": "1Gi" 65 }, 66 "requests": { 67 "cpu": "1", 68 "memory": "1Gi" 69 } 70 }, 71 "livenessProbe": { 72 "httpGet": { 73 "path": "/private/status", 74 "port": 9077, 75 "scheme": "HTTP" 76 }, 77 "initialDelaySeconds": 30, 78 "timeoutSeconds": 1, 79 "periodSeconds": 10, 80 "successThreshold": 1, 81 "failureThreshold": 3 82 }, 83 "readinessProbe": { 84 "httpGet": { 85 "path": "/private/status", 86 "port": 9077, 87 "scheme": "HTTP" 88 }, 89 "initialDelaySeconds": 1, 90 "timeoutSeconds": 1, 91 "periodSeconds": 10, 92 "successThreshold": 1, 93 "failureThreshold": 3 94 }, 95 "terminationMessagePath": "/dev/termination-log", 96 "imagePullPolicy": "IfNotPresent" 97 } 98 ], 99 "restartPolicy": "Always", 100 "terminationGracePeriodSeconds": 30, 101 "dnsPolicy": "ClusterFirst", 102 "securityContext": {} 103 } 104 } 105 ` 106 107 func TestPodTemplateSpecHash(t *testing.T) { 108 seenHashes := make(map[string]int) 109 110 for i := 0; i < 1000; i++ { 111 specJSON := strings.Replace(podSpec, "@@VERSION@@", strconv.Itoa(i), 1) 112 spec := v1.PodTemplateSpec{} 113 json.Unmarshal([]byte(specJSON), &spec) 114 hash := controller.ComputeHash(&spec, nil) 115 if v, ok := seenHashes[hash]; ok { 116 t.Errorf("Hash collision, old: %d new: %d", v, i) 117 break 118 } 119 seenHashes[hash] = i 120 } 121 } 122 123 func BenchmarkAdler(b *testing.B) { 124 spec := v1.PodTemplateSpec{} 125 json.Unmarshal([]byte(podSpec), &spec) 126 127 for i := 0; i < b.N; i++ { 128 getPodTemplateSpecOldHash(spec) 129 } 130 } 131 132 func getPodTemplateSpecOldHash(template v1.PodTemplateSpec) uint32 { 133 podTemplateSpecHasher := adler32.New() 134 hashutil.DeepHashObject(podTemplateSpecHasher, template) 135 return podTemplateSpecHasher.Sum32() 136 } 137 138 func BenchmarkFnv(b *testing.B) { 139 spec := v1.PodTemplateSpec{} 140 json.Unmarshal([]byte(podSpec), &spec) 141 142 for i := 0; i < b.N; i++ { 143 controller.ComputeHash(&spec, nil) 144 } 145 }