NOISSUE - Improve SDK initialization (#302)

* do not require agent connection for all commands

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* improve tests

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* more test cases

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* blank line

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* ignore cmd

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

---------

Signed-off-by: Sammy Oina <sammyoina@gmail.com>
This commit is contained in:
Sammy Kerata Oina
2024-11-07 11:09:51 +03:00
committed by GitHub
parent d3636de824
commit 01a619fd2a
12 changed files with 524 additions and 368 deletions
+129 -114
View File
@@ -44,122 +44,137 @@ func generateRSAPrivateKeyFile(fileName string) error {
return nil
}
func TestAlgorithmCmd_Success(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Algo", mock.Anything, mock.Anything, mock.Anything).Return(nil)
testCLI := New(mockSDK)
func TestAlgorithmCmd(t *testing.T) {
tests := []struct {
name string
setupMock func(*mocks.SDK)
setupFiles func() error
args []string
connectErr error
expectedOutput string
cleanup func()
}{
{
name: "successful upload",
setupMock: func(m *mocks.SDK) {
m.On("Algo", mock.Anything, mock.Anything, mock.Anything).Return(nil)
},
setupFiles: func() error {
if err := os.WriteFile(algorithmFile, []byte("test algorithm"), 0o644); err != nil {
return err
}
return generateRSAPrivateKeyFile(privateKeyFile)
},
args: []string{algorithmFile, privateKeyFile},
expectedOutput: "Successfully uploaded algorithm",
cleanup: func() {
os.Remove(privateKeyFile)
os.Remove(algorithmFile)
},
},
{
name: "missing algorithm file",
setupMock: func(m *mocks.SDK) {
m.On("Algo", mock.Anything, mock.Anything, mock.Anything).Return(nil)
},
args: []string{"non_existent_algo_file.py", privateKeyFile},
expectedOutput: "Error reading algorithm file",
},
{
name: "missing private key file",
setupMock: func(m *mocks.SDK) {
m.On("Algo", mock.Anything, mock.Anything, mock.Anything).Return(nil)
},
setupFiles: func() error {
return os.WriteFile(algorithmFile, []byte("test algorithm"), 0o644)
},
args: []string{algorithmFile, "non_existent_private_key.pem"},
expectedOutput: "Error reading private key file",
cleanup: func() {
os.Remove(algorithmFile)
},
},
{
name: "upload failure",
setupMock: func(m *mocks.SDK) {
m.On("Algo", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("failed to upload algorithm due to error"))
},
setupFiles: func() error {
if err := os.WriteFile(algorithmFile, []byte("test algorithm"), 0o644); err != nil {
return err
}
return generateRSAPrivateKeyFile(privateKeyFile)
},
args: []string{algorithmFile, privateKeyFile},
expectedOutput: "Failed to upload algorithm",
cleanup: func() {
os.Remove(privateKeyFile)
os.Remove(algorithmFile)
},
},
{
name: "invalid private key",
setupMock: func(m *mocks.SDK) {
m.On("Algo", mock.Anything, mock.Anything, mock.Anything).Return(nil)
},
setupFiles: func() error {
if err := os.WriteFile(algorithmFile, []byte("test algorithm"), 0o644); err != nil {
return err
}
privKeyFile, err := os.Create(privateKeyFile)
if err != nil {
return err
}
defer privKeyFile.Close()
_, err = privKeyFile.WriteString("invalid private key")
return err
},
args: []string{algorithmFile, privateKeyFile},
expectedOutput: "Error decoding private key",
cleanup: func() {
os.Remove(algorithmFile)
os.Remove(privateKeyFile)
},
},
{
name: "connection error",
setupMock: func(m *mocks.SDK) {
},
connectErr: errors.New("failed to connect to agent"),
args: []string{algorithmFile, privateKeyFile},
expectedOutput: "Failed to connect to agent",
},
}
err := os.WriteFile(algorithmFile, []byte("test algorithm"), 0o644)
require.NoError(t, err)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockSDK := new(mocks.SDK)
if tt.setupMock != nil {
tt.setupMock(mockSDK)
}
err = generateRSAPrivateKeyFile(privateKeyFile)
require.NoError(t, err)
testCLI := CLI{
agentSDK: mockSDK,
connectErr: tt.connectErr,
}
cmd := testCLI.NewAlgorithmCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{algorithmFile, privateKeyFile})
err = cmd.Execute()
require.NoError(t, err)
if tt.setupFiles != nil {
err := tt.setupFiles()
require.NoError(t, err)
}
require.Contains(t, buf.String(), "Successfully uploaded algorithm")
t.Cleanup(func() {
os.Remove(privateKeyFile)
os.Remove(algorithmFile)
})
}
func TestAlgorithmCmd_MissingAlgorithmFile(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Algo", mock.Anything, mock.Anything, mock.Anything).Return(nil)
testCLI := New(mockSDK)
cmd := testCLI.NewAlgorithmCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{"non_existent_algo_file.py", privateKeyFile})
err := cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), "Error reading algorithm file")
}
func TestAlgorithmCmd_MissingPrivateKeyFile(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Algo", mock.Anything, mock.Anything, mock.Anything).Return(nil)
testCLI := New(mockSDK)
err := os.WriteFile(algorithmFile, []byte("test algorithm"), 0o644)
require.NoError(t, err)
cmd := testCLI.NewAlgorithmCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{algorithmFile, "non_existent_private_key.pem"})
err = cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), "Error reading private key file")
t.Cleanup(func() {
os.Remove(algorithmFile)
})
}
func TestAlgorithmCmd_UploadFailure(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Algo", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("failed to upload algorithm due to error"))
testCLI := New(mockSDK)
err := os.WriteFile(algorithmFile, []byte("test algorithm"), 0o644)
require.NoError(t, err)
err = generateRSAPrivateKeyFile(privateKeyFile)
require.NoError(t, err)
cmd := testCLI.NewAlgorithmCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{algorithmFile, privateKeyFile})
err = cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), "Failed to upload algorithm")
t.Cleanup(func() {
os.Remove(privateKeyFile)
os.Remove(algorithmFile)
})
}
func TestAlgorithmCmd_InvalidPrivateKey(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Algo", mock.Anything, mock.Anything, mock.Anything).Return(nil)
testCLI := New(mockSDK)
err := os.WriteFile(algorithmFile, []byte("test algorithm"), 0o644)
require.NoError(t, err)
privKeyFile, err := os.Create(privateKeyFile)
require.NoError(t, err)
defer privKeyFile.Close()
_, err = privKeyFile.WriteString("invalid private key")
require.NoError(t, err)
cmd := testCLI.NewAlgorithmCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{algorithmFile, privateKeyFile})
err = cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), "Error decoding private key")
t.Cleanup(func() {
os.Remove(algorithmFile)
os.Remove(privateKeyFile)
})
cmd := testCLI.NewAlgorithmCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs(tt.args)
err := cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), tt.expectedOutput)
if tt.cleanup != nil {
tt.cleanup()
}
})
}
}
+5
View File
@@ -29,6 +29,11 @@ func (cli *CLI) NewAlgorithmCmd() *cobra.Command {
Example: "algo <algo_file> <private_key_file_path>",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
if cli.connectErr != nil {
printError(cmd, "Failed to connect to agent: %v ❌ ", cli.connectErr)
return
}
algorithmFile := args[0]
cmd.Println("Uploading algorithm file:", algorithmFile)
+12 -7
View File
@@ -126,9 +126,9 @@ func (cli *CLI) NewAttestationCmd() *cobra.Command {
Use: "attestation [command]",
Short: "Get and validate attestations",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("Get and validate attestations\n\n")
fmt.Printf("Usage:\n %s [command]\n\n", cmd.CommandPath())
fmt.Printf("Available Commands:\n")
cmd.Printf("Get and validate attestations\n\n")
cmd.Printf("Usage:\n %s [command]\n\n", cmd.CommandPath())
cmd.Printf("Available Commands:\n")
// Filter out "completion" command
availableCommands := make([]*cobra.Command, 0)
@@ -139,14 +139,14 @@ func (cli *CLI) NewAttestationCmd() *cobra.Command {
}
for _, subCmd := range availableCommands {
fmt.Printf(" %-15s%s\n", subCmd.Name(), subCmd.Short)
cmd.Printf(" %-15s%s\n", subCmd.Name(), subCmd.Short)
}
fmt.Printf("\nFlags:\n")
cmd.Printf("\nFlags:\n")
cmd.Flags().VisitAll(func(flag *pflag.Flag) {
fmt.Printf(" -%s, --%s %s\n", flag.Shorthand, flag.Name, flag.Usage)
cmd.Printf(" -%s, --%s %s\n", flag.Shorthand, flag.Name, flag.Usage)
})
fmt.Printf("\nUse \"%s [command] --help\" for more information about a command.\n", cmd.CommandPath())
cmd.Printf("\nUse \"%s [command] --help\" for more information about a command.\n", cmd.CommandPath())
},
}
}
@@ -158,6 +158,11 @@ func (cli *CLI) NewGetAttestationCmd() *cobra.Command {
Example: "get <report_data>",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
if cli.connectErr != nil {
printError(cmd, "Failed to connect to agent: %v ❌ ", cli.connectErr)
return
}
cmd.Println("Getting attestation")
reportData, err := hex.DecodeString(args[0])
+99 -17
View File
@@ -27,29 +27,111 @@ func TestNewAttestationCmd(t *testing.T) {
assert.Equal(t, "attestation [command]", cmd.Use)
assert.Equal(t, "Get and validate attestations", cmd.Short)
}
func TestNewGetAttestationCmd(t *testing.T) {
mockSDK := new(mocks.SDK)
cli := &CLI{agentSDK: mockSDK}
cmd := cli.NewGetAttestationCmd()
var buf bytes.Buffer
cmd.SetOutput(&buf)
assert.Equal(t, "get", cmd.Use)
assert.Equal(t, "Retrieve attestation information from agent. Report data expected in hex enoded string of length 64 bytes.", cmd.Short)
reportData := bytes.Repeat([]byte{0x01}, agent.ReportDataSize)
mockSDK.On("Attestation", mock.Anything, [agent.ReportDataSize]byte(reportData)).Return([]byte("mock attestation"), nil)
cmd.SetArgs([]string{hex.EncodeToString(reportData)})
cmd.SetOut(&buf)
err := cmd.Execute()
assert.NoError(t, err)
assert.Contains(t, buf.String(), "Get and validate attestations")
}
assert.Contains(t, buf.String(), "Attestation result retrieved and saved successfully!")
func TestNewGetAttestationCmdN(t *testing.T) {
validattestation, err := os.ReadFile("../attestation.bin")
require.NoError(t, err)
testCases := []struct {
name string
args []string
mockResponse []byte
mockError error
expectedErr string
expectedOut string
}{
{
name: "successful attestation retrieval",
args: []string{hex.EncodeToString(bytes.Repeat([]byte{0x01}, agent.ReportDataSize))},
mockResponse: []byte("mock attestation"),
mockError: nil,
expectedOut: "Attestation result retrieved and saved successfully!",
},
{
name: "invalid report data (decoding error)",
args: []string{"invalid"},
mockResponse: nil,
mockError: errors.New("error"),
expectedErr: "Error decoding report data",
},
{
name: "invalid report data size",
args: []string{hex.EncodeToString(bytes.Repeat([]byte{0x01}, 32))},
mockResponse: nil,
mockError: errors.New("error"),
expectedErr: "report data must be a hex encoded string of length 64 bytes",
},
{
name: "invalid report data hex",
args: []string{"invalid"},
mockResponse: nil,
mockError: errors.New("error"),
expectedErr: "Error decoding report data",
},
{
name: "failed to get attestation",
args: []string{hex.EncodeToString(bytes.Repeat([]byte{0x01}, agent.ReportDataSize))},
mockResponse: nil,
mockError: errors.New("error"),
expectedErr: "Failed to get attestation due to error",
},
{
name: "JSON report error",
args: []string{hex.EncodeToString(bytes.Repeat([]byte{0x01}, agent.ReportDataSize)), "--json"},
mockResponse: []byte("mock attestation"),
mockError: nil,
expectedErr: "Error converting attestation to json",
},
{
name: "successful JSON report",
args: []string{hex.EncodeToString(bytes.Repeat([]byte{0x01}, agent.ReportDataSize)), "--json"},
mockResponse: validattestation,
mockError: nil,
expectedOut: "Attestation result retrieved and saved successfully!",
},
{
name: "connection error",
args: []string{hex.EncodeToString(bytes.Repeat([]byte{0x01}, agent.ReportDataSize))},
mockResponse: nil,
mockError: errors.New("failed to connect to agent"),
expectedErr: "Failed to connect to agent",
},
}
os.Remove(attestationFilePath)
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Cleanup(func() {
os.Remove(attestationFilePath)
os.Remove(attestationJson)
})
mockSDK := new(mocks.SDK)
cli := &CLI{agentSDK: mockSDK}
if tc.name == "connection error" {
cli.connectErr = errors.New("failed to connect to agent")
}
cmd := cli.NewGetAttestationCmd()
var buf bytes.Buffer
cmd.SetOutput(&buf)
mockSDK.On("Attestation", mock.Anything, [agent.ReportDataSize]byte(bytes.Repeat([]byte{0x01}, agent.ReportDataSize))).Return(tc.mockResponse, tc.mockError)
cmd.SetArgs(tc.args)
err := cmd.Execute()
if tc.expectedErr != "" {
assert.Contains(t, buf.String(), tc.expectedErr)
} else {
assert.NoError(t, err)
assert.Contains(t, buf.String(), tc.expectedOut)
}
})
}
}
func TestNewValidateAttestationValidationCmd(t *testing.T) {
+5
View File
@@ -26,6 +26,11 @@ func (cli *CLI) NewDatasetsCmd() *cobra.Command {
Example: "data <dataset_path> <private_key_file_path>",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
if cli.connectErr != nil {
printError(cmd, "Failed to connect to agent: %v ❌ ", cli.connectErr)
return
}
datasetPath := args[0]
cmd.Println("Uploading dataset:", datasetPath)
+122 -110
View File
@@ -27,120 +27,132 @@ func createTempDatasetFile(content string) (string, error) {
return tmpFile.Name(), nil
}
func TestDatasetsCmd_Success(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Data", mock.Anything, mock.Anything, mock.Anything).Return(nil)
testCLI := New(mockSDK)
func TestDatasetsCmd(t *testing.T) {
tests := []struct {
name string
setupMock func(*mocks.SDK)
setupFiles func() (string, error)
connectErr error
expectedOutput string
cleanup func(string, string)
}{
{
name: "successful upload",
setupMock: func(m *mocks.SDK) {
m.On("Data", mock.Anything, mock.Anything, mock.Anything).Return(nil)
},
setupFiles: func() (string, error) {
datasetFile, err := createTempDatasetFile("test dataset content")
if err != nil {
return "", err
}
err = generateRSAPrivateKeyFile(privateKeyFile)
return datasetFile, err
},
expectedOutput: "Successfully uploaded dataset",
cleanup: func(datasetFile, privateKeyFile string) {
os.Remove(datasetFile)
os.Remove(privateKeyFile)
},
},
{
name: "missing dataset file",
setupMock: func(m *mocks.SDK) {
m.On("Data", mock.Anything, mock.Anything, mock.Anything).Return(nil)
},
setupFiles: func() (string, error) {
return "", nil
},
expectedOutput: "Error reading dataset file",
},
{
name: "missing private key file",
setupMock: func(m *mocks.SDK) {
m.On("Data", mock.Anything, mock.Anything, mock.Anything).Return(nil)
},
setupFiles: func() (string, error) {
return createTempDatasetFile("test dataset content")
},
expectedOutput: "Error reading private key file",
cleanup: func(datasetFile, _ string) {
os.Remove(datasetFile)
},
},
{
name: "upload failure",
setupMock: func(m *mocks.SDK) {
m.On("Data", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("failed to upload algorithm due to error"))
},
setupFiles: func() (string, error) {
datasetFile, err := createTempDatasetFile("test dataset content")
if err != nil {
return "", err
}
err = generateRSAPrivateKeyFile(privateKeyFile)
return datasetFile, err
},
expectedOutput: "Failed to upload dataset due to error",
cleanup: func(datasetFile, privateKeyFile string) {
os.Remove(datasetFile)
os.Remove(privateKeyFile)
},
},
{
name: "invalid private key",
setupMock: func(m *mocks.SDK) {
m.On("Data", mock.Anything, mock.Anything, mock.Anything).Return(nil)
},
setupFiles: func() (string, error) {
datasetFile, err := createTempDatasetFile("test dataset content")
if err != nil {
return "", err
}
err = os.WriteFile(privateKeyFile, []byte("invalid private key"), 0o644)
return datasetFile, err
},
expectedOutput: "Error decoding private key",
cleanup: func(datasetFile, privateKeyFile string) {
os.Remove(datasetFile)
os.Remove(privateKeyFile)
},
},
{
name: "connection error",
setupMock: func(m *mocks.SDK) {
},
setupFiles: func() (string, error) { return "", nil },
connectErr: errors.New("failed to connect to agent"),
expectedOutput: "Failed to connect to agent",
},
}
datasetFile, err := createTempDatasetFile("test dataset content")
require.NoError(t, err)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockSDK := new(mocks.SDK)
if tt.setupMock != nil {
tt.setupMock(mockSDK)
}
err = generateRSAPrivateKeyFile(privateKeyFile)
require.NoError(t, err)
testCLI := CLI{
agentSDK: mockSDK,
connectErr: tt.connectErr,
}
cmd := testCLI.NewDatasetsCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
datasetFile, err := tt.setupFiles()
require.NoError(t, err)
cmd.SetArgs([]string{datasetFile, privateKeyFile})
err = cmd.Execute()
require.NoError(t, err)
cmd := testCLI.NewDatasetsCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{datasetFile, privateKeyFile})
err = cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), "Successfully uploaded dataset")
mockSDK.AssertCalled(t, "Data", mock.Anything, mock.Anything, mock.Anything)
require.Contains(t, buf.String(), tt.expectedOutput)
t.Cleanup(func() {
os.Remove(datasetFile)
os.Remove(privateKeyFile)
})
}
func TestDatasetsCmd_MissingDatasetFile(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Data", mock.Anything, mock.Anything, mock.Anything).Return(nil)
testCLI := New(mockSDK)
cmd := testCLI.NewDatasetsCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{"non_existent_dataset.txt", privateKeyFile})
err := cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), "Error reading dataset file")
}
func TestDatasetsCmd_MissingPrivateKeyFile(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Data", mock.Anything, mock.Anything, mock.Anything).Return(nil)
testCLI := New(mockSDK)
datasetFile, err := createTempDatasetFile("test dataset content")
require.NoError(t, err)
cmd := testCLI.NewDatasetsCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{datasetFile, "non_existent_private_key.pem"})
err = cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), "Error reading private key file")
t.Cleanup(func() {
os.Remove(datasetFile)
})
}
func TestDatasetsCmd_UploadFailure(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Data", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("failed to upload algorithm due to error"))
testCLI := New(mockSDK)
datasetFile, err := createTempDatasetFile("test dataset content")
require.NoError(t, err)
err = generateRSAPrivateKeyFile(privateKeyFile)
require.NoError(t, err)
cmd := testCLI.NewDatasetsCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{datasetFile, privateKeyFile})
err = cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), "Failed to upload dataset due to error")
t.Cleanup(func() {
os.Remove(datasetFile)
os.Remove(privateKeyFile)
})
}
func TestDatasetsCmd_InvalidPrivateKey(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Data", mock.Anything, mock.Anything, mock.Anything).Return(nil)
testCLI := New(mockSDK)
datasetFile, err := createTempDatasetFile("test dataset content")
require.NoError(t, err)
err = os.WriteFile(privateKeyFile, []byte("invalid private key"), 0o644)
require.NoError(t, err)
cmd := testCLI.NewDatasetsCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{datasetFile, privateKeyFile})
err = cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), "Error decoding private key")
t.Cleanup(func() {
os.Remove(datasetFile)
os.Remove(privateKeyFile)
})
if tt.cleanup != nil {
tt.cleanup(datasetFile, privateKeyFile)
}
})
}
}
+5
View File
@@ -23,6 +23,11 @@ func (cli *CLI) NewResultsCmd() *cobra.Command {
Example: "result <private_key_file_path>",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
if cli.connectErr != nil {
printError(cmd, "Failed to connect to agent: %v ❌ ", cli.connectErr)
return
}
cmd.Println("⏳ Retrieving computation result file")
privKeyFile, err := os.ReadFile(args[0])
+112 -102
View File
@@ -18,43 +18,10 @@ import (
const compResult = "Test computation result"
func TestResultsCmd_Success(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Result", mock.Anything, mock.Anything).Return([]byte(compResult), nil)
testCLI := New(mockSDK)
err := generateRSAPrivateKeyFile(privateKeyFile)
require.NoError(t, err)
cmd := testCLI.NewResultsCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{privateKeyFile})
err = cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), "Computation result retrieved and saved successfully")
files, err := filepath.Glob("results*.zip")
require.NoError(t, err)
require.Len(t, files, 1)
resultFile, err := os.ReadFile(files[0])
require.NoError(t, err)
require.Equal(t, compResult, string(resultFile))
t.Cleanup(func() {
for _, file := range files {
os.Remove(file)
}
os.Remove(privateKeyFile)
})
}
func TestResultsCmd_MultipleExecutions(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Result", mock.Anything, mock.Anything).Return([]byte(compResult), nil)
testCLI := New(mockSDK)
testCLI := CLI{agentSDK: mockSDK}
err := generateRSAPrivateKeyFile(privateKeyFile)
require.NoError(t, err)
@@ -83,77 +50,10 @@ func TestResultsCmd_MultipleExecutions(t *testing.T) {
})
}
func TestResultsCmd_MissingPrivateKeyFile(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Result", mock.Anything, mock.Anything).Return([]byte(compResult), nil)
testCLI := New(mockSDK)
cmd := testCLI.NewResultsCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{"non_existent_private_key.pem"})
err := cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), "Error reading private key file")
}
func TestResultsCmd_ResultFailure(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Result", mock.Anything, mock.Anything).Return(nil, errors.New("error retrieving computation result"))
testCLI := New(mockSDK)
err := generateRSAPrivateKeyFile(privateKeyFile)
require.NoError(t, err)
cmd := testCLI.NewResultsCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{privateKeyFile})
err = cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), "error retrieving computation result")
mockSDK.AssertCalled(t, "Result", mock.Anything, mock.Anything)
t.Cleanup(func() {
os.Remove(privateKeyFile)
})
}
func TestResultsCmd_SaveFailure(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Result", mock.Anything, mock.Anything).Return([]byte(compResult), nil)
testCLI := New(mockSDK)
err := generateRSAPrivateKeyFile(privateKeyFile)
require.NoError(t, err)
// Simulate failure in saving the result file by making all files read-only
err = os.Chmod(".", 0o555)
require.NoError(t, err)
cmd := testCLI.NewResultsCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{privateKeyFile})
err = cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), "Error saving computation result file")
mockSDK.AssertCalled(t, "Result", mock.Anything, mock.Anything)
t.Cleanup(func() {
err := os.Chmod(".", 0o755)
require.NoError(t, err)
err = os.Remove(privateKeyFile)
require.NoError(t, err)
})
}
func TestResultsCmd_InvalidPrivateKey(t *testing.T) {
mockSDK := new(mocks.SDK)
mockSDK.On("Result", mock.Anything, mock.Anything).Return([]byte(compResult), nil)
testCLI := New(mockSDK)
testCLI := CLI{agentSDK: mockSDK}
invalidPrivateKey, err := os.CreateTemp("", "invalid_private_key.pem")
require.NoError(t, err)
@@ -198,3 +98,113 @@ func TestGetUniqueFilePath(t *testing.T) {
require.NoError(t, err)
require.Equal(t, "test_3.txt", path)
}
func TestResultsCmd(t *testing.T) {
tests := []struct {
name string
setupMock func(*mocks.SDK)
setupFiles func() (string, error)
connectErr error
expectedOutput string
cleanup func()
}{
{
name: "successful result retrieval",
setupMock: func(m *mocks.SDK) {
m.On("Result", mock.Anything, mock.Anything).Return([]byte(compResult), nil)
},
setupFiles: func() (string, error) {
return privateKeyFile, generateRSAPrivateKeyFile(privateKeyFile)
},
expectedOutput: "Computation result retrieved and saved successfully",
cleanup: func() {
files, _ := filepath.Glob("results*.zip")
for _, file := range files {
os.Remove(file)
}
os.Remove(privateKeyFile)
},
},
{
name: "missing private key file",
setupMock: func(m *mocks.SDK) {
m.On("Result", mock.Anything, mock.Anything).Return([]byte(compResult), nil)
},
setupFiles: func() (string, error) {
return "non_existent_private_key.pem", nil
},
expectedOutput: "Error reading private key file",
},
{
name: "result retrieval failure",
setupMock: func(m *mocks.SDK) {
m.On("Result", mock.Anything, mock.Anything).Return(nil, errors.New("error retrieving computation result"))
},
setupFiles: func() (string, error) {
return privateKeyFile, generateRSAPrivateKeyFile(privateKeyFile)
},
expectedOutput: "error retrieving computation result",
cleanup: func() {
os.Remove(privateKeyFile)
},
},
{
name: "save failure",
setupMock: func(m *mocks.SDK) {
m.On("Result", mock.Anything, mock.Anything).Return([]byte(compResult), nil)
},
setupFiles: func() (string, error) {
err := generateRSAPrivateKeyFile(privateKeyFile)
if err != nil {
return "", err
}
// Simulate failure in saving the result file by making all files read-only
return privateKeyFile, os.Chmod(".", 0o555)
},
expectedOutput: "Error saving computation result file",
cleanup: func() {
err := os.Chmod(".", 0o755)
require.NoError(t, err)
os.Remove(privateKeyFile)
},
},
{
name: "connection error",
setupMock: func(m *mocks.SDK) {
},
setupFiles: func() (string, error) { return "", nil },
connectErr: errors.New("failed to connect to agent"),
expectedOutput: "Failed to connect to agent",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockSDK := new(mocks.SDK)
if tt.setupMock != nil {
tt.setupMock(mockSDK)
}
testCLI := CLI{
agentSDK: mockSDK,
connectErr: tt.connectErr,
}
file, err := tt.setupFiles()
require.NoError(t, err)
cmd := testCLI.NewResultsCmd()
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs([]string{file})
err = cmd.Execute()
require.NoError(t, err)
require.Contains(t, buf.String(), tt.expectedOutput)
if tt.cleanup != nil {
tt.cleanup()
}
})
}
}
+29 -4
View File
@@ -2,16 +2,41 @@
// SPDX-License-Identifier: Apache-2.0
package cli
import "github.com/ultravioletrs/cocos/pkg/sdk"
import (
"context"
"github.com/ultravioletrs/cocos/pkg/clients/grpc"
"github.com/ultravioletrs/cocos/pkg/clients/grpc/agent"
"github.com/ultravioletrs/cocos/pkg/sdk"
)
var Verbose bool
type CLI struct {
agentSDK sdk.SDK
agentSDK sdk.SDK
config grpc.Config
client grpc.Client
connectErr error
}
func New(agentSDK sdk.SDK) *CLI {
func New(config grpc.Config) *CLI {
return &CLI{
agentSDK: agentSDK,
config: config,
}
}
func (c *CLI) InitializeSDK() error {
agentGRPCClient, agentClient, err := agent.NewAgentClient(context.Background(), c.config)
if err != nil {
c.connectErr = err
return err
}
c.client = agentGRPCClient
c.agentSDK = sdk.NewAgentSDK(agentClient)
return nil
}
func (c *CLI) Close() {
c.client.Close()
}
+4 -13
View File
@@ -3,7 +3,6 @@
package main
import (
"context"
"fmt"
"os"
"os/signal"
@@ -16,8 +15,6 @@ import (
"github.com/spf13/pflag"
"github.com/ultravioletrs/cocos/cli"
"github.com/ultravioletrs/cocos/pkg/clients/grpc"
"github.com/ultravioletrs/cocos/pkg/clients/grpc/agent"
"github.com/ultravioletrs/cocos/pkg/sdk"
cmd "github.com/virtee/sev-snp-measure-go/sevsnpmeasure/cmd"
)
@@ -101,17 +98,11 @@ func main() {
return
}
agentGRPCClient, agentClient, err := agent.NewAgentClient(context.Background(), agentGRPCConfig)
if err != nil {
message := color.New(color.FgRed).Sprintf("failed to create %s gRPC client : %s", svcName, err)
rootCmd.Println(message)
return
cliSVC := cli.New(agentGRPCConfig)
if err := cliSVC.InitializeSDK(); err == nil {
defer cliSVC.Close()
}
defer agentGRPCClient.Close()
agentSDK := sdk.NewAgentSDK(agentClient)
cliSVC := cli.New(agentSDK)
rootCmd.PersistentFlags().BoolVarP(&cli.Verbose, "verbose", "v", false, "Enable verbose output")
+1
View File
@@ -4,6 +4,7 @@
coverage:
ignore:
- "test/*"
- "cmd/*"
- "**/mocks/**"
- "mocks/**"
- "**/*.pb.go"
+1 -1
View File
@@ -58,7 +58,7 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-configfs-tsm v0.2.2 // indirect
github.com/google/logger v1.1.1 // indirect
github.com/google/logger v1.1.1
github.com/google/uuid v1.6.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect