From 8436dc4e2c8725ddceb6ffc505ca7911752a7120 Mon Sep 17 00:00:00 2001 From: Quint Daenen Date: Mon, 25 Mar 2024 11:40:32 +0100 Subject: [PATCH] Add mgmt canister test. --- agent.go | 7 ++--- agent_test.go | 2 +- ic/dfx.json | 4 +++ ic/ic_test.go | 63 +++++++++++++++++++++++++++++++++++---- ic/testdata/networks.json | 6 +++- logger.go | 4 +-- mock/replica.go | 16 +++++----- 7 files changed, 80 insertions(+), 22 deletions(-) diff --git a/agent.go b/agent.go index e17d71b..c8392b2 100644 --- a/agent.go +++ b/agent.go @@ -136,7 +136,7 @@ func (a Agent) Call(canisterID principal.Principal, methodName string, args []an return err } canisterID = effectiveCanisterID(canisterID, args) - a.logger.Printf("[AGENT] CALL %s %s", canisterID, methodName) + a.logger.Printf("[AGENT] CALL %s %s (%x)", canisterID, methodName, *requestID) if _, err := a.call(canisterID, data); err != nil { return err } @@ -256,7 +256,7 @@ func (a Agent) Query(canisterID principal.Principal, methodName string, args []a // RequestStatus returns the status of the request with the given ID. func (a Agent) RequestStatus(canisterID principal.Principal, requestID RequestID) ([]byte, hashtree.Node, error) { - a.logger.Printf("[AGENT] REQUEST STATUS %s", requestID) + a.logger.Printf("[AGENT] REQUEST STATUS %s %x", canisterID, requestID) path := []hashtree.Label{hashtree.Label("request_status"), requestID[:]} c, err := a.readStateCertificate(canisterID, [][]hashtree.Label{path}) if err != nil { @@ -303,7 +303,7 @@ func (a Agent) poll(canisterID principal.Principal, requestID RequestID, delay, for { select { case <-ticker.C: - a.logger.Printf("[AGENT] POLL %s", requestID) + a.logger.Printf("[AGENT] POLL %s %x", canisterID, requestID) data, node, err := a.RequestStatus(canisterID, requestID) if err != nil { return nil, err @@ -323,7 +323,6 @@ func (a Agent) poll(canisterID principal.Principal, requestID RequestID, delay, } return nil, fmt.Errorf("(%d) %s", uint64FromBytes(code), string(message)) case "replied": - fmt.Println(node) replied, err := hashtree.NewHashTree(node).Lookup(append(path, hashtree.Label("reply"))...) if err != nil { return nil, fmt.Errorf("no reply found") diff --git a/agent_test.go b/agent_test.go index 37f2068..25a8b67 100644 --- a/agent_test.go +++ b/agent_test.go @@ -186,6 +186,6 @@ func TestICPLedger_queryBlocks(t *testing.T) { type testLogger struct{} -func (t testLogger) Printf(format string, v ...interface{}) { +func (t testLogger) Printf(format string, v ...any) { fmt.Printf("[TEST]"+format+"\n", v...) } diff --git a/ic/dfx.json b/ic/dfx.json index 97d0c02..230265d 100644 --- a/ic/dfx.json +++ b/ic/dfx.json @@ -3,6 +3,10 @@ "assetstorage": { "type": "motoko", "main": "assetstorage/actor.mo" + }, + "ic0": { + "type": "motoko", + "main": "ic/actor.mo" } } } diff --git a/ic/ic_test.go b/ic/ic_test.go index eb213ae..2aaba40 100644 --- a/ic/ic_test.go +++ b/ic/ic_test.go @@ -4,7 +4,9 @@ import ( "encoding/json" "fmt" "github.com/aviate-labs/agent-go" + "github.com/aviate-labs/agent-go/ic" "github.com/aviate-labs/agent-go/ic/assetstorage" + ic0 "github.com/aviate-labs/agent-go/ic/ic" "github.com/aviate-labs/agent-go/principal" "net/url" "os" @@ -19,11 +21,11 @@ func TestModules(t *testing.T) { if err != nil { t.Skip(err) } - var networksConfig map[string]map[string]string + var networksConfig networkConfig if err := json.Unmarshal(rawNetworksConfig, &networksConfig); err != nil { t.Fatal(err) } - host, err := url.Parse(fmt.Sprintf("http://%s", networksConfig["local"]["bind"])) + host, err := url.Parse(fmt.Sprintf("http://%s", networksConfig.Local.Bind)) if err != nil { t.Fatal(err) } @@ -60,12 +62,15 @@ func TestModules(t *testing.T) { t.Fatal(err) } + config := agent.Config{ + ClientConfig: &agent.ClientConfig{Host: host}, + FetchRootKey: true, + Logger: new(localLogger), + } + t.Run("assetstorage", func(t *testing.T) { cId, _ := principal.Decode(m["assetstorage"]["local"]) - a, err := assetstorage.NewAgent(cId, agent.Config{ - ClientConfig: &agent.ClientConfig{Host: host}, - FetchRootKey: true, - }) + a, err := assetstorage.NewAgent(cId, config) if err != nil { t.Fatal(err) } @@ -73,6 +78,40 @@ func TestModules(t *testing.T) { t.Error(err) } }) + + t.Run("management canister", func(t *testing.T) { + controller := principal.AnonymousID + addController := exec.Command(dfxPath, "canister", "update-settings", "--add-controller", controller.String(), "ic0") + if out, err := addController.CombinedOutput(); err != nil { + t.Fatal(sanitizeOutput(out)) + } + + getContollers := exec.Command(dfxPath, "canister", "info", "ic0") + out, err := getContollers.CombinedOutput() + if err != nil { + t.Fatal(sanitizeOutput(out)) + } + if !strings.Contains(string(out), controller.String()) { + t.Error("controller not added") + } + + cId, _ := principal.Decode(m["ic0"]["local"]) + a, err := ic0.NewAgent(ic.MANAGEMENT_CANISTER_PRINCIPAL, config) + if err != nil { + t.Fatal(err) + } + + if err := a.UpdateSettings(ic0.UpdateSettingsArgs{ + CanisterId: cId, + Settings: ic0.CanisterSettings{ + Controllers: &[]principal.Principal{ + principal.AnonymousID, + }, + }, + }); err != nil { + t.Error(err) + } + }) } func sanitizeOutput(out []byte) string { @@ -83,3 +122,15 @@ func sanitizeOutput(out []byte) string { } return s } + +type localLogger struct{} + +func (l localLogger) Printf(format string, v ...any) { + fmt.Printf("[LOCAL]"+format+"\n", v...) +} + +type networkConfig struct { + Local struct { + Bind string `json:"bind"` + } `json:"local"` +} diff --git a/ic/testdata/networks.json b/ic/testdata/networks.json index 5a407fc..0b6b072 100644 --- a/ic/testdata/networks.json +++ b/ic/testdata/networks.json @@ -1,5 +1,9 @@ { "local": { - "bind": "127.0.0.1:8080" + "bind": "127.0.0.1:8080", + "type": "ephemeral", + "replica": { + "subnet_type": "system" + } } } diff --git a/logger.go b/logger.go index dc339c0..c713f50 100644 --- a/logger.go +++ b/logger.go @@ -1,9 +1,9 @@ package agent type Logger interface { - Printf(format string, v ...interface{}) + Printf(format string, v ...any) } type defaultLogger struct{} -func (l defaultLogger) Printf(format string, v ...interface{}) {} +func (l defaultLogger) Printf(format string, v ...any) {} diff --git a/mock/replica.go b/mock/replica.go index 408ec7e..63441f2 100644 --- a/mock/replica.go +++ b/mock/replica.go @@ -108,9 +108,9 @@ func (r *Replica) handleCanister(writer http.ResponseWriter, canisterId, typ str _, _ = writer.Write([]byte("expected call request")) return } - requestId := agent.NewRequestID(req) - requestIdHex := hex.EncodeToString(requestId[:]) - r.Requests[requestIdHex] = req + requestID := agent.NewRequestID(req) + requestIDHex := hex.EncodeToString(requestID[:]) + r.Requests[requestIDHex] = req writer.WriteHeader(http.StatusAccepted) case "query": if req.Type != agent.RequestTypeQuery { @@ -161,12 +161,12 @@ func (r *Replica) handleCanister(writer http.ResponseWriter, canisterId, typ str _, _ = writer.Write([]byte("expected request_status")) return } - requestId := req.Paths[0][1] - requestIdHex := hex.EncodeToString(requestId) - req, ok := r.Requests[requestIdHex] + requestID := req.Paths[0][1] + requestIDHex := hex.EncodeToString(requestID) + req, ok := r.Requests[requestIDHex] if !ok { writer.WriteHeader(http.StatusNotFound) - _, _ = writer.Write([]byte("request not found: " + requestIdHex)) + _, _ = writer.Write([]byte("request not found: " + requestIDHex)) return } @@ -195,7 +195,7 @@ func (r *Replica) handleCanister(writer http.ResponseWriter, canisterId, typ str LeftTree: hashtree.Labeled{ Label: []byte("request_status"), Tree: hashtree.Labeled{ - Label: requestId, + Label: requestID, Tree: hashtree.Fork{ LeftTree: hashtree.Labeled{ Label: []byte("reply"),