Skip to content

Commit

Permalink
correct controller test
Browse files Browse the repository at this point in the history
  • Loading branch information
dmikey committed Jan 11, 2023
1 parent 1ba7ab6 commit a9cbccb
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 88 deletions.
20 changes: 10 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
.phony: all
.PHONY: all
all: clean build

.phony: test
.PHONY: test
test:
@echo "Testing..."
@echo "\n🧪 Testing...\n"
go clean -testcache
go test ./src/...
@echo "Done."
@echo "\n✅ Done.\n"

.phony: build
.PHONY: build
build:
@echo "Building node..."
@echo "\n🛠 Building node...\n"
cd src && go build -o ../dist/b7s
@echo "Done."
@echo "\n✅ Done.\n"

.phony: clean
.PHONY: clean
clean:
@echo "Cleaning..."
@echo "\n🧹 Cleaning...\n"
rm -rf dist
@echo "Done."
@echo "\n✅ Done.\n"

This file was deleted.

146 changes: 146 additions & 0 deletions src/controller/controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package controller

import (
"context"
"encoding/json"
"fmt"
"os/exec"
"strings"
"testing"

"github.com/blocklessnetworking/b7s/src/db"
"github.com/blocklessnetworking/b7s/src/enums"
"github.com/blocklessnetworking/b7s/src/memstore"
"github.com/blocklessnetworking/b7s/src/models"
)

func TestIsFunctionInstalled(t *testing.T) {

// set up a mock function manifest to store in the database
mockManifest := models.FunctionManifest{
Function: models.Function{
ID: "test-function",
Name: "Test Function",
Version: "1.0.0",
Runtime: "go",
},
Deployment: models.Deployment{
Cid: "Qmabcdef",
Checksum: "123456789",
Uri: "https://ipfs.io/ipfs/Qmabcdef",
Methods: []models.Methods{
{
Name: "TestMethod",
Entry: "main.TestMethod",
},
},
},
Runtime: models.Runtime{
Checksum: "987654321",
Url: "https://ipfs.io/ipfs/Qmzyxwvu",
},
}
mockManifestBytes, _ := json.Marshal(mockManifest)

appDb := db.GetDb("/tmp/b7s")
defer db.Close(appDb)
ctx := context.WithValue(context.Background(), "appDb", appDb)

// Insert a test value into the database
db.Set(ctx, "test_key", string(mockManifestBytes))

// Call IsFunctionInstalled
functionManifest, err := IsFunctionInstalled(ctx, "test_key")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}

// Compare the function manifests as strings to account for potential encoding issues
functionManifestBytes, _ := json.Marshal(functionManifest)
expectedManifestBytes, _ := json.Marshal(mockManifest)
if string(functionManifestBytes) != string(expectedManifestBytes) {
t.Errorf("Unexpected function manifest. Got %v, expected %v", functionManifest, mockManifest)
}
}
func TestExecuteFunction(t *testing.T) {
// Create a mock Config value to pass to the context
mockConfig := models.Config{
Protocol: models.ConfigProtocol{
Role: enums.RoleWorker,
},
Node: models.ConfigNode{
WorkspaceRoot: "/tmp/b7s_tests",
},
}
ctx := context.WithValue(context.Background(), "config", mockConfig)
testStringValue := "foo"
testString := fmt.Sprintf("echo %s", testStringValue)
// Inject a mock execCommand function
mockExecCommand := func(command string, args ...string) *exec.Cmd {
cs := []string{"-c", testString}
cmd := exec.Command("bash", cs...)
return cmd
}
ctx = context.WithValue(ctx, "execCommand", mockExecCommand)

// Set up a mock function manifest to store in the database
mockManifest := models.FunctionManifest{
Function: models.Function{
ID: "test-function",
Name: "Test Function",
Version: "1.0.0",
Runtime: "go",
},
Deployment: models.Deployment{
Cid: "Qmabcdef",
Checksum: "123456789",
Uri: "https://ipfs.io/ipfs/Qmabcdef",
Methods: []models.Methods{
{
Name: "TestMethod",
Entry: "main.TestMethod",
},
},
},
Runtime: models.Runtime{
Checksum: "987654321",
Url: "https://ipfs.io/ipfs/Qmzyxwvu",
},
}
mockManifestBytes, _ := json.Marshal(mockManifest)

appDb := db.GetDb("/tmp/b7s")
defer db.Close(appDb)
ctx = context.WithValue(ctx, "appDb", appDb)

// response memstore
executionResponseMemStore := memstore.NewReqRespStore()
ctx = context.WithValue(ctx, "executionResponseMemStore", executionResponseMemStore)

// Insert the mock function manifest into the database
db.Set(ctx, "test-function", string(mockManifestBytes))

// Create a mock RequestExecute value to pass to ExecuteFunction
mockRequest := models.RequestExecute{
FunctionId: "test-function",
Method: "TestMethod",
Parameters: []models.RequestExecuteParameters{
{
Name: "param1",
Value: "value1",
},
},
Config: models.ExecutionRequestConfig{},
}

// Call ExecuteFunction with the mock context and request
response, err := ExecuteFunction(ctx, mockRequest)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}

