From 1acd8d8c6e1e1c775b3db5ba467d8ae1fb19543e Mon Sep 17 00:00:00 2001 From: Igor Sirotin Date: Thu, 19 Sep 2024 15:54:44 +0100 Subject: [PATCH] chore_: test, improvements --- cmd/statusd/server/endpoints.go | 131 +++++++++--------- .../server/parse-api/endpoints_template.txt | 11 +- cmd/statusd/server/signals_server.go | 57 +++----- cmd/statusd/server/signals_server_test.go | 82 +++++++++-- 4 files changed, 167 insertions(+), 114 deletions(-) diff --git a/cmd/statusd/server/endpoints.go b/cmd/statusd/server/endpoints.go index 30dbc4d81..baa193f06 100644 --- a/cmd/statusd/server/endpoints.go +++ b/cmd/statusd/server/endpoints.go @@ -1,73 +1,76 @@ +// Code generated by parse-api/main.go. DO NOT EDIT. +// source: parse-api/main.go + package server import statusgo "github.com/status-im/status-go/mobile" -var EndpointsWithResponse = []func(string) string{ - statusgo.InitializeApplication, - statusgo.ExtractGroupMembershipSignatures, - statusgo.SignGroupMembership, - statusgo.ValidateNodeConfig, - statusgo.CallRPC, - statusgo.CallPrivateRPC, - statusgo.CreateAccountAndLogin, - statusgo.LoginAccount, - statusgo.RestoreAccountAndLogin, - statusgo.InitKeystore, - statusgo.SignMessage, - statusgo.HashTypedData, - statusgo.HashTypedDataV4, - statusgo.Recover, - statusgo.HashTransaction, - statusgo.HashMessage, - statusgo.StartCPUProfile, - statusgo.WriteHeapProfile, - statusgo.AddPeer, - statusgo.SignHash, - statusgo.GenerateAlias, - statusgo.IsAlias, - statusgo.Identicon, - statusgo.EmojiHash, - statusgo.ColorHash, - statusgo.ColorID, - statusgo.ValidateMnemonic, - statusgo.DecompressPublicKey, - statusgo.CompressPublicKey, - statusgo.SerializeLegacyKey, - statusgo.GetPasswordStrength, - statusgo.GetPasswordStrengthScore, - statusgo.GetConnectionStringForBeingBootstrapped, - statusgo.GetConnectionStringForBootstrappingAnotherDevice, - statusgo.GetConnectionStringForExportingKeypairsKeystores, - statusgo.ValidateConnectionString, - statusgo.DecodeParameters, - statusgo.HexToNumber, - statusgo.NumberToHex, - statusgo.Sha3, - statusgo.Utf8ToHex, - statusgo.HexToUtf8, - statusgo.CheckAddressChecksum, - statusgo.IsAddress, - statusgo.ToChecksumAddress, - statusgo.DeserializeAndCompressKey, - statusgo.InitLogging, - statusgo.ToggleCentralizedMetrics, - statusgo.AddCentralizedMetric, +var EndpointsWithResponse = map[string]func(string) string{ + "/statusgo/InitializeApplication": statusgo.InitializeApplication, + "/statusgo/ExtractGroupMembershipSignatures": statusgo.ExtractGroupMembershipSignatures, + "/statusgo/SignGroupMembership": statusgo.SignGroupMembership, + "/statusgo/ValidateNodeConfig": statusgo.ValidateNodeConfig, + "/statusgo/CallRPC": statusgo.CallRPC, + "/statusgo/CallPrivateRPC": statusgo.CallPrivateRPC, + "/statusgo/CreateAccountAndLogin": statusgo.CreateAccountAndLogin, + "/statusgo/LoginAccount": statusgo.LoginAccount, + "/statusgo/RestoreAccountAndLogin": statusgo.RestoreAccountAndLogin, + "/statusgo/InitKeystore": statusgo.InitKeystore, + "/statusgo/SignMessage": statusgo.SignMessage, + "/statusgo/HashTypedData": statusgo.HashTypedData, + "/statusgo/HashTypedDataV4": statusgo.HashTypedDataV4, + "/statusgo/Recover": statusgo.Recover, + "/statusgo/HashTransaction": statusgo.HashTransaction, + "/statusgo/HashMessage": statusgo.HashMessage, + "/statusgo/StartCPUProfile": statusgo.StartCPUProfile, + "/statusgo/WriteHeapProfile": statusgo.WriteHeapProfile, + "/statusgo/AddPeer": statusgo.AddPeer, + "/statusgo/SignHash": statusgo.SignHash, + "/statusgo/GenerateAlias": statusgo.GenerateAlias, + "/statusgo/IsAlias": statusgo.IsAlias, + "/statusgo/Identicon": statusgo.Identicon, + "/statusgo/EmojiHash": statusgo.EmojiHash, + "/statusgo/ColorHash": statusgo.ColorHash, + "/statusgo/ColorID": statusgo.ColorID, + "/statusgo/ValidateMnemonic": statusgo.ValidateMnemonic, + "/statusgo/DecompressPublicKey": statusgo.DecompressPublicKey, + "/statusgo/CompressPublicKey": statusgo.CompressPublicKey, + "/statusgo/SerializeLegacyKey": statusgo.SerializeLegacyKey, + "/statusgo/GetPasswordStrength": statusgo.GetPasswordStrength, + "/statusgo/GetPasswordStrengthScore": statusgo.GetPasswordStrengthScore, + "/statusgo/GetConnectionStringForBeingBootstrapped": statusgo.GetConnectionStringForBeingBootstrapped, + "/statusgo/GetConnectionStringForBootstrappingAnotherDevice": statusgo.GetConnectionStringForBootstrappingAnotherDevice, + "/statusgo/GetConnectionStringForExportingKeypairsKeystores": statusgo.GetConnectionStringForExportingKeypairsKeystores, + "/statusgo/ValidateConnectionString": statusgo.ValidateConnectionString, + "/statusgo/DecodeParameters": statusgo.DecodeParameters, + "/statusgo/HexToNumber": statusgo.HexToNumber, + "/statusgo/NumberToHex": statusgo.NumberToHex, + "/statusgo/Sha3": statusgo.Sha3, + "/statusgo/Utf8ToHex": statusgo.Utf8ToHex, + "/statusgo/HexToUtf8": statusgo.HexToUtf8, + "/statusgo/CheckAddressChecksum": statusgo.CheckAddressChecksum, + "/statusgo/IsAddress": statusgo.IsAddress, + "/statusgo/ToChecksumAddress": statusgo.ToChecksumAddress, + "/statusgo/DeserializeAndCompressKey": statusgo.DeserializeAndCompressKey, + "/statusgo/InitLogging": statusgo.InitLogging, + "/statusgo/ToggleCentralizedMetrics": statusgo.ToggleCentralizedMetrics, + "/statusgo/AddCentralizedMetric": statusgo.AddCentralizedMetric, } -var EndpointsNoRequest = []func() string{ - statusgo.GetNodeConfig, - statusgo.ResetChainData, - statusgo.Logout, - statusgo.StopCPUProfiling, - statusgo.StartLocalNotifications, - statusgo.StopLocalNotifications, - statusgo.ExportNodeLogs, - statusgo.ImageServerTLSCert, - statusgo.Fleets, - statusgo.LocalPairingPreflightOutboundCheck, - statusgo.StartSearchForLocalPairingPeers, - statusgo.GetRandomMnemonic, - statusgo.CentralizedMetricsInfo, +var EndpointsNoRequest = map[string]func() string{ + "/statusgo/GetNodeConfig": statusgo.GetNodeConfig, + "/statusgo/ResetChainData": statusgo.ResetChainData, + "/statusgo/Logout": statusgo.Logout, + "/statusgo/StopCPUProfiling": statusgo.StopCPUProfiling, + "/statusgo/StartLocalNotifications": statusgo.StartLocalNotifications, + "/statusgo/StopLocalNotifications": statusgo.StopLocalNotifications, + "/statusgo/ExportNodeLogs": statusgo.ExportNodeLogs, + "/statusgo/ImageServerTLSCert": statusgo.ImageServerTLSCert, + "/statusgo/Fleets": statusgo.Fleets, + "/statusgo/LocalPairingPreflightOutboundCheck": statusgo.LocalPairingPreflightOutboundCheck, + "/statusgo/StartSearchForLocalPairingPeers": statusgo.StartSearchForLocalPairingPeers, + "/statusgo/GetRandomMnemonic": statusgo.GetRandomMnemonic, + "/statusgo/CentralizedMetricsInfo": statusgo.CentralizedMetricsInfo, } var EndpointsUnsupported = []string{ diff --git a/cmd/statusd/server/parse-api/endpoints_template.txt b/cmd/statusd/server/parse-api/endpoints_template.txt index 99e8c4713..019b5801b 100644 --- a/cmd/statusd/server/parse-api/endpoints_template.txt +++ b/cmd/statusd/server/parse-api/endpoints_template.txt @@ -1,16 +1,19 @@ +// Code generated by parse-api/main.go. DO NOT EDIT. +// source: parse-api/main.go + package server import statusgo "github.com/status-im/status-go/mobile" -var EndpointsWithResponse = []func(string) string{ +var EndpointsWithResponse = map[string]func(string) string{ {{- range .FunctionsWithResp }} - {{ $.PackageName }}.{{ . }}, + "/{{ $.PackageName }}/{{ . }}": {{ $.PackageName }}.{{ . }}, {{- end }} } -var EndpointsNoRequest = []func() string{ +var EndpointsNoRequest = map[string]func() string{ {{- range .FunctionsNoArgs }} - {{ $.PackageName }}.{{ . }}, + "/{{ $.PackageName }}/{{ . }}": {{ $.PackageName }}.{{ . }}, {{- end }} } diff --git a/cmd/statusd/server/signals_server.go b/cmd/statusd/server/signals_server.go index a20e28842..6330b691d 100644 --- a/cmd/statusd/server/signals_server.go +++ b/cmd/statusd/server/signals_server.go @@ -3,13 +3,10 @@ package server import ( "context" "errors" - "fmt" "io" "net" "net/http" - "reflect" - "runtime" - "strings" + "strconv" "sync" "time" @@ -39,6 +36,14 @@ func (s *Server) Address() string { return s.address } +func (s *Server) Port() (int, error) { + _, portString, err := net.SplitHostPort(s.address) + if err != nil { + return 0, err + } + return strconv.Atoi(portString) +} + func (s *Server) Setup() { signal.SetMobileSignalHandler(s.signalHandler) } @@ -124,10 +129,9 @@ func (s *Server) signals(w http.ResponseWriter, r *http.Request) { s.connections[connection] = struct{}{} } -func (s *Server) addEndpointWithResponse(handler func(string) string) { - endpoint := endpointName(functionName(handler)) - log.Debug("adding endpoint", "name", endpoint) - s.mux.HandleFunc(endpoint, func(w http.ResponseWriter, r *http.Request) { +func (s *Server) addEndpointWithResponse(name string, handler func(string) string) { + log.Info("adding endpoint", "name", name) + s.mux.HandleFunc(name, func(w http.ResponseWriter, r *http.Request) { request, err := io.ReadAll(r.Body) if err != nil { log.Error("failed to read request: %w", err) @@ -143,10 +147,9 @@ func (s *Server) addEndpointWithResponse(handler func(string) string) { }) } -func (s *Server) addEndpointNoRequest(handler func() string) { - endpoint := endpointName(functionName(handler)) - log.Debug("adding endpoint", "name", endpoint) - s.mux.HandleFunc(endpoint, func(w http.ResponseWriter, r *http.Request) { +func (s *Server) addEndpointNoRequest(name string, handler func() string) { + log.Debug("adding endpoint", "name", name) + s.mux.HandleFunc(name, func(w http.ResponseWriter, r *http.Request) { response := handler() _, err := w.Write([]byte(response)) @@ -157,34 +160,20 @@ func (s *Server) addEndpointNoRequest(handler func() string) { } func (s *Server) addUnsupportedEndpoint(name string) { - endpoint := endpointName(name) - log.Debug("marking unsupported endpoint", "name", endpoint) - s.mux.HandleFunc(endpoint, func(w http.ResponseWriter, r *http.Request) { + log.Debug("marking unsupported endpoint", "name", name) + s.mux.HandleFunc(name, func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotImplemented) }) } func (s *Server) RegisterMobileAPI() { - for _, endpoint := range EndpointsWithResponse { - s.addEndpointWithResponse(endpoint) + for name, endpoint := range EndpointsWithResponse { + s.addEndpointWithResponse(name, endpoint) } - for _, endpoint := range EndpointsNoRequest { - s.addEndpointNoRequest(endpoint) + for name, endpoint := range EndpointsNoRequest { + s.addEndpointNoRequest(name, endpoint) } - for _, endpoint := range EndpointsUnsupported { - s.addUnsupportedEndpoint(endpoint) + for _, name := range EndpointsUnsupported { + s.addUnsupportedEndpoint(name) } } - -func functionName(fn any) string { - fullName := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name() - parts := strings.Split(fullName, "/") - lastPart := parts[len(parts)-1] - nameParts := strings.Split(lastPart, ".") - return nameParts[len(nameParts)-1] -} - -func endpointName(functionName string) string { - const base = "statusgo" - return fmt.Sprintf("/%s/%s", base, functionName) -} diff --git a/cmd/statusd/server/signals_server_test.go b/cmd/statusd/server/signals_server_test.go index fbc5ff784..742db6f3c 100644 --- a/cmd/statusd/server/signals_server_test.go +++ b/cmd/statusd/server/signals_server_test.go @@ -1,9 +1,12 @@ package server import ( + "bytes" "context" "encoding/json" "fmt" + "io" + "net/http" "net/url" "testing" "time" @@ -16,24 +19,37 @@ import ( "github.com/status-im/status-go/signal" ) -func TestSignalsServer(t *testing.T) { - server := NewServer() - server.Setup() - err := server.Listen("localhost:0") +func setupServer(t *testing.T) (*Server, string) { + srv := NewServer() + srv.Setup() + err := srv.Listen("localhost:0") require.NoError(t, err) - defer func() { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - server.Stop(ctx) - }() - addr := server.Address() - serverURLString := fmt.Sprintf("ws://%s", addr) + addr := srv.Address() + + // Check URL + serverURLString := fmt.Sprintf("http://%s", addr) serverURL, err := url.Parse(serverURLString) require.NoError(t, err) + require.NotNil(t, serverURL) require.NotZero(t, serverURL.Port()) - connection, _, err := websocket.DefaultDialer.Dial(serverURLString+"/signals", nil) + return srv, addr +} + +func shutdownServer(srv *Server) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + srv.Stop(ctx) +} + +func TestSignals(t *testing.T) { + srv, serverURLString := setupServer(t) + go srv.Serve() + defer shutdownServer(srv) + + signalsURL := fmt.Sprintf("ws://%s/signals", serverURLString) + connection, _, err := websocket.DefaultDialer.Dial(signalsURL, nil) require.NoError(t, err) require.NotNil(t, connection) defer func() { @@ -68,6 +84,48 @@ func TestSignalsServer(t *testing.T) { require.Equal(t, sentEvent, receivedEvent) } +func TestMobileAPI(t *testing.T) { + const method = "/echo" + randomResponsePostfix := randomAlphabeticalString(t, 5) + + endpointsWithResponse := EndpointsWithResponse + endpointsNoRequest := EndpointsNoRequest + endpointsUnsupported := EndpointsUnsupported + t.Cleanup(func() { + EndpointsWithResponse = endpointsWithResponse + EndpointsNoRequest = endpointsNoRequest + EndpointsUnsupported = endpointsUnsupported + }) + + EndpointsWithResponse = map[string]func(string) string{ + method: func(request string) string { + return request + randomResponsePostfix + }, + } + + srv, _ := setupServer(t) + defer shutdownServer(srv) + go srv.Serve() + srv.RegisterMobileAPI() + + requestBody := []byte(randomAlphabeticalString(t, 5)) + bodyReader := bytes.NewReader(requestBody) + + port, err := srv.Port() + require.NoError(t, err) + + requestURL := fmt.Sprintf("http://127.0.0.1:%d%s", port, method) + + resp, err := http.Post(requestURL, "application/text", bodyReader) + require.NoError(t, err) + require.NotNil(t, resp) + + responseBody, err := io.ReadAll(resp.Body) + require.NoError(t, err) + require.Equal(t, 200, resp.StatusCode) + require.Equal(t, string(requestBody)+randomResponsePostfix, string(responseBody)) +} + func randomAlphabeticalString(t *testing.T, n int) string { s, err := common.RandomAlphabeticalString(n) require.NoError(t, err)