helpers_test.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package helper
  14. import (
  15. "reflect"
  16. "testing"
  17. "k8s.io/apimachinery/pkg/api/resource"
  18. "k8s.io/apimachinery/pkg/labels"
  19. "k8s.io/kubernetes/pkg/apis/core"
  20. )
  21. func TestSemantic(t *testing.T) {
  22. table := []struct {
  23. a, b interface{}
  24. shouldEqual bool
  25. }{
  26. {resource.MustParse("0"), resource.Quantity{}, true},
  27. {resource.Quantity{}, resource.MustParse("0"), true},
  28. {resource.Quantity{}, resource.MustParse("1m"), false},
  29. {
  30. resource.NewQuantity(5, resource.BinarySI),
  31. resource.NewQuantity(5, resource.DecimalSI),
  32. true,
  33. },
  34. {resource.MustParse("2m"), resource.MustParse("1m"), false},
  35. }
  36. for index, item := range table {
  37. if e, a := item.shouldEqual, Semantic.DeepEqual(item.a, item.b); e != a {
  38. t.Errorf("case[%d], expected %v, got %v.", index, e, a)
  39. }
  40. }
  41. }
  42. func TestIsStandardResource(t *testing.T) {
  43. testCases := []struct {
  44. input string
  45. output bool
  46. }{
  47. {"cpu", true},
  48. {"memory", true},
  49. {"disk", false},
  50. {"blah", false},
  51. {"x.y.z", false},
  52. {"hugepages-2Mi", true},
  53. {"requests.hugepages-2Mi", true},
  54. }
  55. for i, tc := range testCases {
  56. if IsStandardResourceName(tc.input) != tc.output {
  57. t.Errorf("case[%d], input: %s, expected: %t, got: %t", i, tc.input, tc.output, !tc.output)
  58. }
  59. }
  60. }
  61. func TestIsStandardContainerResource(t *testing.T) {
  62. testCases := []struct {
  63. input string
  64. output bool
  65. }{
  66. {"cpu", true},
  67. {"memory", true},
  68. {"disk", false},
  69. {"hugepages-2Mi", true},
  70. }
  71. for i, tc := range testCases {
  72. if IsStandardContainerResourceName(tc.input) != tc.output {
  73. t.Errorf("case[%d], input: %s, expected: %t, got: %t", i, tc.input, tc.output, !tc.output)
  74. }
  75. }
  76. }
  77. func TestGetAccessModesFromString(t *testing.T) {
  78. modes := GetAccessModesFromString("ROX")
  79. if !containsAccessMode(modes, core.ReadOnlyMany) {
  80. t.Errorf("Expected mode %s, but got %+v", core.ReadOnlyMany, modes)
  81. }
  82. modes = GetAccessModesFromString("ROX,RWX")
  83. if !containsAccessMode(modes, core.ReadOnlyMany) {
  84. t.Errorf("Expected mode %s, but got %+v", core.ReadOnlyMany, modes)
  85. }
  86. if !containsAccessMode(modes, core.ReadWriteMany) {
  87. t.Errorf("Expected mode %s, but got %+v", core.ReadWriteMany, modes)
  88. }
  89. modes = GetAccessModesFromString("RWO,ROX,RWX")
  90. if !containsAccessMode(modes, core.ReadOnlyMany) {
  91. t.Errorf("Expected mode %s, but got %+v", core.ReadOnlyMany, modes)
  92. }
  93. if !containsAccessMode(modes, core.ReadWriteMany) {
  94. t.Errorf("Expected mode %s, but got %+v", core.ReadWriteMany, modes)
  95. }
  96. }
  97. func TestRemoveDuplicateAccessModes(t *testing.T) {
  98. modes := []core.PersistentVolumeAccessMode{
  99. core.ReadWriteOnce, core.ReadOnlyMany, core.ReadOnlyMany, core.ReadOnlyMany,
  100. }
  101. modes = removeDuplicateAccessModes(modes)
  102. if len(modes) != 2 {
  103. t.Errorf("Expected 2 distinct modes in set but found %v", len(modes))
  104. }
  105. }
  106. func TestNodeSelectorRequirementsAsSelector(t *testing.T) {
  107. matchExpressions := []core.NodeSelectorRequirement{{
  108. Key: "foo",
  109. Operator: core.NodeSelectorOpIn,
  110. Values: []string{"bar", "baz"},
  111. }}
  112. mustParse := func(s string) labels.Selector {
  113. out, e := labels.Parse(s)
  114. if e != nil {
  115. panic(e)
  116. }
  117. return out
  118. }
  119. tc := []struct {
  120. in []core.NodeSelectorRequirement
  121. out labels.Selector
  122. expectErr bool
  123. }{
  124. {in: nil, out: labels.Nothing()},
  125. {in: []core.NodeSelectorRequirement{}, out: labels.Nothing()},
  126. {
  127. in: matchExpressions,
  128. out: mustParse("foo in (baz,bar)"),
  129. },
  130. {
  131. in: []core.NodeSelectorRequirement{{
  132. Key: "foo",
  133. Operator: core.NodeSelectorOpExists,
  134. Values: []string{"bar", "baz"},
  135. }},
  136. expectErr: true,
  137. },
  138. {
  139. in: []core.NodeSelectorRequirement{{
  140. Key: "foo",
  141. Operator: core.NodeSelectorOpGt,
  142. Values: []string{"1"},
  143. }},
  144. out: mustParse("foo>1"),
  145. },
  146. {
  147. in: []core.NodeSelectorRequirement{{
  148. Key: "bar",
  149. Operator: core.NodeSelectorOpLt,
  150. Values: []string{"7"},
  151. }},
  152. out: mustParse("bar<7"),
  153. },
  154. }
  155. for i, tc := range tc {
  156. out, err := NodeSelectorRequirementsAsSelector(tc.in)
  157. if err == nil && tc.expectErr {
  158. t.Errorf("[%v]expected error but got none.", i)
  159. }
  160. if err != nil && !tc.expectErr {
  161. t.Errorf("[%v]did not expect error but got: %v", i, err)
  162. }
  163. if !reflect.DeepEqual(out, tc.out) {
  164. t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out)
  165. }
  166. }
  167. }
  168. func TestIsHugePageResourceName(t *testing.T) {
  169. testCases := []struct {
  170. name core.ResourceName
  171. result bool
  172. }{
  173. {
  174. name: core.ResourceName("hugepages-2Mi"),
  175. result: true,
  176. },
  177. {
  178. name: core.ResourceName("hugepages-1Gi"),
  179. result: true,
  180. },
  181. {
  182. name: core.ResourceName("cpu"),
  183. result: false,
  184. },
  185. {
  186. name: core.ResourceName("memory"),
  187. result: false,
  188. },
  189. }
  190. for _, testCase := range testCases {
  191. if testCase.result != IsHugePageResourceName(testCase.name) {
  192. t.Errorf("resource: %v expected result: %v", testCase.name, testCase.result)
  193. }
  194. }
  195. }
  196. func TestHugePageResourceName(t *testing.T) {
  197. testCases := []struct {
  198. pageSize resource.Quantity
  199. name core.ResourceName
  200. }{
  201. {
  202. pageSize: resource.MustParse("2Mi"),
  203. name: core.ResourceName("hugepages-2Mi"),
  204. },
  205. {
  206. pageSize: resource.MustParse("1Gi"),
  207. name: core.ResourceName("hugepages-1Gi"),
  208. },
  209. {
  210. // verify we do not regress our canonical representation
  211. pageSize: *resource.NewQuantity(int64(2097152), resource.BinarySI),
  212. name: core.ResourceName("hugepages-2Mi"),
  213. },
  214. }
  215. for _, testCase := range testCases {
  216. if result := HugePageResourceName(testCase.pageSize); result != testCase.name {
  217. t.Errorf("pageSize: %v, expected: %v, but got: %v", testCase.pageSize.String(), testCase.name, result.String())
  218. }
  219. }
  220. }
  221. func TestHugePageSizeFromResourceName(t *testing.T) {
  222. testCases := []struct {
  223. name core.ResourceName
  224. expectErr bool
  225. pageSize resource.Quantity
  226. }{
  227. {
  228. name: core.ResourceName("hugepages-2Mi"),
  229. pageSize: resource.MustParse("2Mi"),
  230. expectErr: false,
  231. },
  232. {
  233. name: core.ResourceName("hugepages-1Gi"),
  234. pageSize: resource.MustParse("1Gi"),
  235. expectErr: false,
  236. },
  237. {
  238. name: core.ResourceName("hugepages-bad"),
  239. expectErr: true,
  240. },
  241. }
  242. for _, testCase := range testCases {
  243. value, err := HugePageSizeFromResourceName(testCase.name)
  244. if testCase.expectErr && err == nil {
  245. t.Errorf("Expected an error for %v", testCase.name)
  246. } else if !testCase.expectErr && err != nil {
  247. t.Errorf("Unexpected error for %v, got %v", testCase.name, err)
  248. } else if testCase.pageSize.Value() != value.Value() {
  249. t.Errorf("Unexpected pageSize for resource %v got %v", testCase.name, value.String())
  250. }
  251. }
  252. }
  253. func TestIsOvercommitAllowed(t *testing.T) {
  254. testCases := []struct {
  255. name core.ResourceName
  256. allowed bool
  257. }{
  258. {
  259. name: core.ResourceCPU,
  260. allowed: true,
  261. },
  262. {
  263. name: core.ResourceMemory,
  264. allowed: true,
  265. },
  266. {
  267. name: HugePageResourceName(resource.MustParse("2Mi")),
  268. allowed: false,
  269. },
  270. }
  271. for _, testCase := range testCases {
  272. if testCase.allowed != IsOvercommitAllowed(testCase.name) {
  273. t.Errorf("Unexpected result for %v", testCase.name)
  274. }
  275. }
  276. }