2023-06-25 20:20:59 -06:00
package graphvent
import (
"testing"
2023-06-25 22:19:05 -06:00
"time"
2023-07-06 16:57:51 -06:00
"errors"
2023-07-19 14:45:05 -06:00
"net"
"net/http"
"io"
"fmt"
"encoding/json"
"bytes"
"crypto/rand"
"crypto/ecdh"
"crypto/ecdsa"
"crypto/elliptic"
2023-07-21 01:05:24 -06:00
"crypto/tls"
2023-07-20 00:24:22 -06:00
"encoding/base64"
2023-06-25 20:20:59 -06:00
)
func TestGQLThread ( t * testing . T ) {
2023-07-03 13:14:48 -06:00
ctx := logTestContext ( t , [ ] string { } )
2023-07-19 14:45:05 -06:00
key , err := ecdsa . GenerateKey ( elliptic . P256 ( ) , rand . Reader )
fatalErr ( t , err )
2023-07-21 12:09:29 -06:00
2023-07-21 01:05:24 -06:00
gql_t_r := NewGQLThread ( RandID ( ) , "GQL Thread" , "init" , ":0" , ecdh . P256 ( ) , key , nil , nil )
2023-07-09 20:30:19 -06:00
gql_t := & gql_t_r
t1_r := NewSimpleThread ( RandID ( ) , "Test thread 1" , "init" , nil , BaseThreadActions , BaseThreadHandlers )
t1 := & t1_r
t2_r := NewSimpleThread ( RandID ( ) , "Test thread 2" , "init" , nil , BaseThreadActions , BaseThreadHandlers )
t2 := & t2_r
2023-07-21 13:33:04 -06:00
err = UpdateStates ( ctx , [ ] Node { gql_t , t1 , t2 } , func ( nodes NodeMap ) error {
2023-07-11 16:54:09 -06:00
i1 := NewParentThreadInfo ( true , "start" , "restore" )
2023-07-21 13:33:04 -06:00
err := LinkThreads ( ctx , gql_t , t1 , & i1 , nodes )
2023-07-09 20:30:19 -06:00
if err != nil {
return err
}
2023-06-26 21:20:04 -06:00
2023-07-11 16:54:09 -06:00
i2 := NewParentThreadInfo ( false , "start" , "restore" )
2023-07-09 20:30:19 -06:00
return LinkThreads ( ctx , gql_t , t2 , & i2 , nodes )
} )
2023-06-25 20:20:59 -06:00
fatalErr ( t , err )
2023-06-25 22:19:05 -06:00
go func ( thread Thread ) {
time . Sleep ( 10 * time . Millisecond )
2023-07-09 20:30:19 -06:00
err := UseStates ( ctx , [ ] Node { thread } , func ( nodes NodeMap ) error {
return thread . Signal ( ctx , CancelSignal ( nil ) , nodes )
2023-07-04 18:45:23 -06:00
} )
2023-07-05 23:54:11 -06:00
fatalErr ( t , err )
2023-07-09 20:30:19 -06:00
} ( gql_t )
2023-06-25 22:19:05 -06:00
2023-07-09 20:30:19 -06:00
err = ThreadLoop ( ctx , gql_t , "start" )
2023-06-25 20:20:59 -06:00
fatalErr ( t , err )
}
2023-07-01 13:06:39 -06:00
func TestGQLDBLoad ( t * testing . T ) {
2023-07-19 21:28:48 -06:00
ctx := logTestContext ( t , [ ] string { } )
2023-07-09 20:30:19 -06:00
l1_r := NewSimpleLockable ( RandID ( ) , "Test Lockable 1" )
l1 := & l1_r
2023-07-01 13:06:39 -06:00
2023-07-09 20:30:19 -06:00
t1_r := NewSimpleThread ( RandID ( ) , "Test Thread 1" , "init" , nil , BaseThreadActions , BaseThreadHandlers )
t1 := & t1_r
2023-07-19 20:03:13 -06:00
update_channel := UpdateChannel ( t1 , 10 , NodeID { } )
2023-07-01 13:06:39 -06:00
2023-07-20 00:24:22 -06:00
u1_key , err := ecdsa . GenerateKey ( elliptic . P256 ( ) , rand . Reader )
fatalErr ( t , err )
u1_shared := [ ] byte { 0xDE , 0xAD , 0xBE , 0xEF , 0x01 , 0x23 , 0x45 , 0x67 }
2023-07-21 13:33:04 -06:00
u1_r := NewUser ( "Test User" , time . Now ( ) , & u1_key . PublicKey , u1_shared , [ ] string { "gql" } )
2023-07-20 00:24:22 -06:00
u1 := & u1_r
2023-07-21 13:33:04 -06:00
p1_r := NewSimplePolicy ( RandID ( ) , NewNodeActions ( nil , [ ] string { "enumerate" } ) )
2023-07-20 23:19:10 -06:00
p1 := & p1_r
2023-07-19 14:45:05 -06:00
key , err := ecdsa . GenerateKey ( elliptic . P256 ( ) , rand . Reader )
fatalErr ( t , err )
2023-07-21 01:05:24 -06:00
gql_r := NewGQLThread ( RandID ( ) , "GQL Thread" , "init" , ":0" , ecdh . P256 ( ) , key , nil , nil )
2023-07-09 20:30:19 -06:00
gql := & gql_r
2023-07-01 13:06:39 -06:00
2023-07-11 16:54:09 -06:00
info := NewParentThreadInfo ( true , "start" , "restore" )
2023-07-20 23:19:10 -06:00
err = UpdateStates ( ctx , [ ] Node { gql , t1 , l1 , u1 , p1 } , func ( nodes NodeMap ) error {
2023-07-21 12:09:29 -06:00
err := gql . AddPolicy ( p1 )
2023-07-20 23:19:10 -06:00
if err != nil {
return err
}
2023-07-20 00:24:22 -06:00
gql . Users [ KeyID ( & u1_key . PublicKey ) ] = u1
2023-07-20 23:19:10 -06:00
err = LinkLockables ( ctx , gql , [ ] Lockable { l1 } , nodes )
2023-07-09 20:30:19 -06:00
if err != nil {
return err
}
return LinkThreads ( ctx , gql , t1 , & info , nodes )
2023-07-04 18:45:23 -06:00
} )
2023-07-03 13:14:48 -06:00
fatalErr ( t , err )
2023-07-09 20:30:19 -06:00
err = UseStates ( ctx , [ ] Node { gql } , func ( nodes NodeMap ) error {
err := gql . Signal ( ctx , NewSignal ( t1 , "child_added" ) , nodes )
if err != nil {
return nil
}
return gql . Signal ( ctx , AbortSignal ( nil ) , nodes )
2023-07-04 18:45:23 -06:00
} )
2023-07-09 20:30:19 -06:00
fatalErr ( t , err )
2023-07-06 16:57:51 -06:00
err = ThreadLoop ( ctx , gql , "start" )
2023-07-19 20:03:13 -06:00
if errors . Is ( err , NewThreadAbortedError ( NodeID { } ) ) {
2023-07-06 16:57:51 -06:00
ctx . Log . Logf ( "test" , "Main thread aborted by signal: %s" , err )
} else {
fatalErr ( t , err )
}
2023-07-03 13:14:48 -06:00
2023-07-06 16:57:51 -06:00
( * GraphTester ) ( t ) . WaitForValue ( ctx , update_channel , "thread_aborted" , t1 , 100 * time . Millisecond , "Didn't receive thread_abort from t1 on t1" )
2023-07-03 13:14:48 -06:00
2023-07-21 00:02:53 -06:00
err = UseStates ( ctx , [ ] Node { gql , u1 } , func ( nodes NodeMap ) error {
2023-07-09 20:30:19 -06:00
ser1 , err := gql . Serialize ( )
2023-07-21 00:02:53 -06:00
ser2 , err := u1 . Serialize ( )
2023-07-19 20:03:13 -06:00
ctx . Log . Logf ( "test" , "\n%s\n\n" , ser1 )
ctx . Log . Logf ( "test" , "\n%s\n\n" , ser2 )
2023-07-01 13:06:39 -06:00
return err
} )
2023-07-03 13:14:48 -06:00
gql_loaded , err := LoadNode ( ctx , gql . ID ( ) )
2023-07-01 13:06:39 -06:00
fatalErr ( t , err )
2023-07-09 20:30:19 -06:00
var t1_loaded * SimpleThread = nil
2023-07-01 13:06:39 -06:00
2023-07-09 20:30:19 -06:00
var update_channel_2 chan GraphSignal
err = UseStates ( ctx , [ ] Node { gql_loaded } , func ( nodes NodeMap ) error {
ser , err := gql_loaded . Serialize ( )
2023-07-19 14:45:05 -06:00
ctx . Log . Logf ( "test" , "\n%s\n\n" , ser )
2023-07-21 00:02:53 -06:00
u_loaded := gql_loaded . ( * GQLThread ) . Users [ u1 . ID ( ) ]
2023-07-09 20:30:19 -06:00
child := gql_loaded . ( Thread ) . Children ( ) [ 0 ] . ( * SimpleThread )
t1_loaded = child
2023-07-19 20:03:13 -06:00
update_channel_2 = UpdateChannel ( t1_loaded , 10 , NodeID { } )
2023-07-21 00:02:53 -06:00
err = UseMoreStates ( ctx , [ ] Node { u_loaded } , nodes , func ( nodes NodeMap ) error {
ser , err := u_loaded . Serialize ( )
2023-07-19 14:45:05 -06:00
ctx . Log . Logf ( "test" , "\n%s\n\n" , ser )
2023-07-03 13:14:48 -06:00
return err
} )
2023-07-09 20:30:19 -06:00
gql_loaded . Signal ( ctx , AbortSignal ( nil ) , nodes )
2023-07-01 13:06:39 -06:00
return err
} )
2023-07-03 13:14:48 -06:00
2023-07-06 16:57:51 -06:00
err = ThreadLoop ( ctx , gql_loaded . ( Thread ) , "restore" )
2023-07-19 20:03:13 -06:00
if errors . Is ( err , NewThreadAbortedError ( NodeID { } ) ) {
2023-07-06 16:57:51 -06:00
ctx . Log . Logf ( "test" , "Main thread aborted by signal: %s" , err )
} else {
fatalErr ( t , err )
}
2023-07-10 01:07:56 -06:00
( * GraphTester ) ( t ) . WaitForValue ( ctx , update_channel_2 , "thread_aborted" , t1_loaded , 100 * time . Millisecond , "Didn't received thread_aborted on t1_loaded from t1_loaded" )
2023-07-03 13:14:48 -06:00
2023-07-01 13:06:39 -06:00
}
2023-07-19 14:45:05 -06:00
func TestGQLAuth ( t * testing . T ) {
2023-07-21 13:33:04 -06:00
ctx := logTestContext ( t , [ ] string { "test" , "gql" } )
2023-07-19 14:45:05 -06:00
key , err := ecdsa . GenerateKey ( elliptic . P256 ( ) , rand . Reader )
fatalErr ( t , err )
2023-07-21 01:05:24 -06:00
2023-07-21 13:56:44 -06:00
p1_r := NewPerTagPolicy ( RandID ( ) , map [ string ] NodeActions { "gql" : NewNodeActions ( nil , [ ] string { "*" } ) } )
2023-07-21 12:09:29 -06:00
p1 := & p1_r
2023-07-21 01:21:53 -06:00
gql_t_r := NewGQLThread ( RandID ( ) , "GQL Thread" , "init" , ":0" , ecdh . P256 ( ) , key , nil , nil )
2023-07-19 14:45:05 -06:00
gql_t := & gql_t_r
2023-07-21 12:09:29 -06:00
err = UpdateStates ( ctx , [ ] Node { gql_t , p1 } , func ( nodes NodeMap ) error {
return gql_t . AddPolicy ( p1 )
} )
2023-07-19 14:45:05 -06:00
done := make ( chan error , 1 )
var update_channel chan GraphSignal
err = UseStates ( ctx , [ ] Node { gql_t } , func ( nodes NodeMap ) error {
2023-07-19 20:03:13 -06:00
update_channel = UpdateChannel ( gql_t , 10 , NodeID { } )
2023-07-19 14:45:05 -06:00
return nil
} )
fatalErr ( t , err )
go func ( done chan error , thread Thread ) {
timeout := time . After ( 2 * time . Second )
select {
case <- timeout :
ctx . Log . Logf ( "test" , "TIMEOUT" )
case <- done :
ctx . Log . Logf ( "test" , "DONE" )
}
err := UseStates ( ctx , [ ] Node { gql_t } , func ( nodes NodeMap ) error {
return thread . Signal ( ctx , CancelSignal ( nil ) , nodes )
} )
fatalErr ( t , err )
} ( done , gql_t )
go func ( thread Thread ) {
( * GraphTester ) ( t ) . WaitForValue ( ctx , update_channel , "server_started" , gql_t , 100 * time . Millisecond , "Server didn't start" )
port := gql_t . tcp_listener . Addr ( ) . ( * net . TCPAddr ) . Port
ctx . Log . Logf ( "test" , "GQL_PORT: %d" , port )
2023-07-21 01:05:24 -06:00
customTransport := & http . Transport {
Proxy : http . DefaultTransport . ( * http . Transport ) . Proxy ,
DialContext : http . DefaultTransport . ( * http . Transport ) . DialContext ,
MaxIdleConns : http . DefaultTransport . ( * http . Transport ) . MaxIdleConns ,
IdleConnTimeout : http . DefaultTransport . ( * http . Transport ) . IdleConnTimeout ,
ExpectContinueTimeout : http . DefaultTransport . ( * http . Transport ) . ExpectContinueTimeout ,
TLSHandshakeTimeout : http . DefaultTransport . ( * http . Transport ) . TLSHandshakeTimeout ,
TLSClientConfig : & tls . Config { InsecureSkipVerify : true } ,
}
client := & http . Client { Transport : customTransport }
url := fmt . Sprintf ( "https://localhost:%d/auth" , port )
2023-07-19 14:45:05 -06:00
id , err := ecdsa . GenerateKey ( elliptic . P256 ( ) , rand . Reader )
fatalErr ( t , err )
2023-07-19 21:28:48 -06:00
auth_req , ec_key , err := NewAuthReqJSON ( ecdh . P256 ( ) , id )
2023-07-19 14:45:05 -06:00
fatalErr ( t , err )
str , err := json . Marshal ( auth_req )
fatalErr ( t , err )
2023-07-20 00:24:22 -06:00
2023-07-19 14:45:05 -06:00
b := bytes . NewBuffer ( str )
req , err := http . NewRequest ( "PUT" , url , b )
fatalErr ( t , err )
2023-07-20 00:24:22 -06:00
2023-07-19 14:45:05 -06:00
resp , err := client . Do ( req )
fatalErr ( t , err )
2023-07-20 00:24:22 -06:00
2023-07-19 14:45:05 -06:00
body , err := io . ReadAll ( resp . Body )
fatalErr ( t , err )
2023-07-19 21:28:48 -06:00
2023-07-20 00:24:22 -06:00
resp . Body . Close ( )
2023-07-19 21:28:48 -06:00
var j AuthRespJSON
err = json . Unmarshal ( body , & j )
fatalErr ( t , err )
2023-07-20 00:24:22 -06:00
shared , err := ParseAuthRespJSON ( j , elliptic . P256 ( ) , ecdh . P256 ( ) , ec_key )
fatalErr ( t , err )
2023-07-21 01:05:24 -06:00
url = fmt . Sprintf ( "https://localhost:%d/gql" , port )
2023-07-20 00:24:22 -06:00
ser , err := json . MarshalIndent ( & GQLPayload {
2023-07-21 17:49:19 -06:00
Query : "query { Self { Users { ID, Name } } }" ,
2023-07-20 00:24:22 -06:00
} , "" , " " )
fatalErr ( t , err )
b = bytes . NewBuffer ( ser )
req , err = http . NewRequest ( "GET" , url , b )
2023-07-19 21:28:48 -06:00
fatalErr ( t , err )
2023-07-20 00:24:22 -06:00
req . SetBasicAuth ( KeyID ( & id . PublicKey ) . String ( ) , base64 . StdEncoding . EncodeToString ( shared ) )
resp , err = client . Do ( req )
fatalErr ( t , err )
body , err = io . ReadAll ( resp . Body )
fatalErr ( t , err )
resp . Body . Close ( )
ctx . Log . Logf ( "test" , "TEST_RESP: %s" , body )
req . SetBasicAuth ( KeyID ( & id . PublicKey ) . String ( ) , "BAD_PASSWORD" )
resp , err = client . Do ( req )
fatalErr ( t , err )
body , err = io . ReadAll ( resp . Body )
fatalErr ( t , err )
resp . Body . Close ( )
ctx . Log . Logf ( "test" , "TEST_RESP: %s" , body )
2023-07-19 21:28:48 -06:00
2023-07-19 14:45:05 -06:00
done <- nil
} ( gql_t )
err = ThreadLoop ( ctx , gql_t , "start" )
fatalErr ( t , err )
}