diff --git a/.github/workflows/go_unit_test.yml b/.github/workflows/go_unit_test.yml index 5636c3f..b31e5a8 100644 --- a/.github/workflows/go_unit_test.yml +++ b/.github/workflows/go_unit_test.yml @@ -16,7 +16,5 @@ jobs: - uses: actions/setup-go@v4 with: go-version: '1.20' - - name: setup OpenGemini - uses: shoothzj/setup-opengemini-action@main - name: Run coverage - run: go test ./... -coverpkg=./opengemini/... -race -coverprofile=coverage.out -covermode=atomic + run: go test ./... -coverpkg=./opcua/... -race -coverprofile=coverage.out -covermode=atomic diff --git a/go.mod b/go.mod index 2c81d83..d41d48b 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,11 @@ module opcua-go go 1.20 + +require github.com/stretchr/testify v1.9.0 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..60ce688 --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/opcua/server.go b/opcua/server.go index d6555ba..7f486fb 100644 --- a/opcua/server.go +++ b/opcua/server.go @@ -1,12 +1,59 @@ package opcua +import ( + "fmt" + "net" +) + type ServerConfig struct { + Host string + Port int +} + +func (s *ServerConfig) addr() string { + return fmt.Sprintf("%s:%d", s.Host, s.Port) } type Server struct { + config *ServerConfig + listener net.Listener } func NewServer(config *ServerConfig) *Server { - server := &Server{} + server := &Server{ + config: config, + } return server } + +func (s *Server) Run() (int, error) { + listener, err := net.Listen("tcp", s.config.addr()) + if err != nil { + return 0, fmt.Errorf("failed to listen on %s: %w", s.config.addr(), err) + } + + actualAddr, ok := listener.Addr().(*net.TCPAddr) + if !ok { + return 0, fmt.Errorf("failed to get TCP address from listener") + } + + if s.config.Port == 0 { + s.config.Port = actualAddr.Port + } + + s.listener = listener + + return actualAddr.Port, nil +} + +func (s *Server) Close() error { + if s.listener == nil { + return nil + } + err := s.listener.Close() + s.listener = nil + if err == nil { + return nil + } + return fmt.Errorf("failed to close listener: %w", err) +} diff --git a/opcua/server_test.go b/opcua/server_test.go new file mode 100644 index 0000000..159ba66 --- /dev/null +++ b/opcua/server_test.go @@ -0,0 +1,24 @@ +package opcua + +import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" +) + +func TestStartWithZeroPort(t *testing.T) { + config := &ServerConfig{ + Host: "localhost", + Port: 0, + } + + server := NewServer(config) + + port, err := server.Run() + require.NoError(t, err, "Server should start without error") + + assert.NotEqual(t, 0, port, "Expected a valid port to be assigned, but got port 0") + + err = server.Close() + assert.NoError(t, err, "Server should close without error") +}