package osbuild import ( "bytes" "encoding/json" "testing" "github.com/stretchr/testify/assert" "github.com/osbuild/osbuild-composer/internal/common" ) func TestStageResult_UnmarshalJSON(t *testing.T) { cases := []struct { input string success bool }{ {input: `{}`, success: true}, {input: `{"success": true}`, success: true}, {input: `{"success": false}`, success: false}, } for _, c := range cases { t.Run(c.input, func(t *testing.T) { var result StageResult err := json.Unmarshal([]byte(c.input), &result) assert.NoError(t, err) assert.Equal(t, c.success, result.Success) }) } } func TestUnmarshal(t *testing.T) { assert := assert.New(t) var result Result err := json.Unmarshal([]byte(fullResultRaw), &result) assert.NoError(err) assert.True(result.Success) assert.Equal(len(result.Log), 4) for _, plName := range []string{"build", "image", "os", "qcow2"} { assert.Contains(result.Log, plName) for _, stage := range result.Log[plName] { assert.True(stage.Success) } } assert.Equal(len(result.Metadata), 2) pipelinePackageCount := map[string]int{ "build": 254, "os": 449, } for _, plName := range []string{"build", "os"} { assert.Contains(result.Metadata, plName) for stageType, stageMetadata := range result.Metadata[plName] { if stageType == "org.osbuild.rpm" { rpmMd, convOk := stageMetadata.(*RPMStageMetadata) assert.True(convOk) assert.Len(rpmMd.Packages, pipelinePackageCount[plName]) } } } } func TestUnmarshalV1Success(t *testing.T) { var result Result err := json.Unmarshal([]byte(v1ResultSuccess), &result) assert := assert.New(t) assert.NoError(err) assert.True(result.Success) pipelineStageCount := map[string]int{ "build": 2, "os": 11, "assembler": 1, } assert.Len(result.Log, len(pipelineStageCount)) for name, stageCount := range pipelineStageCount { assert.Contains(result.Log, name) assert.Len(result.Log[name], stageCount) for _, stage := range result.Log[name] { assert.True(stage.Success) } } buildLog := result.Log["build"] assert.Equal("org.osbuild.rpm", buildLog[0].Type) osLog := result.Log["os"] assert.Equal(osLog[0].Type, "org.osbuild.rpm") assemblerLog := result.Log["assembler"] assert.Equal(assemblerLog[0].Type, "org.osbuild.qemu") for _, plName := range []string{"build", "os"} { assert.Contains(result.Metadata, plName) for stageType, stageMetadata := range result.Metadata[plName] { if stageType == "org.osbuild.rpm" { rpmMd, convOk := stageMetadata.(*RPMStageMetadata) assert.True(convOk) assert.Len(rpmMd.Packages, 1) } } } } func TestUnmarshalV1Failure(t *testing.T) { assert := assert.New(t) var result Result err := json.Unmarshal([]byte(v1ResultFailure), &result) assert.NoError(err) assert.False(result.Success) pipelineStageCount := map[string]int{ "build": 2, "os": 9, } assert.Len(result.Log, len(pipelineStageCount)) for name, stageCount := range pipelineStageCount { assert.Contains(result.Log, name) assert.Len(result.Log[name], stageCount) for idx, stage := range result.Log[name] { // lastStage should be false, all else true lastStage := (name == "os") && (idx == pipelineStageCount["os"]-1) assert.Equal(stage.Success, !lastStage) } } buildLog := result.Log["build"] assert.Equal("org.osbuild.rpm", buildLog[0].Type) osLog := result.Log["os"] assert.False(osLog[8].Success) assert.Equal(osLog[0].Type, "org.osbuild.rpm") } func TestUnmarshalV2Success(t *testing.T) { assert := assert.New(t) var result Result err := json.Unmarshal([]byte(v2ResultSuccess), &result) assert.NoError(err) assert.True(result.Success) pipelineStageCount := map[string]int{ "build": 2, "ostree-tree": 7, "ostree-commit": 2, "container-tree": 4, "assembler": 1, } assert.Len(result.Log, len(pipelineStageCount)) for name, stageCount := range pipelineStageCount { assert.Contains(result.Log, name) assert.Len(result.Log[name], stageCount) for _, stage := range result.Log[name] { assert.True(stage.Success) } } // check metadata for _, pipeline := range result.Metadata { for stageType, stageMetadata := range pipeline { if stageType == "org.osbuild.rpm" { rpmMd, convOk := stageMetadata.(*RPMStageMetadata) assert.True(convOk) assert.Greater(len(rpmMd.Packages), 0) } else if stageType == "org.osbuild.ostree.commit" { commitMd, convOk := stageMetadata.(*OSTreeCommitStageMetadata) assert.True(convOk) assert.NotEmpty(commitMd.Compose.Ref) } } } } func TestUnmarshalV2Failure(t *testing.T) { assert := assert.New(t) var result Result err := json.Unmarshal([]byte(v2ResultFailure), &result) assert.NoError(err) assert.False(result.Success) pipelineStageCount := map[string]int{ "build": 2, "ostree-tree": 5, } assert.Len(result.Log, len(pipelineStageCount)) for name, stageCount := range pipelineStageCount { assert.Contains(result.Log, name) assert.Len(result.Log[name], stageCount) for idx, stage := range result.Log[name] { // success of last stage in last pipeline should be 'false' and // 'true' everywhere else (Success == !lastStage) lastStage := (name == "ostree-tree") && (idx == pipelineStageCount["ostree-tree"]-1) assert.Equal(stage.Success, !lastStage) } } } func TestWrite(t *testing.T) { assert := assert.New(t) result := Result{ Type: "result", Success: true, Error: []byte{}, Log: map[string]PipelineResult{ "build": { StageResult{ ID: "7de66f934df730534ea120a819480fb94913a5f448aa2fe6827c49d884cb9bd1", Type: "org.osbuild.rpm", Output: "", }, StageResult{ ID: "5fca77a102097ff631d7e125a838a42235c7bfbdbd45fd872a61e3f0805125c5", Type: "org.osbuild.selinux", Output: "", }, }, "os": { StageResult{ ID: "some ID", Type: "org.osbuild.rpm", Output: "", }, }, "final-pipeline": { StageResult{ ID: "assembler ID", Type: "org.osbuild.qcow2", Output: "assmelber the image", }, }, }, Metadata: map[string]PipelineMetadata{ "build": map[string]StageMetadata{ "org.osbuild.rpm": RPMStageMetadata{ Packages: []RPMPackageMetadata{ { Name: "fake-package", Version: "1", Release: "2", Arch: "x86_64", }, }, }, }, "os": map[string]StageMetadata{ "org.osbuild.rpm": RPMStageMetadata{ Packages: []RPMPackageMetadata{ { Name: "vim-minimal", Version: "8.0.1763", Release: "15.el8", Epoch: common.ToPtr("2"), Arch: "x86_64", SigMD5: "4b3ddc56cbb1be95e0973b4a98047820", SigPGP: "8902150305005ed77b28199e2f91fd431d510108a4141000995156bc9f610ad386ee49c42ab31c864fc605cae26592ba58f973fe97b54ea12b42c8e7ee2d716162714fe815de63b60cadb7400a0c71aa56dd3b0af656c6ea413eaaada53374e2e910e556d90e4d157a5b41a6540e355a0176fb3879bf17d90533d1aa3b3d23f06a99a42ad80f17498af2c321193b7be5a504f5dc759d6787a180f9fb3c1903be75f448429537eb0abeb96bb2e73cdc5fe91465c3d54154f6717ffd0a1b42a178e5093500d475639ef60ee483a1ec0d3148d23e0c2ab7bde7c68e5dfdd1103f8e9da7d53ec637c057bc1496d0504fe92760942f9f6de7382fbdef481489c7f6f943bf7fb8c8aadb6484569a6a8f074db78f84579dbaccc86c1eb49379b47033a9eca2577df00d60b353b08bc3850d852365792f194dd8b2b9ba4a1ad5c103afd4db853382520a64ecc362339f3642f4f1ad4e52d8f67b2e731b8d10cef29cb3ed05837245bfca37335f3760f3fb64cbf7acae7e18916a3d4272b0d1589320ab963123649eb9722c8c0e444952900caf39caa371fa77bec8a0e4b010f370eab3d4fe5653a38d88a5a4a415a89f917a31da856a4616ae07ce5749d90ac84bb9189263b162e0cf54ba58a8012d64c89196abae9113e0cda60b4e86879e23d8693691a234784ad3e161733798a0aa41416c045feeb8e2f5859a8a64272298da3d2c1ece675ee802fe8cb273e0b3c1b0f00960d3da09adbdbc531e", }, }, }, }, }} var b bytes.Buffer assert.NoError(result.Write(&b)) expectedOutput := `Pipeline build Stage org.osbuild.rpm Output: Metadata: { "packages": [ { "name": "fake-package", "version": "1", "release": "2", "epoch": null, "arch": "x86_64", "sigmd5": "", "sigpgp": "", "siggpg": "" } ] } Stage org.osbuild.selinux Output: Pipeline final-pipeline Stage org.osbuild.qcow2 Output: assmelber the image Pipeline os Stage org.osbuild.rpm Output: Metadata: { "packages": [ { "name": "vim-minimal", "version": "8.0.1763", "release": "15.el8", "epoch": "2", "arch": "x86_64", "sigmd5": "4b3ddc56cbb1be95e0973b4a98047820", "sigpgp": "8902150305005ed77b28199e2f91fd431d510108a4141000995156bc9f610ad386ee49c42ab31c864fc605cae26592ba58f973fe97b54ea12b42c8e7ee2d716162714fe815de63b60cadb7400a0c71aa56dd3b0af656c6ea413eaaada53374e2e910e556d90e4d157a5b41a6540e355a0176fb3879bf17d90533d1aa3b3d23f06a99a42ad80f17498af2c321193b7be5a504f5dc759d6787a180f9fb3c1903be75f448429537eb0abeb96bb2e73cdc5fe91465c3d54154f6717ffd0a1b42a178e5093500d475639ef60ee483a1ec0d3148d23e0c2ab7bde7c68e5dfdd1103f8e9da7d53ec637c057bc1496d0504fe92760942f9f6de7382fbdef481489c7f6f943bf7fb8c8aadb6484569a6a8f074db78f84579dbaccc86c1eb49379b47033a9eca2577df00d60b353b08bc3850d852365792f194dd8b2b9ba4a1ad5c103afd4db853382520a64ecc362339f3642f4f1ad4e52d8f67b2e731b8d10cef29cb3ed05837245bfca37335f3760f3fb64cbf7acae7e18916a3d4272b0d1589320ab963123649eb9722c8c0e444952900caf39caa371fa77bec8a0e4b010f370eab3d4fe5653a38d88a5a4a415a89f917a31da856a4616ae07ce5749d90ac84bb9189263b162e0cf54ba58a8012d64c89196abae9113e0cda60b4e86879e23d8693691a234784ad3e161733798a0aa41416c045feeb8e2f5859a8a64272298da3d2c1ece675ee802fe8cb273e0b3c1b0f00960d3da09adbdbc531e", "siggpg": "" } ] } ` assert.Equal(expectedOutput, b.String()) } func TestWriteEmpty(t *testing.T) { assert := assert.New(t) var b bytes.Buffer var testNilResult *Result assert.NoError(testNilResult.Write(&b)) assert.Equal("The compose result is empty.\n", b.String()) b.Reset() result := Result{} assert.NoError(result.Write(&b)) assert.Equal("The compose result is empty.\n", b.String()) }