// Assert that the correct function was called (Worker`Exec`uteFunction in this case)
if strings.Trim(response.Result, "\n") != testStringValue {
t.Errorf("Unexpected response. Got %v, expected %v", response.Result, testStringValue)
}
}
76 changes: 43 additions & 33 deletions src/executor/executor.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// Executor provides functions for running and interacting with functions.
package executor

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"os/exec"
Expand All @@ -15,6 +17,7 @@ import (
log "github.com/sirupsen/logrus"
)

// prepExecutionManifest creates the execution manifest file for the specified function.
func prepExecutionManifest(ctx context.Context, requestId string, request models.RequestExecute, manifest models.FunctionManifest) (string, error) {
config := ctx.Value("config").(models.Config)

Expand Down Expand Up @@ -60,34 +63,42 @@ func queryRuntime(runtimePath string) error {
}
return nil
}

// executes a shell command to execute a wasm file
func Execute(ctx context.Context, request models.RequestExecute, functionManifest models.FunctionManifest) (models.ExecutorResponse, error) {
requestId, _ := uuid.NewRandom()
requestID, _ := uuid.NewRandom()
config := ctx.Value("config").(models.Config)
tempFSPath := filepath.Join(config.Node.WorkspaceRoot, "t", requestId.String(), "fs")
tempFSPath := filepath.Join(config.Node.WorkspaceRoot, "t", requestID.String(), "fs")
os.MkdirAll(tempFSPath, os.ModePerm)

// check to see if runtime is available
err := queryRuntime(config.Node.RuntimePath)
var execCommand func(string, ...string) *exec.Cmd
if ctxExecCommand, ok := ctx.Value("execCommand").(func(string, ...string) *exec.Cmd); ok {
execCommand = ctxExecCommand
} else {
// Check if the runtime is available.
if err := queryRuntime(config.Node.RuntimePath); err != nil {
return models.ExecutorResponse{
Code: enums.ResponseCodeError,
RequestId: requestID.String(),
}, err
}
execCommand = exec.Command
}

// Prepare the execution manifest.
runtimeManifestPath, err := prepExecutionManifest(ctx, requestID.String(), request, functionManifest)
if err != nil {
return models.ExecutorResponse{
Code: enums.ResponseCodeError,
RequestId: requestId.String(),
RequestId: requestID.String(),
}, err
}

runtimeManifestPath, err := prepExecutionManifest(ctx, requestId.String(), request, functionManifest)

var executorResponse models.ExecutorResponse

// check to see if there is any input to pass to the runtime
var input string = ""
var envVars []models.RequestExecuteEnvVars = request.Config.EnvVars
var envVarString string = ""
var envVarKeys string = ""

// Build the input and environment variable strings.
input := ""
if request.Config.Stdin != nil {
input = *request.Config.Stdin
}
envVars := request.Config.EnvVars
envVarString, envVarKeys := "", ""
if len(envVars) > 0 {
for _, envVar := range envVars {
envVarString += envVar.Name + "=\"" + envVar.Value + "\" "
Expand All @@ -97,26 +108,25 @@ func Execute(ctx context.Context, request models.RequestExecute, functionManifes
envVarKeys = envVarKeys[:len(envVarKeys)-1]
}

if request.Config.Stdin != nil {
input = *request.Config.Stdin
}
// Build the command string.
cmd := fmt.Sprintf("echo \"%s\" | %s BLS_LIST_VARS=\"%s\" %s/blockless-cli %s", input, envVarString, envVarKeys, config.Node.RuntimePath, runtimeManifestPath)

cmd := "echo \"" + input + "\" | " + envVarString + " BLS_LIST_VARS=\"" + envVarKeys + "\" " + config.Node.RuntimePath + "/blockless-cli " + runtimeManifestPath
run := exec.Command("bash", "-c", cmd)
// Execute the command.
run := execCommand("bash", "-c", cmd)
run.Dir = tempFSPath
out, err := run.Output()

if err != nil {

log.WithFields(log.Fields{
"err": err,
}).Error("failed to execute request")

return executorResponse, err
log.WithFields(log.Fields{"err": err}).Error("failed to execute request")
return models.ExecutorResponse{
Code: enums.ResponseCodeError,
RequestId: requestID.String(),
}, err
}

// Store the result in the execution response memory store

executionResponseMemStore := ctx.Value("executionResponseMemStore").(memstore.ReqRespStore)
err = executionResponseMemStore.Set(requestId.String(), &models.MsgExecuteResponse{
err = executionResponseMemStore.Set(requestID.String(), &models.MsgExecuteResponse{
Type: enums.MsgExecuteResponse,
Code: enums.ResponseCodeOk,
Result: string(out),
Expand All @@ -129,11 +139,11 @@ func Execute(ctx context.Context, request models.RequestExecute, functionManifes
}

log.WithFields(log.Fields{
"requestId": requestId,
"requestId": requestID,
}).Info("function executed")

executorResponse = models.ExecutorResponse{
RequestId: requestId.String(),
executorResponse := models.ExecutorResponse{
RequestId: requestID.String(),
Code: enums.ResponseCodeOk,
Result: string(out),
}
Expand Down

0 comments on commit a9cbccb

Please sign in to comment.