2023-06-25 20:20:59 -06:00
|
|
|
package graphvent
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
2023-06-25 22:19:05 -06:00
|
|
|
"time"
|
2023-07-29 11:03:41 -06:00
|
|
|
"fmt"
|
|
|
|
"encoding/json"
|
2023-08-11 13:01:32 -06:00
|
|
|
"encoding/base64"
|
2023-07-29 11:03:41 -06:00
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"net"
|
|
|
|
"crypto/tls"
|
2023-08-01 14:09:29 -06:00
|
|
|
"crypto/x509"
|
2023-08-10 23:43:10 -06:00
|
|
|
"crypto/rand"
|
|
|
|
"crypto/ed25519"
|
2023-07-29 11:03:41 -06:00
|
|
|
"bytes"
|
2023-08-15 18:23:06 -06:00
|
|
|
"golang.org/x/net/websocket"
|
|
|
|
"github.com/google/uuid"
|
2023-06-25 20:20:59 -06:00
|
|
|
)
|
|
|
|
|
2023-08-07 20:44:56 -06:00
|
|
|
func TestGQLServer(t *testing.T) {
|
2023-08-15 18:23:06 -06:00
|
|
|
ctx := logTestContext(t, []string{"test", "gql", "policy", "pending"})
|
2023-07-29 00:40:18 -06:00
|
|
|
|
|
|
|
TestNodeType := NodeType("TEST")
|
2023-08-07 20:26:02 -06:00
|
|
|
err := ctx.RegisterNodeType(TestNodeType, []ExtType{LockableExtType})
|
2023-07-29 00:40:18 -06:00
|
|
|
fatalErr(t, err)
|
|
|
|
|
2023-08-10 23:43:10 -06:00
|
|
|
pub, gql_key, err := ed25519.GenerateKey(rand.Reader)
|
|
|
|
fatalErr(t, err)
|
|
|
|
gql_id := KeyID(pub)
|
|
|
|
|
|
|
|
group_policy_1 := NewAllNodesPolicy(Tree{
|
|
|
|
ReadSignalType.String(): Tree{
|
|
|
|
GroupExtType.String(): Tree{
|
|
|
|
"members": Tree{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ReadResultSignalType.String(): nil,
|
|
|
|
ErrorSignalType.String(): nil,
|
|
|
|
})
|
|
|
|
|
2023-08-11 16:00:36 -06:00
|
|
|
group_policy_2 := NewMemberOfPolicy(map[NodeID]Tree{
|
2023-08-10 23:43:10 -06:00
|
|
|
gql_id: Tree{
|
|
|
|
LinkSignalType.String(): nil,
|
|
|
|
LockSignalType.String(): nil,
|
|
|
|
StatusSignalType.String(): nil,
|
|
|
|
ReadSignalType.String(): nil,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
user_policy_1 := NewAllNodesPolicy(Tree{
|
|
|
|
ReadResultSignalType.String(): nil,
|
|
|
|
ErrorSignalType.String(): nil,
|
|
|
|
})
|
|
|
|
|
2023-08-11 16:00:36 -06:00
|
|
|
user_policy_2 := NewMemberOfPolicy(map[NodeID]Tree{
|
2023-08-10 23:43:10 -06:00
|
|
|
gql_id: Tree{
|
|
|
|
LinkSignalType.String(): nil,
|
|
|
|
ReadSignalType.String(): nil,
|
|
|
|
},
|
2023-08-08 14:00:17 -06:00
|
|
|
})
|
|
|
|
|
2023-08-15 18:23:06 -06:00
|
|
|
gql_ext, err := NewGQLExt(ctx, ":0", nil, nil)
|
2023-07-29 00:40:18 -06:00
|
|
|
fatalErr(t, err)
|
2023-08-10 23:43:10 -06:00
|
|
|
|
2023-07-29 00:40:18 -06:00
|
|
|
listener_ext := NewListenerExt(10)
|
2023-08-08 14:00:17 -06:00
|
|
|
n1 := NewNode(ctx, nil, TestNodeType, 10, map[PolicyType]Policy{
|
2023-08-10 23:43:10 -06:00
|
|
|
MemberOfPolicyType: &user_policy_2,
|
|
|
|
AllNodesPolicyType: &user_policy_1,
|
2023-08-11 13:01:32 -06:00
|
|
|
}, NewLockableExt(nil))
|
2023-08-08 14:00:17 -06:00
|
|
|
|
2023-08-10 23:43:10 -06:00
|
|
|
gql := NewNode(ctx, gql_key, GQLNodeType, 10, map[PolicyType]Policy{
|
|
|
|
MemberOfPolicyType: &group_policy_2,
|
|
|
|
AllNodesPolicyType: &group_policy_1,
|
2023-08-11 13:01:32 -06:00
|
|
|
}, NewLockableExt([]NodeID{n1.ID}), gql_ext, NewGroupExt(map[NodeID]string{
|
2023-08-10 23:43:10 -06:00
|
|
|
n1.ID: "user",
|
|
|
|
gql_id: "self",
|
|
|
|
}), listener_ext)
|
|
|
|
|
|
|
|
ctx.Log.Logf("test", "GQL: %s", gql.ID)
|
|
|
|
ctx.Log.Logf("test", "NODE: %s", n1.ID)
|
|
|
|
|
2023-08-12 11:26:19 -06:00
|
|
|
_, err = WaitForSignal(listener_ext.Chan, 100*time.Millisecond, StatusSignalType, func(sig *IDStringSignal) bool {
|
2023-07-30 23:42:47 -06:00
|
|
|
return sig.Str == "server_started"
|
2023-07-29 00:40:18 -06:00
|
|
|
})
|
|
|
|
fatalErr(t, err)
|
2023-07-29 11:03:41 -06:00
|
|
|
|
|
|
|
skipVerifyTransport := &http.Transport{
|
|
|
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
|
|
}
|
|
|
|
client := &http.Client{Transport: skipVerifyTransport}
|
|
|
|
port := gql_ext.tcp_listener.Addr().(*net.TCPAddr).Port
|
|
|
|
url := fmt.Sprintf("https://localhost:%d/gql", port)
|
2023-08-15 18:23:06 -06:00
|
|
|
ws_url := fmt.Sprintf("wss://127.0.0.1:%d/gqlws", port)
|
2023-07-29 11:03:41 -06:00
|
|
|
|
2023-07-29 16:34:21 -06:00
|
|
|
req_1 := GQLPayload{
|
2023-07-29 16:00:01 -06:00
|
|
|
Query: "query Node($id:String) { Node(id:$id) { ID, TypeHash } }",
|
|
|
|
Variables: map[string]interface{}{
|
|
|
|
"id": n1.ID.String(),
|
|
|
|
},
|
2023-07-29 16:34:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
req_2 := GQLPayload{
|
2023-08-11 13:01:32 -06:00
|
|
|
Query: "query Node($id:String) { Node(id:$id) { ID, TypeHash, ... on GQLServer { Members { ID } , Listen, Requirements { ID, TypeHash Owner { ID } } } } }",
|
2023-07-29 16:34:21 -06:00
|
|
|
Variables: map[string]interface{}{
|
|
|
|
"id": gql.ID.String(),
|
|
|
|
},
|
|
|
|
}
|
2023-07-29 11:03:41 -06:00
|
|
|
|
2023-08-15 18:23:06 -06:00
|
|
|
auth_username := base64.StdEncoding.EncodeToString(n1.ID.Serialize())
|
|
|
|
key_bytes, err := x509.MarshalPKCS8PrivateKey(n1.Key)
|
|
|
|
fatalErr(t, err)
|
|
|
|
auth_password := base64.StdEncoding.EncodeToString(key_bytes)
|
|
|
|
auth_b64 := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", auth_username, auth_password)))
|
|
|
|
|
2023-07-29 16:34:21 -06:00
|
|
|
SendGQL := func(payload GQLPayload) []byte {
|
|
|
|
ser, err := json.MarshalIndent(&payload, "", " ")
|
|
|
|
fatalErr(t, err)
|
2023-07-29 11:03:41 -06:00
|
|
|
|
2023-07-29 16:34:21 -06:00
|
|
|
req_data := bytes.NewBuffer(ser)
|
|
|
|
req, err := http.NewRequest("GET", url, req_data)
|
|
|
|
fatalErr(t, err)
|
2023-07-29 11:03:41 -06:00
|
|
|
|
2023-08-15 18:23:06 -06:00
|
|
|
req.SetBasicAuth(auth_username, auth_password)
|
2023-07-29 16:34:21 -06:00
|
|
|
resp, err := client.Do(req)
|
|
|
|
fatalErr(t, err)
|
2023-07-29 11:03:41 -06:00
|
|
|
|
2023-07-29 16:34:21 -06:00
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
|
|
fatalErr(t, err)
|
2023-07-29 11:03:41 -06:00
|
|
|
|
2023-07-29 16:34:21 -06:00
|
|
|
resp.Body.Close()
|
|
|
|
return body
|
|
|
|
}
|
2023-07-29 11:03:41 -06:00
|
|
|
|
2023-07-29 16:34:21 -06:00
|
|
|
resp_1 := SendGQL(req_1)
|
|
|
|
ctx.Log.Logf("test", "RESP_1: %s", resp_1)
|
|
|
|
resp_2 := SendGQL(req_2)
|
|
|
|
ctx.Log.Logf("test", "RESP_2: %s", resp_2)
|
2023-07-29 11:03:41 -06:00
|
|
|
|
2023-08-15 18:23:06 -06:00
|
|
|
sub_1 := GQLPayload{
|
|
|
|
Query: "subscription { Self }",
|
|
|
|
}
|
|
|
|
|
|
|
|
SubGQL := func(payload GQLPayload) {
|
|
|
|
config, err := websocket.NewConfig(ws_url, url)
|
|
|
|
fatalErr(t, err)
|
|
|
|
config.Protocol = append(config.Protocol, "graphql-ws")
|
|
|
|
config.TlsConfig = &tls.Config{InsecureSkipVerify: true}
|
|
|
|
config.Header.Add("Authorization", fmt.Sprintf("Basic %s", auth_b64))
|
|
|
|
|
|
|
|
ws, err := websocket.DialConfig(config)
|
|
|
|
|
|
|
|
fatalErr(t, err)
|
|
|
|
|
|
|
|
init := GQLWSMsg{
|
|
|
|
ID: uuid.New().String(),
|
|
|
|
Type: "connection_init",
|
|
|
|
}
|
|
|
|
|
|
|
|
ser, err := json.Marshal(&init)
|
|
|
|
fatalErr(t, err)
|
|
|
|
|
|
|
|
_, err = ws.Write(ser)
|
|
|
|
fatalErr(t, err)
|
|
|
|
|
|
|
|
resp := make([]byte, 1024)
|
|
|
|
n, err := ws.Read(resp)
|
|
|
|
|
|
|
|
var init_resp GQLWSMsg
|
|
|
|
err = json.Unmarshal(resp[:n], &init_resp)
|
|
|
|
fatalErr(t, err)
|
|
|
|
|
|
|
|
if init_resp.Type != "connection_ack" {
|
|
|
|
t.Fatal("Didn't receive connection_ack")
|
|
|
|
}
|
|
|
|
|
|
|
|
sub := GQLWSMsg{
|
|
|
|
ID: uuid.New().String(),
|
|
|
|
Type: "subscribe",
|
|
|
|
Payload: sub_1,
|
|
|
|
}
|
|
|
|
|
|
|
|
ser, err = json.Marshal(&sub)
|
|
|
|
fatalErr(t, err)
|
|
|
|
_, err = ws.Write(ser)
|
|
|
|
fatalErr(t, err)
|
|
|
|
|
|
|
|
for i := 0; i < 10; i++ {
|
|
|
|
n, err = ws.Read(resp)
|
|
|
|
fatalErr(t, err)
|
|
|
|
|
|
|
|
ctx.Log.Logf("test", "SUB_%d: %s", i, resp[:n])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SubGQL(sub_1)
|
|
|
|
|
|
|
|
msgs := Messages{}
|
|
|
|
msgs = msgs.Add(gql.ID, gql.Key, &StopSignal, gql.ID)
|
2023-08-08 14:00:17 -06:00
|
|
|
err = ctx.Send(msgs)
|
|
|
|
fatalErr(t, err)
|
2023-08-12 11:26:19 -06:00
|
|
|
_, err = WaitForSignal(listener_ext.Chan, 100*time.Millisecond, StatusSignalType, func(sig *IDStringSignal) bool {
|
2023-08-15 18:23:06 -06:00
|
|
|
return sig.Str == "stopped"
|
2023-07-29 11:03:41 -06:00
|
|
|
})
|
2023-08-07 20:44:56 -06:00
|
|
|
fatalErr(t, err)
|
2023-07-29 00:40:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestGQLDB(t *testing.T) {
|
2023-08-01 20:58:27 -06:00
|
|
|
ctx := logTestContext(t, []string{"test"})
|
2023-07-26 13:28:03 -06:00
|
|
|
|
|
|
|
TestUserNodeType := NodeType("TEST_USER")
|
2023-07-27 11:33:11 -06:00
|
|
|
err := ctx.RegisterNodeType(TestUserNodeType, []ExtType{})
|
2023-07-26 13:28:03 -06:00
|
|
|
fatalErr(t, err)
|
2023-07-28 15:07:38 -06:00
|
|
|
u1 := NewNode(ctx, nil, TestUserNodeType, 10, nil)
|
2023-07-26 13:28:03 -06:00
|
|
|
|
|
|
|
ctx.Log.Logf("test", "U1_ID: %s", u1.ID)
|
2023-07-01 13:06:39 -06:00
|
|
|
|
2023-08-15 18:23:06 -06:00
|
|
|
gql_ext, err := NewGQLExt(ctx, ":0", nil, nil)
|
2023-07-29 00:40:18 -06:00
|
|
|
fatalErr(t, err)
|
2023-07-27 12:03:39 -06:00
|
|
|
listener_ext := NewListenerExt(10)
|
2023-07-28 15:07:38 -06:00
|
|
|
gql := NewNode(ctx, nil, GQLNodeType, 10, nil,
|
2023-07-27 11:33:11 -06:00
|
|
|
gql_ext,
|
2023-07-27 12:03:39 -06:00
|
|
|
listener_ext,
|
|
|
|
NewGroupExt(nil))
|
2023-07-26 11:56:10 -06:00
|
|
|
ctx.Log.Logf("test", "GQL_ID: %s", gql.ID)
|
2023-07-27 00:57:18 -06:00
|
|
|
|
2023-08-08 14:00:17 -06:00
|
|
|
msgs := Messages{}
|
2023-08-10 23:43:10 -06:00
|
|
|
msgs = msgs.Add(gql.ID, gql.Key, &StopSignal, gql.ID)
|
2023-08-08 14:00:17 -06:00
|
|
|
err = ctx.Send(msgs)
|
|
|
|
fatalErr(t, err)
|
2023-08-12 11:26:19 -06:00
|
|
|
_, err = WaitForSignal(listener_ext.Chan, 100*time.Millisecond, StatusSignalType, func(sig *IDStringSignal) bool {
|
2023-07-31 18:29:26 -06:00
|
|
|
return sig.Str == "stopped" && sig.NodeID == gql.ID
|
2023-07-28 19:32:27 -06:00
|
|
|
})
|
|
|
|
fatalErr(t, err)
|
2023-07-03 13:14:48 -06:00
|
|
|
|
2023-07-27 15:27:14 -06:00
|
|
|
ser1, err := gql.Serialize()
|
|
|
|
ser2, err := u1.Serialize()
|
2023-08-01 20:58:27 -06:00
|
|
|
ser3, err := StopSignal.Serialize()
|
|
|
|
ctx.Log.Logf("test", "SER_1: \n%s\n\n", ser1)
|
|
|
|
ctx.Log.Logf("test", "SER_2: \n%s\n\n", ser2)
|
|
|
|
ctx.Log.Logf("test", "SER_3: \n%s\n\n", ser3)
|
2023-07-01 13:06:39 -06:00
|
|
|
|
2023-07-26 11:56:10 -06:00
|
|
|
// Clear all loaded nodes from the context so it loads them from the database
|
2023-08-10 23:43:10 -06:00
|
|
|
ctx.Nodes = map[NodeID]*Node{}
|
2023-07-26 11:56:10 -06:00
|
|
|
gql_loaded, err := LoadNode(ctx, gql.ID)
|
2023-07-01 13:06:39 -06:00
|
|
|
fatalErr(t, err)
|
2023-07-27 15:27:14 -06:00
|
|
|
listener_ext, err = GetExt[*ListenerExt](gql_loaded)
|
2023-07-27 12:20:49 -06:00
|
|
|
fatalErr(t, err)
|
2023-08-08 14:00:17 -06:00
|
|
|
msgs = Messages{}
|
2023-08-10 23:43:10 -06:00
|
|
|
msgs = msgs.Add(gql_loaded.ID, gql_loaded.Key, &StopSignal, gql_loaded.ID)
|
2023-08-08 14:00:17 -06:00
|
|
|
err = ctx.Send(msgs)
|
2023-07-23 19:04:04 -06:00
|
|
|
fatalErr(t, err)
|
2023-08-12 11:26:19 -06:00
|
|
|
_, err = WaitForSignal(listener_ext.Chan, 100*time.Millisecond, StatusSignalType, func(sig *IDStringSignal) bool {
|
2023-07-31 18:29:26 -06:00
|
|
|
return sig.Str == "stopped" && sig.NodeID == gql_loaded.ID
|
2023-07-28 19:32:27 -06:00
|
|
|
})
|
|
|
|
fatalErr(t, err)
|
2023-07-01 13:06:39 -06:00
|
|
|
}
|
2023-07-19 14:45:05 -06:00
|
|
|
|