constellation/cli/proto/client_test.go

164 lines
4.9 KiB
Go
Raw Normal View History

package proto
import (
"context"
"encoding/base64"
"errors"
"net"
"testing"
"time"
"github.com/edgelesssys/constellation/coordinator/pubapi/pubproto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/test/bufconn"
)
func TestClose(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
client := NewClient(map[uint32][]byte{})
// Create a connection.
listener := bufconn.Listen(4)
defer listener.Close()
ctx := context.Background()
conn, err := grpc.DialContext(ctx, "", grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) {
return listener.Dial()
}), grpc.WithTransportCredentials(insecure.NewCredentials()))
require.NoError(err)
defer conn.Close()
// Wait for connection to reach 'connecting' state.
// Connection is not yet usable in this state, but we just need
// any stable non 'shutdown' state to validate that the state
// previous to calling close isn't already 'shutdown'.
err = func() error {
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
for {
if ctx.Err() != nil {
return ctx.Err()
}
if connectivity.Connecting == conn.GetState() {
return nil
}
time.Sleep(5 * time.Millisecond)
}
}()
require.NoError(err)
client.conn = conn
// Close connection.
assert.NoError(client.Close())
assert.Empty(client.conn)
assert.Equal(connectivity.Shutdown, conn.GetState())
// Close closed connection.
assert.NoError(client.Close())
assert.Empty(client.conn)
assert.Equal(connectivity.Shutdown, conn.GetState())
}
func TestActivate(t *testing.T) {
testKey := base64.StdEncoding.EncodeToString([]byte("32bytesWireGuardKeyForTheTesting"))
someErr := errors.New("failed")
testCases := map[string]struct {
avpn *stubAVPNClient
userPublicKey string
ips []string
errExpected bool
}{
"normal activation": {
avpn: &stubAVPNClient{},
userPublicKey: testKey,
ips: []string{"192.0.2.1", "192.0.2.1", "192.0.2.1"},
errExpected: false,
},
"client without avpn": {
userPublicKey: testKey,
ips: []string{"192.0.2.1", "192.0.2.1", "192.0.2.1"},
errExpected: true,
},
"empty public key parameter": {
avpn: &stubAVPNClient{},
userPublicKey: "",
ips: []string{"192.0.2.1", "192.0.2.1", "192.0.2.1"},
errExpected: true,
},
"invalid public key parameter": {
avpn: &stubAVPNClient{},
userPublicKey: "invalid Key",
ips: []string{"192.0.2.1", "192.0.2.1", "192.0.2.1"},
errExpected: true,
},
"empty ips parameter": {
avpn: &stubAVPNClient{},
userPublicKey: testKey,
ips: []string{},
errExpected: true,
},
"fail ActivateAsCoordinator": {
avpn: &stubAVPNClient{activateAsCoordinatorErr: someErr},
userPublicKey: testKey,
ips: []string{"192.0.2.1", "192.0.2.1", "192.0.2.1"},
errExpected: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
client := Client{}
if tc.avpn != nil {
client.avpn = tc.avpn
}
_, err := client.Activate(context.Background(), []byte(tc.userPublicKey), []byte("Constellation"), tc.ips, nil, "serviceaccount://test")
if tc.errExpected {
assert.Error(err)
} else {
assert.NoError(err)
assert.Equal("32bytesWireGuardKeyForTheTesting", string(tc.avpn.activateAsCoordinatorReqKey))
assert.Equal(tc.ips, tc.avpn.activateAsCoordinatorReqIPs)
assert.Equal("Constellation", string(tc.avpn.activateAsCoordinatorMasterSecret))
assert.Equal("serviceaccount://test", tc.avpn.activateCloudServiceAccountURI)
}
})
}
}
type stubAVPNClient struct {
activateAsCoordinatorErr error
activateAdditionalNodesErr error
activateAsCoordinatorReqKey []byte
activateAsCoordinatorReqIPs []string
activateAsCoordinatorMasterSecret []byte
activateAdditionalNodesReqIPs []string
activateCloudServiceAccountURI string
pubproto.APIClient
}
func (s *stubAVPNClient) ActivateAsCoordinator(ctx context.Context, in *pubproto.ActivateAsCoordinatorRequest,
opts ...grpc.CallOption,
) (pubproto.API_ActivateAsCoordinatorClient, error) {
s.activateAsCoordinatorReqKey = in.AdminVpnPubKey
s.activateAsCoordinatorReqIPs = in.NodePublicIps
s.activateAsCoordinatorMasterSecret = in.MasterSecret
s.activateCloudServiceAccountURI = in.CloudServiceAccountUri
return dummyAVPNActivateAsCoordinatorClient{}, s.activateAsCoordinatorErr
}
func (s *stubAVPNClient) ActivateAdditionalNodes(ctx context.Context, in *pubproto.ActivateAdditionalNodesRequest,
opts ...grpc.CallOption,
) (pubproto.API_ActivateAdditionalNodesClient, error) {
s.activateAdditionalNodesReqIPs = in.NodePublicIps
return dummyAVPNActivateAdditionalNodesClient{}, s.activateAdditionalNodesErr
}