service_test.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. package kubemodel
  2. import (
  3. "testing"
  4. "time"
  5. "github.com/stretchr/testify/require"
  6. )
  7. func TestValidateService(t *testing.T) {
  8. start := time.Now().UTC().Truncate(time.Hour)
  9. end := start.Add(time.Hour)
  10. window := Window{Start: start, End: end}
  11. tests := []struct {
  12. name string
  13. service *Service
  14. wantErr string
  15. }{
  16. {
  17. name: "empty UID",
  18. service: &Service{Name: "my-svc", NamespaceUID: "ns-uid", Start: start, End: end},
  19. wantErr: "UID is missing for Service with name 'my-svc'",
  20. },
  21. {
  22. name: "empty Name",
  23. service: &Service{UID: "svc-uid", NamespaceUID: "ns-uid", Start: start, End: end},
  24. wantErr: "Name is missing for Service 'svc-uid'",
  25. },
  26. {
  27. name: "empty NamespaceUID",
  28. service: &Service{UID: "svc-uid", Name: "my-svc", Start: start, End: end},
  29. wantErr: "NamespaceUID is missing for Service 'svc-uid'",
  30. },
  31. {
  32. name: "outside window",
  33. service: &Service{UID: "svc-uid", Name: "my-svc", NamespaceUID: "ns-uid", Start: start.Add(-time.Hour), End: end},
  34. wantErr: checkWindow(window, start.Add(-time.Hour), end).Error(),
  35. },
  36. {
  37. name: "valid",
  38. service: &Service{UID: "svc-uid", Name: "my-svc", NamespaceUID: "ns-uid", Start: start, End: end},
  39. },
  40. }
  41. for _, tt := range tests {
  42. t.Run(tt.name, func(t *testing.T) {
  43. err := tt.service.ValidateService(window)
  44. if tt.wantErr != "" {
  45. require.EqualError(t, err, tt.wantErr)
  46. } else {
  47. require.NoError(t, err)
  48. }
  49. })
  50. }
  51. }
  52. func TestRegisterService(t *testing.T) {
  53. start := time.Now().UTC().Truncate(time.Hour)
  54. end := start.Add(time.Hour)
  55. newService := func(uid, name string) *Service {
  56. return &Service{UID: uid, Name: name, NamespaceUID: "ns-uid", Start: start, End: end}
  57. }
  58. tests := []struct {
  59. name string
  60. setup func(*KubeModelSet)
  61. service *Service
  62. wantErr string
  63. want *KubeModelSet
  64. }{
  65. {
  66. name: "validation failure",
  67. service: &Service{UID: "", Name: "my-svc", NamespaceUID: "ns-uid", Start: start, End: end},
  68. wantErr: "RegisterService: invalid service: UID is missing for Service with name 'my-svc'",
  69. want: func() *KubeModelSet {
  70. kms := NewKubeModelSet(start, end)
  71. kms.Metadata.Diagnostics = []Diagnostic{
  72. {Level: DiagnosticLevelError, Message: "RegisterService: invalid service: UID is missing for Service with name 'my-svc'"},
  73. }
  74. return kms
  75. }(),
  76. },
  77. {
  78. name: "registers service",
  79. service: newService("svc-uid", "my-svc"),
  80. want: func() *KubeModelSet {
  81. kms := NewKubeModelSet(start, end)
  82. kms.Services["svc-uid"] = newService("svc-uid", "my-svc")
  83. kms.Metadata.ObjectCount = 1
  84. return kms
  85. }(),
  86. },
  87. {
  88. name: "duplicate registration is a no-op",
  89. setup: func(kms *KubeModelSet) {
  90. kms.RegisterService(newService("svc-uid", "original"))
  91. },
  92. service: newService("svc-uid", "duplicate"),
  93. want: func() *KubeModelSet {
  94. kms := NewKubeModelSet(start, end)
  95. kms.Services["svc-uid"] = newService("svc-uid", "original")
  96. kms.Metadata.ObjectCount = 1
  97. return kms
  98. }(),
  99. },
  100. }
  101. for _, tt := range tests {
  102. t.Run(tt.name, func(t *testing.T) {
  103. kms := NewKubeModelSet(start, end)
  104. if tt.setup != nil {
  105. tt.setup(kms)
  106. }
  107. err := kms.RegisterService(tt.service)
  108. if tt.wantErr != "" {
  109. require.EqualError(t, err, tt.wantErr)
  110. } else {
  111. require.NoError(t, err)
  112. }
  113. KubeModelSetEquals(t, tt.want, kms)
  114. })
  115. }
  116. }
  117. func TestParseServiceType(t *testing.T) {
  118. tests := []struct {
  119. input string
  120. expected ServiceType
  121. }{
  122. // Exact canonical values
  123. {"ClusterIP", ServiceTypeClusterIP},
  124. {"NodePort", ServiceTypeNodePort},
  125. {"LoadBalancer", ServiceTypeLoadBalancer},
  126. {"ExternalName", ServiceTypeExternalName},
  127. // Case-insensitive
  128. {"clusterip", ServiceTypeClusterIP},
  129. {"nodeport", ServiceTypeNodePort},
  130. {"loadbalancer", ServiceTypeLoadBalancer},
  131. {"externalname", ServiceTypeExternalName},
  132. {"CLUSTERIP", ServiceTypeClusterIP},
  133. {"LOADBALANCER", ServiceTypeLoadBalancer},
  134. // "lb" alias
  135. {"lb", ServiceTypeLoadBalancer},
  136. {"LB", ServiceTypeLoadBalancer},
  137. // Unknown input defaults to ClusterIP
  138. {"", ServiceTypeClusterIP},
  139. {"unknown", ServiceTypeClusterIP},
  140. {"ingress", ServiceTypeClusterIP},
  141. }
  142. for _, tt := range tests {
  143. t.Run(tt.input, func(t *testing.T) {
  144. got := ParseServiceType(tt.input)
  145. if got != tt.expected {
  146. t.Errorf("ParseServiceType(%q) = %q, want %q", tt.input, got, tt.expected)
  147. }
  148. })
  149. }
  150. }