okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
d9c1a13
main
1// Controlled cancellation and malformed wire batches cannot be forced reliably 2// through a scripted provider; these tests exercise the public transport boundaries. 3package daemon 4 5import ( 6"albedo/cli/internal/daemon/protocol" 7"encoding/json" 8"errors" 9"fmt" 10"net/http" 11"testing" 12) 13 14func TestAgentEventsValidateNullableSendersAndBooleanFields (t * testing.T ) { 15event ,err := decodeAgentEvent (json .RawMessage (`{"type":"mail","data":{"mail_id":"m","sender_session_id":null,"sender_label":null,"receiver_session_id":"s","kind":"message","bytes":2}}` )) 16if err != nil || event == nil || event .To != "s" { 17t .Fatalf ("nullable bus sender rejected: %v" ,err ) 18 } 19if _ ,err := decodeAgentEvent (json .RawMessage (`{"type":"invalidate","data":{"urls":[],"session_ids":["s"],"scope_dirty":"false"}}` ));err == nil { 20t .Fatal ("malformed bus boolean accepted" ) 21 } 22} 23 24// Presence and null differ even when Go would decode both as the same zero. 25// A controlled peer can violate these contracts at every nested boundary. 26func TestSessionReadValidatesRequiredAndNullableMembers (t * testing.T ) { 27for _ ,scenario := range []struct { 28name string 29change func (map [string ]any ) 30valid bool 31 }{ 32 {"required nullable omitted" ,func (session map [string ]any ) {delete (session ,"effort" ) },false }, 33 {"nullable retained" ,func (session map [string ]any ) {session ["effort" ]= nil },true }, 34 {"nested required omitted" ,func (session map [string ]any ) { 35delete (session ["kernel" ].(map [string ]any ),"live_job_count" ) 36 },false }, 37 {"nested nullable retained" ,func (session map [string ]any ) { 38session ["kernel" ].(map [string ]any )["live_job_count" ]= nil 39 },true }, 40 {"job list omitted" ,func (session map [string ]any ) { 41delete (session ["kernel" ].(map [string ]any ),"running_jobs" ) 42 },false }, 43 {"unknown job list" ,func (session map [string ]any ) { 44session ["kernel" ].(map [string ]any )["running_jobs" ]= nil 45 },true }, 46 {"job pid omitted" ,func (session map [string ]any ) { 47session ["kernel" ].(map [string ]any )["running_jobs" ]= []any {map [string ]any {"id" :"j" ,"command" :"sleep 10" }} 48 },false }, 49 {"nullable job pid" ,func (session map [string ]any ) { 50session ["kernel" ].(map [string ]any )["running_jobs" ]= []any {map [string ]any {"id" :"j" ,"pid" :nil ,"command" :"sleep 10" ,"started_at" :0 }} 51 },true }, 52 {"job started_at omitted" ,func (session map [string ]any ) { 53session ["kernel" ].(map [string ]any )["running_jobs" ]= []any {map [string ]any {"id" :"j" ,"pid" :nil ,"command" :"sleep 10" }} 54 },false }, 55 {"null scalar" ,func (session map [string ]any ) { 56session ["status" ].(map [string ]any )["interrupt_requested" ]= nil 57 },false }, 58 {"null array" ,func (session map [string ]any ) {session ["glances" ]= nil },false }, 59 {"null object" ,func (session map [string ]any ) {session ["preferences" ]= nil },false }, 60 {"optional progress preview omitted" ,func (session map [string ]any ) { 61progress := canonicalProgress ("call" ) 62delete (progress ,"preview" ) 63session ["current_progress" ]= []any {progress } 64 },true }, 65 {"optional progress preview null" ,func (session map [string ]any ) { 66progress := canonicalProgress ("call" ) 67progress ["preview" ]= nil 68session ["current_progress" ]= []any {progress } 69 },false }, 70 } { 71t .Run (scenario .name ,func (t * testing.T ) { 72session := canonicalSession ("s" ,generationA ,0 ) 73scenario .change (session ) 74conn := controlledConnection (t ,func (w http.ResponseWriter ,request * http.Request ) { 75if request .URL .RequestURI ()!= "/sessions/s?tail=0" { 76t .Errorf ("unexpected session read %s" ,request .URL ) 77 } 78_ = json .NewEncoder (w ).Encode (session ) 79 }) 80captured ,err := GetSession (t .Context (),conn ,"s" ) 81if scenario .valid { 82if err != nil || captured .ID != "s" { 83t .Fatalf ("nullable native fact rejected: %+v, %v" ,captured ,err ) 84 } 85 }else if _ ,ok := errors.AsType [* ProtocolError ](err );! ok { 86t .Fatalf ("malformed required member accepted: %v" ,err ) 87 } 88 }) 89 } 90} 91 92func TestSessionChangeRejectsMissingNestedMembers (t * testing.T ) { 93for _ ,valid := range []bool {true ,false } { 94session := canonicalSession ("s" ,generationA ,0 ) 95if ! valid { 96delete (session ["kernel" ].(map [string ]any ),"live_job_count" ) 97 } 98payload ,err := json .Marshal (map [string ]any {"session" :session ,"resource" :session ["configuration_resource" ],"move" :nil }) 99if err != nil { 100t .Fatal (err ) 101 } 102var change protocol.SessionChange 103err = decodeRequired (payload ,& change ) 104if (err == nil )!= valid { 105t .Fatalf ("nested session validation valid=%v: %v" ,valid ,err ) 106 } 107 } 108} 109 110func TestModelPagingRejectsRepeatedTokens (t * testing.T ) { 111calls := 0 112conn := controlledConnection (t ,func (w http.ResponseWriter ,r * http.Request ) { 113calls ++ 114if calls == 1 && r .URL .Query ().Get ("next" )!= "" || calls == 2 && r .URL .Query ().Get ("next" )!= "same" { 115t .Errorf ("wrong cursor at page %d: %s" ,calls ,r .URL ) 116 } 117_ ,_ = fmt .Fprint (w ,`{"items":[],"next":"same"}` ) 118 }) 119if _ ,err := ListModels (t .Context (),conn ,"provider" ,"" );err == nil || calls != 2 { 120t .Fatalf ("repeated cursor accepted: calls=%d, error=%v" ,calls ,err ) 121 } 122}