|
6 | 6 | "context"
|
7 | 7 | "crypto/sha256"
|
8 | 8 | "encoding/json"
|
| 9 | + "net/netip" |
9 | 10 | "sync"
|
10 | 11 | "testing"
|
11 | 12 | "time"
|
@@ -222,6 +223,73 @@ func TestServiceForceUpdateCluster(t *testing.T) {
|
222 | 223 | })
|
223 | 224 | }
|
224 | 225 |
|
| 226 | +func TestService_Read_IPv6Normalization(t *testing.T) { |
| 227 | + // Define a canonical IPv6 representation |
| 228 | + key := "2001:0db8:0000:0000:0000:0000:0000:0001" |
| 229 | + parsedKey, err := netip.ParseAddr(key) |
| 230 | + if err != nil { |
| 231 | + t.Fatal(err) |
| 232 | + } |
| 233 | + |
| 234 | + // Assume that our system normalizes IPv6 addresses to the canonical form. |
| 235 | + // Create the configuration for the canonical IPv6 address. |
| 236 | + nodeConfig := NodeConfig{ |
| 237 | + NodeInfo: &scyllaclient.NodeInfo{ |
| 238 | + AgentVersion: "expectedVersion", |
| 239 | + }, |
| 240 | + } |
| 241 | + configHash, err := nodeConfig.sha256hash() |
| 242 | + if err != nil { |
| 243 | + t.Fatal(err) |
| 244 | + } |
| 245 | + |
| 246 | + clusterID := uuid.MustRandom() |
| 247 | + // Prepopulate the service config with the canonical representation as the key. |
| 248 | + initialState := convertMapToSyncMap(map[any]any{ |
| 249 | + clusterID.String(): convertMapToSyncMap(map[any]any{ |
| 250 | + parsedKey.String(): nodeConfig, |
| 251 | + }), |
| 252 | + }) |
| 253 | + |
| 254 | + // Define several valid IPv6 representations for the same host. |
| 255 | + testCases := []struct { |
| 256 | + name string |
| 257 | + hostKey string |
| 258 | + }{ |
| 259 | + {"Fully Expanded", "2001:0db8:0000:0000:0000:0000:0000:0001"}, |
| 260 | + {"Uncompressed", "2001:db8:0:0:0:0:0:1"}, |
| 261 | + {"Compressed", "2001:db8::1"}, |
| 262 | + {"Uppercase Variant", "2001:DB8::1"}, |
| 263 | + {"Bracketed", "[2001:db8::1]"}, |
| 264 | + } |
| 265 | + |
| 266 | + svc := Service{ |
| 267 | + svcConfig: DefaultConfig(), |
| 268 | + clusterSvc: &mockClusterServicer{}, |
| 269 | + scyllaClient: mockProviderFunc, |
| 270 | + secretsStore: &mockStore{}, |
| 271 | + configs: initialState, |
| 272 | + } |
| 273 | + |
| 274 | + for _, tc := range testCases { |
| 275 | + t.Run(tc.name, func(t *testing.T) { |
| 276 | + // When |
| 277 | + conf, err := svc.Read(clusterID, tc.hostKey) |
| 278 | + // Then |
| 279 | + if err != nil { |
| 280 | + t.Fatalf("unexpected error: %v", err) |
| 281 | + } |
| 282 | + h, err := conf.sha256hash() |
| 283 | + if err != nil { |
| 284 | + t.Fatalf("error creating hash: %v", err) |
| 285 | + } |
| 286 | + if h != configHash { |
| 287 | + t.Fatalf("expected hash %v, got %v", configHash, h) |
| 288 | + } |
| 289 | + }) |
| 290 | + } |
| 291 | +} |
| 292 | + |
225 | 293 | func (nc NodeConfig) sha256hash() (hash [32]byte, err error) {
|
226 | 294 | data, err := json.Marshal(nc)
|
227 | 295 | if err != nil {
|
|
0 commit comments