| // Copyright 2016 CNI authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package utils |
| |
| import ( |
| "fmt" |
| "strings" |
| |
| . "github.com/onsi/ginkgo/v2" |
| . "github.com/onsi/gomega" |
| ) |
| |
| var _ = Describe("Utils", func() { |
| Describe("FormatChainName", func() { |
| It("must format a short name", func() { |
| chain := FormatChainName("test", "1234") |
| Expect(chain).To(HaveLen(maxChainLength)) |
| Expect(chain).To(Equal("CNI-2bbe0c48b91a7d1b8a6753a8")) |
| }) |
| |
| It("must truncate a long name", func() { |
| chain := FormatChainName("testalongnamethatdoesnotmakesense", "1234") |
| Expect(chain).To(HaveLen(maxChainLength)) |
| Expect(chain).To(Equal("CNI-374f33fe84ab0ed84dcdebe3")) |
| }) |
| |
| It("must be predictable", func() { |
| chain1 := FormatChainName("testalongnamethatdoesnotmakesense", "1234") |
| chain2 := FormatChainName("testalongnamethatdoesnotmakesense", "1234") |
| Expect(chain1).To(HaveLen(maxChainLength)) |
| Expect(chain2).To(HaveLen(maxChainLength)) |
| Expect(chain1).To(Equal(chain2)) |
| }) |
| |
| It("must change when a character changes", func() { |
| chain1 := FormatChainName("testalongnamethatdoesnotmakesense", "1234") |
| chain2 := FormatChainName("testalongnamethatdoesnotmakesense", "1235") |
| Expect(chain1).To(HaveLen(maxChainLength)) |
| Expect(chain2).To(HaveLen(maxChainLength)) |
| Expect(chain1).To(Equal("CNI-374f33fe84ab0ed84dcdebe3")) |
| Expect(chain1).NotTo(Equal(chain2)) |
| }) |
| }) |
| |
| Describe("MustFormatChainNameWithPrefix", func() { |
| It("generates a chain name with a prefix", func() { |
| chain := MustFormatChainNameWithPrefix("test", "1234", "PREFIX-") |
| Expect(chain).To(HaveLen(maxChainLength)) |
| Expect(chain).To(Equal("CNI-PREFIX-2bbe0c48b91a7d1b8")) |
| }) |
| |
| It("must format a short name", func() { |
| chain := MustFormatChainNameWithPrefix("test", "1234", "PREFIX-") |
| Expect(chain).To(HaveLen(maxChainLength)) |
| Expect(chain).To(Equal("CNI-PREFIX-2bbe0c48b91a7d1b8")) |
| }) |
| |
| It("must truncate a long name", func() { |
| chain := MustFormatChainNameWithPrefix("testalongnamethatdoesnotmakesense", "1234", "PREFIX-") |
| Expect(chain).To(HaveLen(maxChainLength)) |
| Expect(chain).To(Equal("CNI-PREFIX-374f33fe84ab0ed84")) |
| }) |
| |
| It("must be predictable", func() { |
| chain1 := MustFormatChainNameWithPrefix("testalongnamethatdoesnotmakesense", "1234", "PREFIX-") |
| chain2 := MustFormatChainNameWithPrefix("testalongnamethatdoesnotmakesense", "1234", "PREFIX-") |
| Expect(chain1).To(HaveLen(maxChainLength)) |
| Expect(chain2).To(HaveLen(maxChainLength)) |
| Expect(chain1).To(Equal(chain2)) |
| }) |
| |
| It("must change when a character changes", func() { |
| chain1 := MustFormatChainNameWithPrefix("testalongnamethatdoesnotmakesense", "1234", "PREFIX-") |
| chain2 := MustFormatChainNameWithPrefix("testalongnamethatdoesnotmakesense", "1235", "PREFIX-") |
| Expect(chain1).To(HaveLen(maxChainLength)) |
| Expect(chain2).To(HaveLen(maxChainLength)) |
| Expect(chain1).To(Equal("CNI-PREFIX-374f33fe84ab0ed84")) |
| Expect(chain1).NotTo(Equal(chain2)) |
| }) |
| |
| It("panics when prefix is too large", func() { |
| longPrefix := strings.Repeat("PREFIX-", 4) |
| Expect(func() { |
| MustFormatChainNameWithPrefix("test", "1234", longPrefix) |
| }).To(Panic()) |
| }) |
| }) |
| |
| Describe("MustFormatHashWithPrefix", func() { |
| It("always returns a string with the given prefix", func() { |
| Expect(MustFormatHashWithPrefix(10, "AAA", "some string")).To(HavePrefix("AAA")) |
| Expect(MustFormatHashWithPrefix(10, "foo", "some string")).To(HavePrefix("foo")) |
| Expect(MustFormatHashWithPrefix(10, "bar", "some string")).To(HavePrefix("bar")) |
| }) |
| |
| It("always returns a string of the given length", func() { |
| Expect(MustFormatHashWithPrefix(10, "AAA", "some string")).To(HaveLen(10)) |
| Expect(MustFormatHashWithPrefix(15, "AAA", "some string")).To(HaveLen(15)) |
| Expect(MustFormatHashWithPrefix(5, "AAA", "some string")).To(HaveLen(5)) |
| }) |
| |
| It("is deterministic", func() { |
| val1 := MustFormatHashWithPrefix(10, "AAA", "some string") |
| val2 := MustFormatHashWithPrefix(10, "AAA", "some string") |
| val3 := MustFormatHashWithPrefix(10, "AAA", "some string") |
| Expect(val1).To(Equal(val2)) |
| Expect(val1).To(Equal(val3)) |
| }) |
| |
| It("is (nearly) perfect (injective function)", func() { |
| hashes := map[string]int{} |
| |
| for i := 0; i < 1000; i++ { |
| name := fmt.Sprintf("string %d", i) |
| hashes[MustFormatHashWithPrefix(8, "", name)]++ |
| } |
| |
| for key, count := range hashes { |
| Expect(count).To(Equal(1), "for key "+key+" got non-unique correspondence") |
| } |
| }) |
| |
| assertPanicWith := func(f func(), expectedErrorMessage string) { |
| defer func() { |
| Expect(recover()).To(Equal(expectedErrorMessage)) |
| }() |
| f() |
| Fail("function should have panicked but did not") |
| } |
| |
| It("panics when prefix is longer than the length", func() { |
| assertPanicWith( |
| func() { MustFormatHashWithPrefix(3, "AAA", "some string") }, |
| "invalid length", |
| ) |
| }) |
| |
| It("panics when length is not positive", func() { |
| assertPanicWith( |
| func() { MustFormatHashWithPrefix(0, "", "some string") }, |
| "invalid length", |
| ) |
| }) |
| |
| It("panics when length is larger than MaxLen", func() { |
| assertPanicWith( |
| func() { MustFormatHashWithPrefix(MaxHashLen+1, "", "some string") }, |
| "invalid length", |
| ) |
| }) |
| }) |
| }) |