@@ -3,7 +3,6 @@ package osbuildexecutor_test
33import (
44 "archive/tar"
55 "context"
6- "encoding/json"
76 "io"
87 "net/http"
98 "net/http/httptest"
@@ -14,13 +13,21 @@ import (
1413 "testing"
1514 "time"
1615
17- "github.com/osbuild/images/pkg/osbuild"
16+ "github.com/google/uuid"
17+ "github.com/sirupsen/logrus"
18+ "github.com/sirupsen/logrus/hooks/test"
1819 "github.com/stretchr/testify/assert"
1920 "github.com/stretchr/testify/require"
2021
2122 "github.com/osbuild/osbuild-composer/internal/osbuildexecutor"
23+ "github.com/osbuild/osbuild-composer/internal/worker"
2224)
2325
26+ func makeMockEntry () (* logrus.Entry , * test.Hook ) {
27+ logger , hook := test .NewNullLogger ()
28+ return logger .WithField ("test" , "test" ), hook
29+ }
30+
2431func TestWaitForSI (t * testing.T ) {
2532 server := httptest .NewUnstartedServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
2633 w .WriteHeader (http .StatusOK )
@@ -66,29 +73,113 @@ func TestWriteInputArchive(t *testing.T) {
6673 }, strings .Split (string (out ), "\n " ))
6774}
6875
76+ type testJob struct {
77+ PartialUpdates []interface {}
78+ }
79+
80+ func (j * testJob ) Id () uuid.UUID {
81+ return uuid .Nil
82+ }
83+
84+ func (j * testJob ) Type () string {
85+ return "test-job"
86+ }
87+
88+ func (j * testJob ) Args (args interface {}) error {
89+ return nil
90+ }
91+
92+ func (j * testJob ) DynamicArgs (i int , args interface {}) error {
93+ return nil
94+ }
95+
96+ func (j * testJob ) NDynamicArgs () int {
97+ return 0
98+ }
99+
100+ func (j * testJob ) Update (result interface {}) error {
101+ j .PartialUpdates = append (j .PartialUpdates , result )
102+ return nil
103+ }
104+
105+ func (j * testJob ) Finish (result interface {}) error {
106+ return nil
107+ }
108+
109+ func (j * testJob ) Canceled () (bool , error ) {
110+ return false , nil
111+ }
112+
113+ func (j * testJob ) UploadArtifact (name string , readSeeker io.ReadSeeker ) error {
114+ return nil
115+ }
116+
69117func TestHandleBuild (t * testing.T ) {
70118 buildServer := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
71119 input , err := io .ReadAll (r .Body )
72120 require .NoError (t , err )
73121 require .Equal (t , []byte ("test" ), input )
74122
75123 w .WriteHeader (http .StatusCreated )
76- osbuildResult := osbuild.Result {
77- Success : true ,
78- }
79- data , err := json .Marshal (osbuildResult )
80- require .NoError (t , err )
81- _ , err = w .Write (data )
124+ _ , err = w .Write ([]byte (`{"message": "starting pipeline", "context": {"origin": "osbuild.monitor", "pipeline": {"name": "source", "id": "pipeline-id", "stage": {}}, "id": "context-id"}, "progress": {"name": "pipelines/sources", "total": 1, "done": 0}}
125+ {"message": "stage in pipeline", "context": {"id": "context-id"}, "progress": {"name": "source", "total": 1, "done": 0, "progress": {"name": "source/stage", "total": 2, "done": 0}}}
126+ {"message": "finishing pipeline", "result": {"name": "source", "id": "pipeline-id", "success": true}, "context": {"id": "context-id"}, "progress": {"name": "source", "total": 1, "done": 1}}` ))
82127 require .NoError (t , err )
83128 }))
84129
85130 cacheDir := t .TempDir ()
86131 inputArchive := filepath .Join (cacheDir , "test.tar" )
87132 require .NoError (t , os .WriteFile (inputArchive , []byte ("test" ), 0600 ))
88133
89- osbuildResult , err := osbuildexecutor .HandleBuild (inputArchive , buildServer .URL )
134+ entry , hook := makeMockEntry ()
135+ job := testJob {}
136+ osbuildResult , err := osbuildexecutor .HandleBuild (inputArchive , buildServer .URL , entry , & job )
90137 require .NoError (t , err )
91138 require .True (t , osbuildResult .Success )
139+ require .Len (t , hook .Entries , 3 )
140+ require .Equal (t , "OSBuild status: starting pipeline (step 0/1)" , hook .Entries [0 ].Message )
141+ require .Equal (t , "OSBuild status: stage in pipeline (step 0/1: 0/2)" , hook .Entries [1 ].Message )
142+ require .Equal (t , "OSBuild status: finishing pipeline (step 1/1)" , hook .Entries [2 ].Message )
143+
144+ // only 1 update every 30 seconds, so in a testing scenario only the first status should have been received
145+ require .Eventually (t , func () bool { return len (job .PartialUpdates ) == 1 }, time .Second , time .Millisecond * 10 )
146+ partial , ok := job .PartialUpdates [0 ].(worker.JobResult )
147+ require .True (t , ok )
148+ require .Equal (t , worker.JobResult {
149+ Progress : & worker.JobProgress {
150+ Done : 0 ,
151+ Total : 1 ,
152+ Message : "starting pipeline" ,
153+ },
154+ }, partial )
155+ require .Len (t , job .PartialUpdates , 1 )
156+ }
157+
158+ func TestHandleBuildTrace (t * testing.T ) {
159+ buildServer := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
160+ input , err := io .ReadAll (r .Body )
161+ require .NoError (t , err )
162+ require .Equal (t , []byte ("test" ), input )
163+
164+ w .WriteHeader (http .StatusCreated )
165+ _ , err = w .Write ([]byte (`{"message": "starting pipeline", "context": {"origin": "osbuild.monitor", "pipeline": {"name": "source", "id": "pipeline-id", "stage": {}}, "id": "context-id"}, "progress": {"name": "pipelines/sources", "total": 1, "done": 0}}
166+ {"message": "no context, thus trace"}
167+ {"message": "failed pipeline", "result": {"name": "source", "id": "pipeline-id", "success": false}, "context": {"id": "context-id"}, "progress": {"name": "source", "total": 1, "done": 1}}` ))
168+ require .NoError (t , err )
169+ }))
170+
171+ cacheDir := t .TempDir ()
172+ inputArchive := filepath .Join (cacheDir , "test.tar" )
173+ require .NoError (t , os .WriteFile (inputArchive , []byte ("test" ), 0600 ))
174+
175+ entry , hook := makeMockEntry ()
176+ osbuildResult , err := osbuildexecutor .HandleBuild (inputArchive , buildServer .URL , entry , nil )
177+ require .NoError (t , err )
178+ require .False (t , osbuildResult .Success )
179+ require .Len (t , hook .Entries , 3 )
180+ require .Equal (t , "OSBuild status: starting pipeline (step 0/1)" , hook .Entries [0 ].Message )
181+ require .Equal (t , "no context, thus trace" , hook .Entries [1 ].Message )
182+ require .Equal (t , "OSBuild status: failed pipeline (step 1/1)" , hook .Entries [2 ].Message )
92183}
93184
94185func TestHandleBuildNoJSON (t * testing.T ) {
@@ -105,8 +196,9 @@ func TestHandleBuildNoJSON(t *testing.T) {
105196 inputArchive := filepath .Join (cacheDir , "test.tar" )
106197 require .NoError (t , os .WriteFile (inputArchive , []byte ("test" ), 0600 ))
107198
108- _ , err := osbuildexecutor .HandleBuild (inputArchive , buildServer .URL )
109- require .ErrorContains (t , err , `Unable to decode response body "bad non-json text" into osbuild result:` )
199+ entry , _ := makeMockEntry ()
200+ _ , err := osbuildexecutor .HandleBuild (inputArchive , buildServer .URL , entry , nil )
201+ require .ErrorContains (t , err , `error parsing osbuild status, please report a bug: cannot scan line "bad non-json text": invalid character 'b' looking for beginning of value` )
110202}
111203
112204func TestHandleOutputArchive (t * testing.T ) {
0 commit comments