Files
gf/contrib/registry/consul/consul_test.go
hailaz ee24da4e72 refactor: interface{} to any and reflect.Ptr to reflect.Pointer (#4395)
This pull request standardizes the use of the Go 1.18+ `any` type alias
instead of `interface{}` throughout the codebase. The change improves
code readability and aligns with modern Go best practices. The update
touches many files, including core data structures, code generation
templates, logging utilities, and test data, ensuring consistency across
all usages.

**Type alias migration to `any`:**

* Replaced all instances of `interface{}` with `any` in core data
structures such as `garray` and in generated model structs (e.g.,
`TableUser`, `User1`, `User2`) to modernize type usage.
[[1]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L31-R31)
[[2]](diffhunk://#diff-6c19859cb32c7516ea95ddc8f8235460818eb2f24d2204308e0d9e1b19e7d90fL15-R19)
[[3]](diffhunk://#diff-a15ba2f5e830b4833c47b902515a4f9e5a4f83a3707698f3229b307ec3776b41L15-R18)
[[4]](diffhunk://#diff-52e0837e84d49221d1b810d88fdf78221f36cffcd664fb42f8aba49a79b974dcL15-R19)
[[5]](diffhunk://#diff-11c3457d1a23a4ca6ecd00d6b856289774936b6a708384cf03aff164044e7546L15-R19)
[[6]](diffhunk://#diff-2cff9cf8e6a0cc34087326d8c8149c3bbaf74c76fdbdf5a73daed13cc04249e1L15-R19)
* Updated function signatures, method parameters, and return types from
`interface{}` to `any` in various parts of the codebase, including code
generation, service logic, and logging utilities (e.g., `mlog`).
[[1]](diffhunk://#diff-175edfeea54490b8fe4e18ffcbea5835efaf8f0b8acf623359073987cae7eb76L48-R55)
[[2]](diffhunk://#diff-2b1953fb78cf3593d8c2c7d911e95b65fd0b847c30ed0b4d167d16fe6d781235L54-R74)
[[3]](diffhunk://#diff-e001b7a4b63603b9b14f00de78a4d570bb76c5f57d856a24643f071032e12356L66-R73)
[[4]](diffhunk://#diff-5582954e8a9983988dc8854ad82067fb2ac6269b988e07357ad8db1dfec5f1a0L39-R41)
[[5]](diffhunk://#diff-c5d51d56f487779a2b6207c7ad26c7a20bbadcc846ce094fe60ab4cabff58c51L107-R107)
[[6]](diffhunk://#diff-f96e6a9fdb416eb1804ceaba1fe0ac637bff22c43837f8bb849c2366ce72d4a1L116-R121)
[[7]](diffhunk://#diff-f94c83a1b08ae060d9346f4a6031fc4a7b9a0b894e02d9afaa09018b6598eac0L112-R112)
[[8]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L36-R36)
[[9]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L74-R74)
[[10]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L96-R96)

**Generated code and templates:**

* Adjusted generated files and code generation templates to output `any`
instead of `interface{}` for relevant struct fields and function
signatures, ensuring that new code generation aligns with the updated
convention.
[[1]](diffhunk://#diff-6c19859cb32c7516ea95ddc8f8235460818eb2f24d2204308e0d9e1b19e7d90fL15-R19)
[[2]](diffhunk://#diff-a15ba2f5e830b4833c47b902515a4f9e5a4f83a3707698f3229b307ec3776b41L15-R18)
[[3]](diffhunk://#diff-52e0837e84d49221d1b810d88fdf78221f36cffcd664fb42f8aba49a79b974dcL15-R19)
[[4]](diffhunk://#diff-11c3457d1a23a4ca6ecd00d6b856289774936b6a708384cf03aff164044e7546L15-R19)
[[5]](diffhunk://#diff-2cff9cf8e6a0cc34087326d8c8149c3bbaf74c76fdbdf5a73daed13cc04249e1L15-R19)
[[6]](diffhunk://#diff-175edfeea54490b8fe4e18ffcbea5835efaf8f0b8acf623359073987cae7eb76L48-R55)
[[7]](diffhunk://#diff-e001b7a4b63603b9b14f00de78a4d570bb76c5f57d856a24643f071032e12356L66-R73)
[[8]](diffhunk://#diff-5582954e8a9983988dc8854ad82067fb2ac6269b988e07357ad8db1dfec5f1a0L39-R41)

**Container and utility updates:**

* Refactored the `garray` container implementation and related
constructors/methods to use `[]any` instead of `[]interface{}`, along
with corresponding function signatures.
[[1]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L31-R31)
[[2]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L52-R52)
[[3]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L62-R62)
[[4]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L73-R86)
[[5]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L96-R97)
[[6]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L107-R114)
[[7]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L124-R124)
[[8]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L135-R143)
[[9]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L167-R167)

These changes collectively modernize the codebase and prepare it for
future Go developments by using the idiomatic `any` type.
2025-08-28 16:53:19 +08:00

446 lines
11 KiB
Go

// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package consul
import (
"context"
"fmt"
"testing"
"time"
"github.com/gogf/gf/v2/net/gsvc"
"github.com/gogf/gf/v2/test/gtest"
)
const (
testServiceName = "test-service"
testServiceVersion = "1.0.0"
testServiceAddress = "127.0.0.1"
testServicePort = 8000
)
func createTestService() gsvc.Service {
return &gsvc.LocalService{
Name: testServiceName,
Version: testServiceVersion,
Metadata: map[string]any{
"region": "cn-east-1",
"zone": "a",
},
Endpoints: []gsvc.Endpoint{
gsvc.NewEndpoint(fmt.Sprintf("%s:%d", testServiceAddress, testServicePort)),
},
}
}
func Test_Registry_Basic(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
// Create registry
registry, err := New()
t.AssertNil(err)
t.Assert(registry != nil, true)
// Test invalid service
invalidService := &gsvc.LocalService{
Name: testServiceName,
Version: testServiceVersion,
}
_, err = registry.Register(context.Background(), invalidService)
t.AssertNE(err, nil) // Should fail due to no endpoints
// Create service with invalid metadata
serviceWithInvalidMeta := &gsvc.LocalService{
Name: testServiceName,
Version: testServiceVersion,
Metadata: map[string]any{
"invalid": make(chan int), // This will fail JSON marshaling
},
Endpoints: []gsvc.Endpoint{
gsvc.NewEndpoint(fmt.Sprintf("%s:%d", testServiceAddress, testServicePort)),
},
}
_, err = registry.Register(context.Background(), serviceWithInvalidMeta)
t.AssertNE(err, nil) // Should fail due to invalid metadata
// Create service
service := createTestService()
// Register service
ctx := context.Background()
registeredService, err := registry.Register(ctx, service)
t.AssertNil(err)
t.Assert(registeredService != nil, true)
// Wait for service to be registered
time.Sleep(2 * time.Second)
// Search service
services, err := registry.Search(ctx, gsvc.SearchInput{
Name: testServiceName,
Version: testServiceVersion,
})
t.AssertNil(err)
t.Assert(len(services), 1)
// Test service properties
foundService := services[0]
t.Assert(foundService.GetName(), testServiceName)
t.Assert(foundService.GetVersion(), testServiceVersion)
t.Assert(len(foundService.GetEndpoints()), 1)
endpoint := foundService.GetEndpoints()[0]
t.Assert(endpoint.Host(), testServiceAddress)
t.Assert(endpoint.Port(), testServicePort)
metadata := foundService.GetMetadata()
t.Assert(metadata != nil, true)
t.Assert(metadata["region"], "cn-east-1")
t.Assert(metadata["zone"], "a")
// Search with invalid metadata
servicesWithInvalidMeta, err := registry.Search(ctx, gsvc.SearchInput{
Name: testServiceName,
Version: testServiceVersion,
Metadata: map[string]any{"nonexistent": "value"},
})
t.AssertNil(err)
t.Assert(len(servicesWithInvalidMeta), 0)
// Test deregister with invalid service
err = registry.Deregister(ctx, invalidService)
t.AssertNE(err, nil) // Should fail due to no endpoints
// Deregister service
err = registry.Deregister(ctx, service)
t.AssertNil(err)
// Wait for service to be deregistered
time.Sleep(2 * time.Second)
// Verify service is deregistered
deregisteredServices, err := registry.Search(ctx, gsvc.SearchInput{
Name: testServiceName,
Version: testServiceVersion,
})
t.AssertNil(err)
t.Assert(len(deregisteredServices), 0)
})
}
func Test_Registry_Watch(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
// Create registry
registry, err := New()
t.AssertNil(err)
// Create service
service := createTestService()
// Register service first
ctx := context.Background()
_, err = registry.Register(ctx, service)
t.AssertNil(err)
defer registry.Deregister(ctx, service)
// Wait for service to be registered
time.Sleep(time.Second)
// Create watcher after service is registered
watcher, err := registry.Watch(ctx, testServiceName)
t.AssertNil(err)
t.Assert(watcher != nil, true)
defer watcher.Close()
// Wait for initial service query
time.Sleep(time.Second)
// Should receive initial service list
services, err := watcher.Proceed()
t.AssertNil(err)
t.Assert(len(services), 1)
t.Assert(services[0].GetName(), testServiceName)
t.Assert(services[0].GetVersion(), testServiceVersion)
// Test closing watcher
err = watcher.Close()
t.AssertNil(err)
// Test watch with invalid service name
watcher, err = registry.Watch(ctx, "nonexistent-service")
t.AssertNil(err)
defer watcher.Close()
// Wait for initial query
time.Sleep(time.Second)
// Should receive empty service list for non-existent service
services, err = watcher.Proceed()
t.AssertNil(err)
t.Assert(len(services), 0)
// Test watch after service deregistration
watcher, err = registry.Watch(ctx, testServiceName)
t.AssertNil(err)
defer watcher.Close()
// Wait for initial query
time.Sleep(time.Second)
err = registry.Deregister(ctx, service)
t.AssertNil(err)
// Wait for service to be deregistered
time.Sleep(time.Second)
// Should receive empty service list after deregistration
services, err = watcher.Proceed()
t.AssertNil(err)
t.Assert(len(services), 0)
})
}
func Test_Registry_MultipleServices(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
// Create registry
registry, err := New()
t.AssertNil(err)
// Create multiple services
service1 := &gsvc.LocalService{
Name: testServiceName,
Version: "1.0.0",
Metadata: map[string]any{
"region": "us-east-1",
},
Endpoints: []gsvc.Endpoint{
gsvc.NewEndpoint("127.0.0.1:8001"),
},
}
service2 := &gsvc.LocalService{
Name: testServiceName,
Version: "2.0.0",
Metadata: map[string]any{
"region": "us-west-1",
},
Endpoints: []gsvc.Endpoint{
gsvc.NewEndpoint("127.0.0.1:8002"),
},
}
// Register services
ctx := context.Background()
_, err = registry.Register(ctx, service1)
t.AssertNil(err)
defer registry.Deregister(ctx, service1)
_, err = registry.Register(ctx, service2)
t.AssertNil(err)
defer registry.Deregister(ctx, service2)
// Wait for services to be registered
time.Sleep(2 * time.Second)
// Search all services without version filter
allServices, err := registry.Search(ctx, gsvc.SearchInput{
Name: testServiceName,
})
t.AssertNil(err)
t.Assert(len(allServices), 2)
// Test search with different versions
services1, err := registry.Search(ctx, gsvc.SearchInput{
Name: testServiceName,
Version: "1.0.0",
})
t.AssertNil(err)
t.Assert(len(services1), 1)
t.Assert(services1[0].GetVersion(), "1.0.0")
services2, err := registry.Search(ctx, gsvc.SearchInput{
Name: testServiceName,
Version: "2.0.0",
})
t.AssertNil(err)
t.Assert(len(services2), 1)
t.Assert(services2[0].GetVersion(), "2.0.0")
// Test search with metadata
servicesEast, err := registry.Search(ctx, gsvc.SearchInput{
Name: testServiceName,
Metadata: map[string]any{
"region": "us-east-1",
},
})
t.AssertNil(err)
t.Assert(len(servicesEast), 1)
t.Assert(servicesEast[0].GetMetadata()["region"], "us-east-1")
// Watch both services
watcher, err := registry.Watch(ctx, testServiceName)
t.AssertNil(err)
defer watcher.Close()
// Wait for initial query
time.Sleep(time.Second)
// Should receive updates for both services
services, err := watcher.Proceed()
t.AssertNil(err)
t.Assert(len(services), 2)
// Verify services are sorted by version
t.Assert(services[0].GetVersion() < services[1].GetVersion(), true)
})
}
func Test_Registry_Options(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
// Test with custom address
registry1, err := New(WithAddress("localhost:8500"))
t.AssertNil(err)
t.Assert(registry1.(*Registry).GetAddress(), "localhost:8500")
// Test with token
registry2, err := New(WithAddress("localhost:8500"), WithToken("test-token"))
t.AssertNil(err)
t.Assert(registry2.(*Registry).options["token"], "test-token")
// Test with invalid address (should still create registry but fail on operations)
registry3, err := New(WithAddress("invalid:99999"))
t.AssertNil(err)
_, err = registry3.Register(context.Background(), createTestService())
t.AssertNE(err, nil)
})
}
func Test_Registry_MultipleServicesMetadataFiltering(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
// Create registry
registry, err := New()
t.AssertNil(err)
// Create multiple services
service1 := &gsvc.LocalService{
Name: testServiceName,
Version: "1.0.0",
Metadata: map[string]any{
"region": "us-east-1",
"env": "dev",
},
Endpoints: []gsvc.Endpoint{
gsvc.NewEndpoint("127.0.0.1:8001"),
},
}
service2 := &gsvc.LocalService{
Name: testServiceName,
Version: "2.0.0",
Metadata: map[string]any{
"region": "us-west-1",
"env": "prod",
},
Endpoints: []gsvc.Endpoint{
gsvc.NewEndpoint("127.0.0.1:8002"),
},
}
// Register services
ctx := context.Background()
_, err = registry.Register(ctx, service1)
t.AssertNil(err)
defer registry.Deregister(ctx, service1)
_, err = registry.Register(ctx, service2)
t.AssertNil(err)
defer registry.Deregister(ctx, service2)
time.Sleep(time.Second) // Wait for services to be registered
// Test search with metadata filtering
servicesDev, err := registry.Search(ctx, gsvc.SearchInput{
Name: testServiceName,
Metadata: map[string]any{
"env": "dev",
},
})
t.AssertNil(err)
t.Assert(len(servicesDev), 1)
t.Assert(servicesDev[0].GetMetadata()["env"], "dev")
servicesProd, err := registry.Search(ctx, gsvc.SearchInput{
Name: testServiceName,
Metadata: map[string]any{
"env": "prod",
},
})
t.AssertNil(err)
t.Assert(len(servicesProd), 1)
t.Assert(servicesProd[0].GetMetadata()["env"], "prod")
})
}
func Test_Registry_MultipleServicesVersionFiltering(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
// Create registry
registry, err := New()
t.AssertNil(err)
// Create multiple services
service1 := &gsvc.LocalService{
Name: testServiceName,
Version: "1.0.0",
Metadata: map[string]any{
"region": "us-east-1",
},
Endpoints: []gsvc.Endpoint{
gsvc.NewEndpoint("127.0.0.1:8001"),
},
}
service2 := &gsvc.LocalService{
Name: testServiceName,
Version: "2.0.0",
Metadata: map[string]any{
"region": "us-west-1",
},
Endpoints: []gsvc.Endpoint{
gsvc.NewEndpoint("127.0.0.1:8002"),
},
}
// Register services
ctx := context.Background()
_, err = registry.Register(ctx, service1)
t.AssertNil(err)
defer registry.Deregister(ctx, service1)
_, err = registry.Register(ctx, service2)
t.AssertNil(err)
defer registry.Deregister(ctx, service2)
time.Sleep(time.Second) // Wait for services to be registered
// Test search with version filtering
services, err := registry.Search(ctx, gsvc.SearchInput{
Name: testServiceName,
Version: "1.0.0",
})
t.AssertNil(err)
t.Assert(len(services), 1)
t.Assert(services[0].GetVersion(), "1.0.0")
services, err = registry.Search(ctx, gsvc.SearchInput{
Name: testServiceName,
Version: "2.0.0",
})
t.AssertNil(err)
t.Assert(len(services), 1)
t.Assert(services[0].GetVersion(), "2.0.0")
})
}