validation_test.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. /*
  2. Copyright 2019 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 validation
  14. import (
  15. "fmt"
  16. "strings"
  17. "testing"
  18. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  19. api "k8s.io/kubernetes/pkg/apis/core"
  20. "k8s.io/kubernetes/pkg/apis/discovery"
  21. utilpointer "k8s.io/utils/pointer"
  22. )
  23. func TestValidateEndpointSlice(t *testing.T) {
  24. standardMeta := metav1.ObjectMeta{
  25. Name: "hello",
  26. Namespace: "world",
  27. }
  28. testCases := map[string]struct {
  29. expectedErrors int
  30. endpointSlice *discovery.EndpointSlice
  31. }{
  32. "good-slice": {
  33. expectedErrors: 0,
  34. endpointSlice: &discovery.EndpointSlice{
  35. ObjectMeta: standardMeta,
  36. AddressType: discovery.AddressTypeIPv4,
  37. Ports: []discovery.EndpointPort{{
  38. Name: utilpointer.StringPtr("http"),
  39. Protocol: protocolPtr(api.ProtocolTCP),
  40. }},
  41. Endpoints: []discovery.Endpoint{{
  42. Addresses: generateIPAddresses(1),
  43. Hostname: utilpointer.StringPtr("valid-123"),
  44. }},
  45. },
  46. },
  47. "good-fqdns": {
  48. expectedErrors: 0,
  49. endpointSlice: &discovery.EndpointSlice{
  50. ObjectMeta: standardMeta,
  51. AddressType: discovery.AddressTypeFQDN,
  52. Ports: []discovery.EndpointPort{{
  53. Name: utilpointer.StringPtr("http"),
  54. Protocol: protocolPtr(api.ProtocolTCP),
  55. }},
  56. Endpoints: []discovery.Endpoint{{
  57. Addresses: []string{"foo.example.com", "example.com", "example.com.", "hyphens-are-good.example.com"},
  58. Hostname: utilpointer.StringPtr("valid-123"),
  59. }},
  60. },
  61. },
  62. "all-protocols": {
  63. expectedErrors: 0,
  64. endpointSlice: &discovery.EndpointSlice{
  65. ObjectMeta: standardMeta,
  66. AddressType: discovery.AddressTypeIPv4,
  67. Ports: []discovery.EndpointPort{{
  68. Name: utilpointer.StringPtr("tcp"),
  69. Protocol: protocolPtr(api.ProtocolTCP),
  70. }, {
  71. Name: utilpointer.StringPtr("udp"),
  72. Protocol: protocolPtr(api.ProtocolUDP),
  73. }, {
  74. Name: utilpointer.StringPtr("sctp"),
  75. Protocol: protocolPtr(api.ProtocolSCTP),
  76. }},
  77. Endpoints: []discovery.Endpoint{{
  78. Addresses: generateIPAddresses(1),
  79. Hostname: utilpointer.StringPtr("valid-123"),
  80. }},
  81. },
  82. },
  83. "app-protocols": {
  84. expectedErrors: 0,
  85. endpointSlice: &discovery.EndpointSlice{
  86. ObjectMeta: standardMeta,
  87. AddressType: discovery.AddressTypeIP,
  88. Ports: []discovery.EndpointPort{{
  89. Name: utilpointer.StringPtr("one"),
  90. Protocol: protocolPtr(api.ProtocolTCP),
  91. AppProtocol: utilpointer.StringPtr("HTTP"),
  92. }, {
  93. Name: utilpointer.StringPtr("two"),
  94. Protocol: protocolPtr(api.ProtocolTCP),
  95. AppProtocol: utilpointer.StringPtr("https"),
  96. }, {
  97. Name: utilpointer.StringPtr("three"),
  98. Protocol: protocolPtr(api.ProtocolTCP),
  99. AppProtocol: utilpointer.StringPtr("my-protocol"),
  100. }, {
  101. Name: utilpointer.StringPtr("four"),
  102. Protocol: protocolPtr(api.ProtocolTCP),
  103. AppProtocol: utilpointer.StringPtr("example.com/custom-protocol"),
  104. }},
  105. Endpoints: []discovery.Endpoint{{
  106. Addresses: generateIPAddresses(1),
  107. Hostname: utilpointer.StringPtr("valid-123"),
  108. }},
  109. },
  110. },
  111. "empty-port-name": {
  112. expectedErrors: 0,
  113. endpointSlice: &discovery.EndpointSlice{
  114. ObjectMeta: standardMeta,
  115. AddressType: discovery.AddressTypeIPv4,
  116. Ports: []discovery.EndpointPort{{
  117. Name: utilpointer.StringPtr(""),
  118. Protocol: protocolPtr(api.ProtocolTCP),
  119. }, {
  120. Name: utilpointer.StringPtr("http"),
  121. Protocol: protocolPtr(api.ProtocolTCP),
  122. }},
  123. Endpoints: []discovery.Endpoint{{
  124. Addresses: generateIPAddresses(1),
  125. }},
  126. },
  127. },
  128. "long-port-name": {
  129. expectedErrors: 0,
  130. endpointSlice: &discovery.EndpointSlice{
  131. ObjectMeta: standardMeta,
  132. AddressType: discovery.AddressTypeIPv4,
  133. Ports: []discovery.EndpointPort{{
  134. Name: utilpointer.StringPtr(strings.Repeat("a", 63)),
  135. Protocol: protocolPtr(api.ProtocolTCP),
  136. }},
  137. Endpoints: []discovery.Endpoint{{
  138. Addresses: generateIPAddresses(1),
  139. }},
  140. },
  141. },
  142. "empty-ports-and-endpoints": {
  143. expectedErrors: 0,
  144. endpointSlice: &discovery.EndpointSlice{
  145. ObjectMeta: standardMeta,
  146. AddressType: discovery.AddressTypeIPv4,
  147. Ports: []discovery.EndpointPort{},
  148. Endpoints: []discovery.Endpoint{},
  149. },
  150. },
  151. "max-endpoints": {
  152. expectedErrors: 0,
  153. endpointSlice: &discovery.EndpointSlice{
  154. ObjectMeta: standardMeta,
  155. AddressType: discovery.AddressTypeIPv4,
  156. Ports: generatePorts(1),
  157. Endpoints: generateEndpoints(maxEndpoints),
  158. },
  159. },
  160. "max-ports": {
  161. expectedErrors: 0,
  162. endpointSlice: &discovery.EndpointSlice{
  163. ObjectMeta: standardMeta,
  164. AddressType: discovery.AddressTypeIPv4,
  165. Ports: generatePorts(maxPorts),
  166. },
  167. },
  168. "max-addresses": {
  169. expectedErrors: 0,
  170. endpointSlice: &discovery.EndpointSlice{
  171. ObjectMeta: standardMeta,
  172. AddressType: discovery.AddressTypeIPv4,
  173. Ports: []discovery.EndpointPort{{
  174. Name: utilpointer.StringPtr("http"),
  175. Protocol: protocolPtr(api.ProtocolTCP),
  176. }},
  177. Endpoints: []discovery.Endpoint{{
  178. Addresses: generateIPAddresses(maxAddresses),
  179. }},
  180. },
  181. },
  182. "max-topology-keys": {
  183. expectedErrors: 0,
  184. endpointSlice: &discovery.EndpointSlice{
  185. ObjectMeta: standardMeta,
  186. AddressType: discovery.AddressTypeIPv4,
  187. Ports: []discovery.EndpointPort{{
  188. Name: utilpointer.StringPtr("http"),
  189. Protocol: protocolPtr(api.ProtocolTCP),
  190. }},
  191. Endpoints: []discovery.Endpoint{{
  192. Addresses: generateIPAddresses(1),
  193. Topology: generateTopology(maxTopologyLabels),
  194. }},
  195. },
  196. },
  197. // expected failures
  198. "duplicate-port-name": {
  199. expectedErrors: 1,
  200. endpointSlice: &discovery.EndpointSlice{
  201. ObjectMeta: standardMeta,
  202. AddressType: discovery.AddressTypeIPv4,
  203. Ports: []discovery.EndpointPort{{
  204. Name: utilpointer.StringPtr(""),
  205. Protocol: protocolPtr(api.ProtocolTCP),
  206. }, {
  207. Name: utilpointer.StringPtr(""),
  208. Protocol: protocolPtr(api.ProtocolTCP),
  209. }},
  210. Endpoints: []discovery.Endpoint{},
  211. },
  212. },
  213. "bad-port-name-caps": {
  214. expectedErrors: 1,
  215. endpointSlice: &discovery.EndpointSlice{
  216. ObjectMeta: standardMeta,
  217. AddressType: discovery.AddressTypeIPv4,
  218. Ports: []discovery.EndpointPort{{
  219. Name: utilpointer.StringPtr("aCapital"),
  220. Protocol: protocolPtr(api.ProtocolTCP),
  221. }},
  222. Endpoints: []discovery.Endpoint{},
  223. },
  224. },
  225. "bad-port-name-chars": {
  226. expectedErrors: 1,
  227. endpointSlice: &discovery.EndpointSlice{
  228. ObjectMeta: standardMeta,
  229. AddressType: discovery.AddressTypeIPv4,
  230. Ports: []discovery.EndpointPort{{
  231. Name: utilpointer.StringPtr("almost_valid"),
  232. Protocol: protocolPtr(api.ProtocolTCP),
  233. }},
  234. Endpoints: []discovery.Endpoint{},
  235. },
  236. },
  237. "bad-port-name-length": {
  238. expectedErrors: 1,
  239. endpointSlice: &discovery.EndpointSlice{
  240. ObjectMeta: standardMeta,
  241. AddressType: discovery.AddressTypeIPv4,
  242. Ports: []discovery.EndpointPort{{
  243. Name: utilpointer.StringPtr(strings.Repeat("a", 64)),
  244. Protocol: protocolPtr(api.ProtocolTCP),
  245. }},
  246. Endpoints: []discovery.Endpoint{},
  247. },
  248. },
  249. "invalid-port-protocol": {
  250. expectedErrors: 1,
  251. endpointSlice: &discovery.EndpointSlice{
  252. ObjectMeta: standardMeta,
  253. AddressType: discovery.AddressTypeIPv4,
  254. Ports: []discovery.EndpointPort{{
  255. Name: utilpointer.StringPtr("http"),
  256. Protocol: protocolPtr(api.Protocol("foo")),
  257. }},
  258. },
  259. },
  260. "too-many-ports": {
  261. expectedErrors: 1,
  262. endpointSlice: &discovery.EndpointSlice{
  263. ObjectMeta: standardMeta,
  264. AddressType: discovery.AddressTypeIPv4,
  265. Ports: generatePorts(maxPorts + 1),
  266. },
  267. },
  268. "too-many-endpoints": {
  269. expectedErrors: 1,
  270. endpointSlice: &discovery.EndpointSlice{
  271. ObjectMeta: standardMeta,
  272. AddressType: discovery.AddressTypeIPv4,
  273. Ports: generatePorts(1),
  274. Endpoints: generateEndpoints(maxEndpoints + 1),
  275. },
  276. },
  277. "no-endpoint-addresses": {
  278. expectedErrors: 1,
  279. endpointSlice: &discovery.EndpointSlice{
  280. ObjectMeta: standardMeta,
  281. AddressType: discovery.AddressTypeIPv4,
  282. Ports: []discovery.EndpointPort{{
  283. Name: utilpointer.StringPtr("http"),
  284. Protocol: protocolPtr(api.ProtocolTCP),
  285. }},
  286. Endpoints: []discovery.Endpoint{{
  287. Addresses: generateIPAddresses(0),
  288. }},
  289. },
  290. },
  291. "too-many-addresses": {
  292. expectedErrors: 1,
  293. endpointSlice: &discovery.EndpointSlice{
  294. ObjectMeta: standardMeta,
  295. AddressType: discovery.AddressTypeIPv4,
  296. Ports: []discovery.EndpointPort{{
  297. Name: utilpointer.StringPtr("http"),
  298. Protocol: protocolPtr(api.ProtocolTCP),
  299. }},
  300. Endpoints: []discovery.Endpoint{{
  301. Addresses: generateIPAddresses(maxAddresses + 1),
  302. }},
  303. },
  304. },
  305. "bad-topology-key": {
  306. expectedErrors: 1,
  307. endpointSlice: &discovery.EndpointSlice{
  308. ObjectMeta: standardMeta,
  309. AddressType: discovery.AddressTypeIPv4,
  310. Ports: []discovery.EndpointPort{{
  311. Name: utilpointer.StringPtr("http"),
  312. Protocol: protocolPtr(api.ProtocolTCP),
  313. }},
  314. Endpoints: []discovery.Endpoint{{
  315. Addresses: generateIPAddresses(1),
  316. Topology: map[string]string{"--INVALID": "example"},
  317. }},
  318. },
  319. },
  320. "too-many-topology-keys": {
  321. expectedErrors: 1,
  322. endpointSlice: &discovery.EndpointSlice{
  323. ObjectMeta: standardMeta,
  324. AddressType: discovery.AddressTypeIPv4,
  325. Ports: []discovery.EndpointPort{{
  326. Name: utilpointer.StringPtr("http"),
  327. Protocol: protocolPtr(api.ProtocolTCP),
  328. }},
  329. Endpoints: []discovery.Endpoint{{
  330. Addresses: generateIPAddresses(1),
  331. Topology: generateTopology(maxTopologyLabels + 1),
  332. }},
  333. },
  334. },
  335. "bad-hostname": {
  336. expectedErrors: 1,
  337. endpointSlice: &discovery.EndpointSlice{
  338. ObjectMeta: standardMeta,
  339. AddressType: discovery.AddressTypeIPv4,
  340. Ports: []discovery.EndpointPort{{
  341. Name: utilpointer.StringPtr("http"),
  342. Protocol: protocolPtr(api.ProtocolTCP),
  343. }},
  344. Endpoints: []discovery.Endpoint{{
  345. Addresses: generateIPAddresses(1),
  346. Hostname: utilpointer.StringPtr("--INVALID"),
  347. }},
  348. },
  349. },
  350. "bad-meta": {
  351. expectedErrors: 1,
  352. endpointSlice: &discovery.EndpointSlice{
  353. ObjectMeta: metav1.ObjectMeta{
  354. Name: "*&^",
  355. Namespace: "foo",
  356. },
  357. AddressType: discovery.AddressTypeIPv4,
  358. Ports: []discovery.EndpointPort{{
  359. Name: utilpointer.StringPtr("http"),
  360. Protocol: protocolPtr(api.ProtocolTCP),
  361. }},
  362. Endpoints: []discovery.Endpoint{{
  363. Addresses: generateIPAddresses(1),
  364. Hostname: utilpointer.StringPtr("valid-123"),
  365. }},
  366. },
  367. },
  368. "bad-ip": {
  369. expectedErrors: 1,
  370. endpointSlice: &discovery.EndpointSlice{
  371. ObjectMeta: standardMeta,
  372. AddressType: discovery.AddressTypeIP,
  373. Ports: []discovery.EndpointPort{{
  374. Name: utilpointer.StringPtr("http"),
  375. Protocol: protocolPtr(api.ProtocolTCP),
  376. }},
  377. Endpoints: []discovery.Endpoint{{
  378. Addresses: []string{"123.456.789.012"},
  379. Hostname: utilpointer.StringPtr("valid-123"),
  380. }},
  381. },
  382. },
  383. "bad-ipv4": {
  384. expectedErrors: 2,
  385. endpointSlice: &discovery.EndpointSlice{
  386. ObjectMeta: standardMeta,
  387. AddressType: discovery.AddressTypeIPv4,
  388. Ports: []discovery.EndpointPort{{
  389. Name: utilpointer.StringPtr("http"),
  390. Protocol: protocolPtr(api.ProtocolTCP),
  391. }},
  392. Endpoints: []discovery.Endpoint{{
  393. Addresses: []string{"123.456.789.012", "2001:4860:4860::8888"},
  394. Hostname: utilpointer.StringPtr("valid-123"),
  395. }},
  396. },
  397. },
  398. "bad-ipv6": {
  399. expectedErrors: 2,
  400. endpointSlice: &discovery.EndpointSlice{
  401. ObjectMeta: standardMeta,
  402. AddressType: discovery.AddressTypeIPv6,
  403. Ports: []discovery.EndpointPort{{
  404. Name: utilpointer.StringPtr("http"),
  405. Protocol: protocolPtr(api.ProtocolTCP),
  406. }},
  407. Endpoints: []discovery.Endpoint{{
  408. Addresses: []string{"123.456.789.012", "2001:4860:4860:defg"},
  409. Hostname: utilpointer.StringPtr("valid-123"),
  410. }},
  411. },
  412. },
  413. "bad-fqdns": {
  414. expectedErrors: 4,
  415. endpointSlice: &discovery.EndpointSlice{
  416. ObjectMeta: standardMeta,
  417. AddressType: discovery.AddressTypeFQDN,
  418. Ports: []discovery.EndpointPort{{
  419. Name: utilpointer.StringPtr("http"),
  420. Protocol: protocolPtr(api.ProtocolTCP),
  421. }},
  422. Endpoints: []discovery.Endpoint{{
  423. Addresses: []string{"foo.*", "FOO.example.com", "underscores_are_bad.example.com", "*.example.com"},
  424. Hostname: utilpointer.StringPtr("valid-123"),
  425. }},
  426. },
  427. },
  428. "bad-app-protocol": {
  429. expectedErrors: 1,
  430. endpointSlice: &discovery.EndpointSlice{
  431. ObjectMeta: standardMeta,
  432. AddressType: discovery.AddressTypeIP,
  433. Ports: []discovery.EndpointPort{{
  434. Name: utilpointer.StringPtr("http"),
  435. Protocol: protocolPtr(api.ProtocolTCP),
  436. AppProtocol: utilpointer.StringPtr("--"),
  437. }},
  438. Endpoints: []discovery.Endpoint{{
  439. Addresses: generateIPAddresses(1),
  440. Hostname: utilpointer.StringPtr("valid-123"),
  441. }},
  442. },
  443. },
  444. "empty-everything": {
  445. expectedErrors: 3,
  446. endpointSlice: &discovery.EndpointSlice{},
  447. },
  448. }
  449. for name, testCase := range testCases {
  450. t.Run(name, func(t *testing.T) {
  451. errs := ValidateEndpointSlice(testCase.endpointSlice, supportedAddressTypes.Union(deprecatedAddressTypes))
  452. if len(errs) != testCase.expectedErrors {
  453. t.Errorf("Expected %d errors, got %d errors: %v", testCase.expectedErrors, len(errs), errs)
  454. }
  455. })
  456. }
  457. }
  458. func TestValidateEndpointSliceCreate(t *testing.T) {
  459. standardMeta := metav1.ObjectMeta{
  460. Name: "hello",
  461. Namespace: "world",
  462. }
  463. testCases := map[string]struct {
  464. expectedErrors int
  465. endpointSlice *discovery.EndpointSlice
  466. }{
  467. "good-slice": {
  468. expectedErrors: 0,
  469. endpointSlice: &discovery.EndpointSlice{
  470. ObjectMeta: standardMeta,
  471. AddressType: discovery.AddressTypeIPv4,
  472. Ports: []discovery.EndpointPort{{
  473. Name: utilpointer.StringPtr("http"),
  474. Protocol: protocolPtr(api.ProtocolTCP),
  475. }},
  476. Endpoints: []discovery.Endpoint{{
  477. Addresses: generateIPAddresses(1),
  478. Hostname: utilpointer.StringPtr("valid-123"),
  479. }},
  480. },
  481. },
  482. // expected failures
  483. "deprecated-address-type": {
  484. expectedErrors: 1,
  485. endpointSlice: &discovery.EndpointSlice{
  486. ObjectMeta: standardMeta,
  487. AddressType: discovery.AddressTypeIP,
  488. Ports: []discovery.EndpointPort{{
  489. Name: utilpointer.StringPtr("http"),
  490. Protocol: protocolPtr(api.ProtocolTCP),
  491. }},
  492. Endpoints: []discovery.Endpoint{{
  493. Addresses: generateIPAddresses(1),
  494. }},
  495. },
  496. },
  497. "bad-address-type": {
  498. expectedErrors: 1,
  499. endpointSlice: &discovery.EndpointSlice{
  500. ObjectMeta: standardMeta,
  501. AddressType: discovery.AddressType("other"),
  502. Ports: []discovery.EndpointPort{{
  503. Name: utilpointer.StringPtr("http"),
  504. Protocol: protocolPtr(api.ProtocolTCP),
  505. }},
  506. Endpoints: []discovery.Endpoint{{
  507. Addresses: generateIPAddresses(1),
  508. }},
  509. },
  510. },
  511. }
  512. for name, testCase := range testCases {
  513. t.Run(name, func(t *testing.T) {
  514. errs := ValidateEndpointSliceCreate(testCase.endpointSlice)
  515. if len(errs) != testCase.expectedErrors {
  516. t.Errorf("Expected %d errors, got %d errors: %v", testCase.expectedErrors, len(errs), errs)
  517. }
  518. })
  519. }
  520. }
  521. func TestValidateEndpointSliceUpdate(t *testing.T) {
  522. standardMeta := metav1.ObjectMeta{Name: "es1", Namespace: "test"}
  523. testCases := map[string]struct {
  524. expectedErrors int
  525. newEndpointSlice *discovery.EndpointSlice
  526. oldEndpointSlice *discovery.EndpointSlice
  527. }{
  528. "valid and identical slices": {
  529. newEndpointSlice: &discovery.EndpointSlice{
  530. ObjectMeta: standardMeta,
  531. AddressType: discovery.AddressTypeIPv6,
  532. },
  533. oldEndpointSlice: &discovery.EndpointSlice{
  534. ObjectMeta: standardMeta,
  535. AddressType: discovery.AddressTypeIPv6,
  536. },
  537. expectedErrors: 0,
  538. },
  539. "deprecated address type": {
  540. expectedErrors: 0,
  541. newEndpointSlice: &discovery.EndpointSlice{
  542. ObjectMeta: standardMeta,
  543. AddressType: discovery.AddressTypeIP,
  544. },
  545. oldEndpointSlice: &discovery.EndpointSlice{
  546. ObjectMeta: standardMeta,
  547. AddressType: discovery.AddressTypeIP,
  548. },
  549. },
  550. "valid and identical slices with different address types": {
  551. newEndpointSlice: &discovery.EndpointSlice{
  552. ObjectMeta: standardMeta,
  553. AddressType: discovery.AddressTypeIP,
  554. },
  555. oldEndpointSlice: &discovery.EndpointSlice{
  556. ObjectMeta: standardMeta,
  557. AddressType: discovery.AddressType("other"),
  558. },
  559. expectedErrors: 1,
  560. },
  561. "invalid slices with valid address types": {
  562. newEndpointSlice: &discovery.EndpointSlice{
  563. ObjectMeta: standardMeta,
  564. AddressType: discovery.AddressTypeIP,
  565. Ports: []discovery.EndpointPort{{
  566. Name: utilpointer.StringPtr(""),
  567. Protocol: protocolPtr(api.Protocol("invalid")),
  568. }},
  569. },
  570. oldEndpointSlice: &discovery.EndpointSlice{
  571. ObjectMeta: standardMeta,
  572. AddressType: discovery.AddressTypeIP,
  573. },
  574. expectedErrors: 1,
  575. },
  576. }
  577. for name, testCase := range testCases {
  578. t.Run(name, func(t *testing.T) {
  579. errs := ValidateEndpointSliceUpdate(testCase.newEndpointSlice, testCase.oldEndpointSlice)
  580. if len(errs) != testCase.expectedErrors {
  581. t.Errorf("Expected %d errors, got %d errors: %v", testCase.expectedErrors, len(errs), errs)
  582. }
  583. })
  584. }
  585. }
  586. // Test helpers
  587. func protocolPtr(protocol api.Protocol) *api.Protocol {
  588. return &protocol
  589. }
  590. func generatePorts(n int) []discovery.EndpointPort {
  591. ports := []discovery.EndpointPort{}
  592. for i := 0; i < n; i++ {
  593. ports = append(ports, discovery.EndpointPort{
  594. Name: utilpointer.StringPtr(fmt.Sprintf("http-%d", i)),
  595. Protocol: protocolPtr(api.ProtocolTCP),
  596. })
  597. }
  598. return ports
  599. }
  600. func generateEndpoints(n int) []discovery.Endpoint {
  601. endpoints := []discovery.Endpoint{}
  602. for i := 0; i < n; i++ {
  603. endpoints = append(endpoints, discovery.Endpoint{
  604. Addresses: []string{fmt.Sprintf("10.1.2.%d", i%255)},
  605. })
  606. }
  607. return endpoints
  608. }
  609. func generateIPAddresses(n int) []string {
  610. addresses := []string{}
  611. for i := 0; i < n; i++ {
  612. addresses = append(addresses, fmt.Sprintf("10.1.2.%d", i%255))
  613. }
  614. return addresses
  615. }
  616. func generateTopology(n int) map[string]string {
  617. topology := map[string]string{}
  618. for i := 0; i < n; i++ {
  619. topology[fmt.Sprintf("topology-%d", i)] = "example"
  620. }
  621. return topology
  622. }