From 1c5a1484b57850c17ee4fe1eba8d3628ab70f3d7 Mon Sep 17 00:00:00 2001 From: danl5 Date: Tue, 11 Jun 2024 21:47:55 +0800 Subject: [PATCH] update Readme and add unit tests for rpc transport --- Makefile | 4 +- README.md | 49 +++++++------ examples/onenode/node.go | 15 +--- pkg/transport/rpc/config_test.go | 119 +++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+), 35 deletions(-) create mode 100644 pkg/transport/rpc/config_test.go diff --git a/Makefile b/Makefile index b596cfb..aa1e1fa 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ clean: @go clean rm --force "xx.out" test: - @go test + @go test ./... check: @go fmt ./ @go vet ./ @@ -29,4 +29,4 @@ help: @echo "make cover - Checks the test coverage." @echo "make run - Runs the program directly." @echo "make lint - Performs code linting." - @echo "make docker - Builds a Docker image." \ No newline at end of file + @echo "make docker - Builds a Docker image." diff --git a/README.md b/README.md index a65e5d7..06ec0e8 100644 --- a/README.md +++ b/README.md @@ -38,26 +38,35 @@ type ElectConfig struct { Create an Elect instance: ```go -e, err := goelect.NewElect(&goelect.ElectConfig{ - ElectTimeout: 200, - HeartBeatInterval: 150, - ConnectTimeout: 10, - Peers: peerNodes, - // state transition callbacks - CallBacks: &goelect.StateCallBacks{ - EnterLeader: enterLeader, - LeaveLeader: leaveLeader, - EnterFollower: enterFollower, - LeaveFollower: leaveFollower, - EnterCandidate: enterCandidate, - LeaveCandidate: leaveCandidate, - }, - // self node - Node: goelect.Node{ - Address: *nodeAddress, - ID: *nodeAddress, - }, - }, slog.Default()) + // use the built-in RPC as the transport layer. + rpcTransport, err := rpc.NewRPC(logger) + if err != nil { + return nil, err + } + e, err := goelect.NewElect( + rpcTransport, + // rpc transport config + &rpc.Config{}, + &goelect.ElectConfig{ + ElectTimeout: 200, + HeartBeatInterval: 150, + ConnectTimeout: 10, + Peers: peerNodes, + // state transition callbacks + CallBacks: &goelect.StateCallBacks{ + EnterLeader: enterLeader, + LeaveLeader: leaveLeader, + EnterFollower: enterFollower, + LeaveFollower: leaveFollower, + EnterCandidate: enterCandidate, + LeaveCandidate: leaveCandidate, + }, + // self node + Node: goelect.Node{ + Address: *nodeAddress, + ID: *nodeAddress, + }, + }, logger) ``` Start the Elect: ```go diff --git a/examples/onenode/node.go b/examples/onenode/node.go index b835839..bac5940 100644 --- a/examples/onenode/node.go +++ b/examples/onenode/node.go @@ -49,23 +49,12 @@ func newElect() (*goelect.Elect, error) { if err != nil { return nil, err } - // rpc transport config - rpcTransportConfig := &rpc.Config{ - ServerCAs: nil, - ServerKey: "", - ServerCert: "", - ServerSkipVerify: false, - ClientCAs: nil, - ClientCert: "", - ClientKey: "", - ClientSkipVerify: false, - ConnectTimeout: 0, - } // new elect e, err := goelect.NewElect( rpcTransport, - rpcTransportConfig, + // rpc transport config + &rpc.Config{}, &goelect.ElectConfig{ ElectTimeout: 200, HeartBeatInterval: 150, diff --git a/pkg/transport/rpc/config_test.go b/pkg/transport/rpc/config_test.go new file mode 100644 index 0000000..b8e4f08 --- /dev/null +++ b/pkg/transport/rpc/config_test.go @@ -0,0 +1,119 @@ +package rpc + +import ( + "errors" + "testing" +) + +func TestConfig_Validate(t *testing.T) { + // Define test cases + tests := []struct { + name string + config Config + expectedError error + }{ + { + name: "incomplete server certificate configuration", + config: Config{ + ServerKey: "key.pem", + ServerCert: "", + ServerSkipVerify: false, + ServerCAs: []string{}, + ClientKey: "", + ClientCert: "", + ClientSkipVerify: false, + ClientCAs: []string{}, + }, + expectedError: errors.New("incomplete server certificate configuration"), + }, + { + name: "no server CAs configured", + config: Config{ + ServerKey: "cert.key", + ServerCert: "cert.pem", + ServerSkipVerify: false, + ServerCAs: []string{}, + ClientKey: "", + ClientCert: "", + ClientSkipVerify: false, + ClientCAs: []string{}, + }, + expectedError: errors.New("no server CAs configured"), + }, + { + name: "incomplete client certificate configuration", + config: Config{ + ServerKey: "", + ServerCert: "", + ServerSkipVerify: false, + ServerCAs: []string{}, + ClientKey: "key.pem", + ClientCert: "", + ClientSkipVerify: false, + ClientCAs: []string{}, + }, + expectedError: errors.New("incomplete client certificate configuration"), + }, + { + name: "no client CAs configured", + config: Config{ + ServerKey: "", + ServerCert: "", + ServerSkipVerify: false, + ServerCAs: []string{}, + ClientKey: "cert.key", + ClientCert: "cert.pem", + ClientSkipVerify: false, + ClientCAs: []string{}, + }, + expectedError: errors.New("no client CAs configured"), + }, + { + name: "valid configuration", + config: Config{ + ServerKey: "key.pem", + ServerCert: "cert.pem", + ServerSkipVerify: true, + ServerCAs: []string{}, + ClientKey: "client_key.pem", + ClientCert: "client_cert.pem", + ClientSkipVerify: true, + ClientCAs: []string{}, + }, + expectedError: nil, + }, + { + name: "empty configuration", + config: Config{ + ServerKey: "", + ServerCert: "", + ServerSkipVerify: false, + ServerCAs: []string{}, + ClientKey: "", + ClientCert: "", + ClientSkipVerify: false, + ClientCAs: []string{}, + }, + expectedError: nil, + }, + } + + // Run test cases + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.config.Validate() + + if tt.expectedError != nil && err == nil { + t.Errorf("expected error %v, but got nil", tt.expectedError) + } + + if tt.expectedError == nil && err != nil { + t.Errorf("expected no error, but got %v", err) + } + + if tt.expectedError != nil && err != nil && tt.expectedError.Error() != err.Error() { + t.Errorf("expected error %v, but got %v", tt.expectedError, err) + } + }) + } +}