package store import ( "io/ioutil" "os" "testing" "time" "github.com/google/uuid" "github.com/stretchr/testify/suite" "github.com/osbuild/osbuild-composer/internal/blueprint" "github.com/osbuild/osbuild-composer/internal/common" "github.com/osbuild/osbuild-composer/internal/distro" "github.com/osbuild/osbuild-composer/internal/distro/test_distro" osbuild "github.com/osbuild/osbuild-composer/internal/osbuild1" "github.com/osbuild/osbuild-composer/internal/rpmmd" "github.com/osbuild/osbuild-composer/internal/target" ) //struct for sharing state between tests type storeTest struct { suite.Suite dir string myStore *Store myCustomizations blueprint.Customizations myBP blueprint.Blueprint CommitHash string myChange blueprint.Change myTarget *target.Target mySources map[string]osbuild.Source myCompose Compose myImageBuild ImageBuild mySourceConfig SourceConfig myDistro *test_distro.TestDistro myArch distro.Arch myImageType distro.ImageType myManifest distro.Manifest myRepoConfig []rpmmd.RepoConfig myPackageSpec []rpmmd.PackageSpec myImageOptions distro.ImageOptions } //func to initialize some default values before the suite is ran func (suite *storeTest) SetupSuite() { suite.myRepoConfig = []rpmmd.RepoConfig{rpmmd.RepoConfig{ Name: "testRepo", MirrorList: "testURL", }} suite.myPackageSpec = []rpmmd.PackageSpec{rpmmd.PackageSpec{}} suite.myDistro = test_distro.New() suite.myArch, _ = suite.myDistro.GetArch("test_arch") suite.myImageType, _ = suite.myArch.GetImageType("test_type") suite.myManifest, _ = suite.myImageType.Manifest(&suite.myCustomizations, suite.myImageOptions, suite.myRepoConfig, nil, 0) suite.mySourceConfig = SourceConfig{ Name: "testSourceConfig", } suite.myCompose = Compose{ Blueprint: &suite.myBP, ImageBuild: suite.myImageBuild, } suite.myImageBuild = ImageBuild{ ID: 123, } suite.mySources = make(map[string]osbuild.Source) suite.myCustomizations = blueprint.Customizations{} suite.myBP = blueprint.Blueprint{ Name: "testBP", Description: "Testing blueprint", Version: "0.0.1", Packages: []blueprint.Package{ {Name: "test1", Version: "*"}}, Modules: []blueprint.Package{ {Name: "test2", Version: "*"}}, Groups: []blueprint.Group{ {Name: "test3"}}, Customizations: &suite.myCustomizations, } suite.CommitHash = "firstCommit" suite.myChange = blueprint.Change{ Commit: "firstCommit", Message: "firstCommitMessage", Revision: nil, Timestamp: "now", Blueprint: suite.myBP, } suite.myTarget = &target.Target{ Uuid: uuid.New(), ImageName: "ImageName", Name: "Name", Created: time.Now(), Options: nil, } } //setup before each test func (suite *storeTest) SetupTest() { tmpDir, err := ioutil.TempDir("/tmp", "osbuild-composer-test-") suite.NoError(err) distro := test_distro.New() arch, err := distro.GetArch("test_arch") suite.NoError(err) suite.dir = tmpDir suite.myStore = New(&suite.dir, arch, nil) } //teardown after each test func (suite *storeTest) TearDownTest() { os.RemoveAll(suite.dir) } func (suite *storeTest) TestRandomSHA1String() { hash, err := randomSHA1String() suite.NoError(err) suite.Len(hash, 40) } //Check initial state of fields func (suite *storeTest) TestNewEmpty() { suite.Empty(suite.myStore.blueprints) suite.Empty(suite.myStore.workspace) suite.Empty(suite.myStore.composes) suite.Empty(suite.myStore.sources) suite.Empty(suite.myStore.blueprintsChanges) suite.Empty(suite.myStore.blueprintsCommits) suite.Equal(&suite.dir, suite.myStore.stateDir) } //Push a blueprint func (suite *storeTest) TestPushBlueprint() { suite.myStore.PushBlueprint(suite.myBP, "testing commit") suite.Equal(suite.myBP, suite.myStore.blueprints["testBP"]) //force a version bump suite.myStore.PushBlueprint(suite.myBP, "testing commit") suite.Equal("0.0.2", suite.myStore.blueprints["testBP"].Version) } //List the blueprint func (suite *storeTest) TestListBlueprints() { suite.myStore.blueprints["testBP"] = suite.myBP suite.Equal([]string{"testBP"}, suite.myStore.ListBlueprints()) } //Push a blueprint to workspace func (suite *storeTest) TestPushBlueprintToWorkspace() { suite.NoError(suite.myStore.PushBlueprintToWorkspace(suite.myBP)) suite.Equal(suite.myBP, suite.myStore.workspace["testBP"]) } func (suite *storeTest) TestGetBlueprint() { suite.myStore.blueprints["testBP"] = suite.myBP suite.myStore.workspace["WIPtestBP"] = suite.myBP //Get pushed BP actualBP, inWorkspace := suite.myStore.GetBlueprint("testBP") suite.Equal(&suite.myBP, actualBP) suite.False(inWorkspace) //Get BP in worskapce actualBP, inWorkspace = suite.myStore.GetBlueprint("WIPtestBP") suite.Equal(&suite.myBP, actualBP) suite.True(inWorkspace) //Try to get a non existing BP actualBP, inWorkspace = suite.myStore.GetBlueprint("Non_existing_BP") suite.Empty(actualBP) suite.False(inWorkspace) } func (suite *storeTest) TestGetBlueprintCommited() { suite.myStore.blueprints["testBP"] = suite.myBP //Get pushed BP actualBP := suite.myStore.GetBlueprintCommitted("testBP") suite.Equal(&suite.myBP, actualBP) //Try to get workspace BP actualBP = suite.myStore.GetBlueprintCommitted("WIPtestBP") suite.Empty(actualBP) } func (suite *storeTest) TestGetBlueprintChanges() { suite.myStore.blueprintsCommits["testBP"] = []string{"firstCommit", "secondCommit"} actualChanges := suite.myStore.GetBlueprintChanges("testBP") suite.Len(actualChanges, 2) } func (suite *storeTest) TestGetBlueprintChange() { Commit := make(map[string]blueprint.Change) Commit[suite.CommitHash] = suite.myChange suite.myStore.blueprintsCommits["testBP"] = []string{suite.CommitHash} suite.myStore.blueprintsChanges["testBP"] = Commit actualChange, err := suite.myStore.GetBlueprintChange("testBP", suite.CommitHash) suite.NoError(err) expectedChange := suite.myChange suite.Equal(&expectedChange, actualChange) //Try to get non existing BP actualChange, err = suite.myStore.GetBlueprintChange("Non_existing_BP", suite.CommitHash) suite.Nil(actualChange) suite.EqualError(err, "Unknown blueprint") //Try to get a non existing Commit actualChange, err = suite.myStore.GetBlueprintChange("testBP", "Non_existing_commit") suite.Nil(actualChange) suite.EqualError(err, "Unknown commit") } func (suite *storeTest) TestTagBlueprint() { Commit := make(map[string]blueprint.Change) Commit[suite.CommitHash] = suite.myChange suite.myStore.blueprints["testBP"] = suite.myBP suite.myStore.blueprintsCommits["testBP"] = []string{suite.CommitHash} suite.myStore.blueprintsChanges["testBP"] = Commit //Check that the blueprints change has no revision suite.Nil(suite.myStore.blueprintsChanges["testBP"][suite.CommitHash].Revision) suite.NoError(suite.myStore.TagBlueprint("testBP")) //The blueprints change should have a revision now actualRevision := suite.myStore.blueprintsChanges["testBP"][suite.CommitHash].Revision suite.Equal(1, *actualRevision) //Try to tag it again (should not change) suite.NoError(suite.myStore.TagBlueprint("testBP")) suite.Equal(1, *actualRevision) //Try to tag a non existing BNP suite.EqualError(suite.myStore.TagBlueprint("Non_existing_BP"), "Unknown blueprint") //Remove commits from a blueprint and try to tag it suite.myStore.blueprintsCommits["testBP"] = []string{} suite.EqualError(suite.myStore.TagBlueprint("testBP"), "No commits for blueprint") } func (suite *storeTest) TestDeleteBlueprint() { suite.myStore.blueprints["testBP"] = suite.myBP suite.NoError(suite.myStore.DeleteBlueprint("testBP")) suite.Empty(suite.myStore.blueprints) //Try to delete again (should return an error) suite.EqualError(suite.myStore.DeleteBlueprint("testBP"), "Unknown blueprint: testBP") } func (suite *storeTest) TestDeleteBlueprintFromWorkspace() { suite.myStore.workspace["WIPtestBP"] = suite.myBP suite.NoError(suite.myStore.DeleteBlueprintFromWorkspace("WIPtestBP")) suite.Empty(suite.myStore.workspace) //Try to delete again (should return an error) suite.EqualError(suite.myStore.DeleteBlueprintFromWorkspace("WIPtestBP"), "Unknown blueprint: WIPtestBP") } func (suite *storeTest) TestPushCompose() { testID := uuid.New() err := suite.myStore.PushCompose(testID, suite.myManifest, suite.myImageType, &suite.myBP, 123, nil, uuid.New()) suite.NoError(err) suite.Panics(func() { err = suite.myStore.PushCompose(testID, suite.myManifest, suite.myImageType, &suite.myBP, 123, []*target.Target{suite.myTarget}, uuid.New()) }) suite.NoError(err) testID = uuid.New() } func (suite *storeTest) TestPushTestCompose() { ID := uuid.New() err := suite.myStore.PushTestCompose(ID, suite.myManifest, suite.myImageType, &suite.myBP, 123, nil, true) suite.NoError(err) suite.Equal(common.ImageBuildState(2), suite.myStore.composes[ID].ImageBuild.QueueStatus) ID = uuid.New() err = suite.myStore.PushTestCompose(ID, suite.myManifest, suite.myImageType, &suite.myBP, 123, []*target.Target{suite.myTarget}, false) suite.NoError(err) suite.Equal(common.ImageBuildState(3), suite.myStore.composes[ID].ImageBuild.QueueStatus) } func (suite *storeTest) TestGetAllComposes() { suite.myStore.composes = make(map[uuid.UUID]Compose) suite.myStore.composes[uuid.New()] = suite.myCompose compose := suite.myStore.GetAllComposes() suite.Equal(suite.myStore.composes, compose) } func (suite *storeTest) TestDeleteCompose() { ID := uuid.New() suite.myStore.composes = make(map[uuid.UUID]Compose) suite.myStore.composes[ID] = suite.myCompose err := suite.myStore.DeleteCompose(ID) suite.NoError(err) suite.Equal(suite.myStore.composes, map[uuid.UUID]Compose{}) err = suite.myStore.DeleteCompose(ID) suite.Error(err) } func (suite *storeTest) TestDeleteSourceByName() { suite.myStore.sources = make(map[string]SourceConfig) suite.myStore.sources["testSource"] = suite.mySourceConfig suite.myStore.DeleteSourceByName("testSourceConfig") suite.Equal(map[string]SourceConfig{}, suite.myStore.sources) } func (suite *storeTest) TestDeleteSourceByID() { suite.myStore.sources = make(map[string]SourceConfig) suite.myStore.sources["testSource"] = suite.mySourceConfig suite.myStore.DeleteSourceByID("testSource") suite.Equal(map[string]SourceConfig{}, suite.myStore.sources) } func (suite *storeTest) TestPushSource() { expectedSource := map[string]SourceConfig{"testKey": SourceConfig{Name: "testSourceConfig", Type: "", URL: "", CheckGPG: false, CheckSSL: false, System: false}} suite.myStore.PushSource("testKey", suite.mySourceConfig) suite.Equal(expectedSource, suite.myStore.sources) } func (suite *storeTest) TestListSourcesByName() { suite.myStore.sources = make(map[string]SourceConfig) suite.myStore.sources["testSource"] = suite.mySourceConfig actualSources := suite.myStore.ListSourcesByName() suite.Equal([]string([]string{"testSourceConfig"}), actualSources) } func (suite *storeTest) TestListSourcesById() { suite.myStore.sources = make(map[string]SourceConfig) suite.myStore.sources["testSource"] = suite.mySourceConfig actualSources := suite.myStore.ListSourcesById() suite.Equal([]string([]string{"testSource"}), actualSources) } func (suite *storeTest) TestGetSource() { suite.myStore.sources = make(map[string]SourceConfig) suite.myStore.sources["testSource"] = suite.mySourceConfig expectedSource := SourceConfig(SourceConfig{Name: "testSourceConfig", Type: "", URL: "", CheckGPG: false, CheckSSL: false, System: false}) actualSource := suite.myStore.GetSource("testSource") suite.Equal(&expectedSource, actualSource) actualSource = suite.myStore.GetSource("nonExistingSource") suite.Nil(actualSource) } func (suite *storeTest) TestGetAllSourcesByName() { suite.myStore.sources = make(map[string]SourceConfig) suite.myStore.sources["testSource"] = suite.mySourceConfig expectedSource := map[string]SourceConfig{"testSourceConfig": SourceConfig{Name: "testSourceConfig", Type: "", URL: "", CheckGPG: false, CheckSSL: false, System: false}} actualSource := suite.myStore.GetAllSourcesByName() suite.Equal(expectedSource, actualSource) } func (suite *storeTest) TestGetAllSourcesByID() { suite.myStore.sources = make(map[string]SourceConfig) suite.myStore.sources["testSource"] = suite.mySourceConfig expectedSource := map[string]SourceConfig{"testSource": SourceConfig{Name: "testSourceConfig", Type: "", URL: "", CheckGPG: false, CheckSSL: false, System: false}} actualSource := suite.myStore.GetAllSourcesByID() suite.Equal(expectedSource, actualSource) } func (suite *storeTest) TestNewSourceConfigWithBaseURL() { myRepoConfig := rpmmd.RepoConfig{ Name: "testRepo", BaseURL: "testURL", CheckGPG: true, } expectedSource := SourceConfig{Name: "testRepo", Type: "yum-baseurl", URL: "testURL", CheckGPG: true, CheckSSL: true, System: true} actualSource := NewSourceConfig(myRepoConfig, true) suite.Equal(expectedSource, actualSource) } func (suite *storeTest) TestNewSourceConfigWithMetaLink() { myRepoConfig := rpmmd.RepoConfig{ Name: "testRepo", Metalink: "testURL", CheckGPG: true, } expectedSource := SourceConfig{Name: "testRepo", Type: "yum-metalink", URL: "testURL", CheckGPG: true, CheckSSL: true, System: true} actualSource := NewSourceConfig(myRepoConfig, true) suite.Equal(expectedSource, actualSource) } func (suite *storeTest) TestNewSourceConfigWithMirrorList() { myRepoConfig := rpmmd.RepoConfig{ Name: "testRepo", MirrorList: "testURL", } expectedSource := SourceConfig{Name: "testRepo", Type: "yum-mirrorlist", URL: "testURL", CheckGPG: false, CheckSSL: true, System: true} actualSource := NewSourceConfig(myRepoConfig, true) suite.Equal(expectedSource, actualSource) } func (suite *storeTest) TestRepoConfigBaseURL() { expectedRepo := rpmmd.RepoConfig{Name: "testSourceConfig", BaseURL: "testURL", Metalink: "", MirrorList: "", GPGKey: "", IgnoreSSL: true, MetadataExpire: ""} suite.mySourceConfig.Type = "yum-baseurl" suite.mySourceConfig.URL = "testURL" actualRepo := suite.mySourceConfig.RepoConfig("testSourceConfig") suite.Equal(expectedRepo, actualRepo) } func (suite *storeTest) TestRepoConfigMetalink() { expectedRepo := rpmmd.RepoConfig{Name: "testSourceConfig", BaseURL: "", Metalink: "testURL", MirrorList: "", GPGKey: "", IgnoreSSL: true, MetadataExpire: ""} suite.mySourceConfig.Type = "yum-metalink" suite.mySourceConfig.URL = "testURL" actualRepo := suite.mySourceConfig.RepoConfig("testSourceConfig") suite.Equal(expectedRepo, actualRepo) } func (suite *storeTest) TestRepoConfigMirrorlist() { expectedRepo := rpmmd.RepoConfig{Name: "testSourceConfig", BaseURL: "", Metalink: "", MirrorList: "testURL", GPGKey: "", IgnoreSSL: true, MetadataExpire: ""} suite.mySourceConfig.Type = "yum-mirrorlist" suite.mySourceConfig.URL = "testURL" actualRepo := suite.mySourceConfig.RepoConfig("testSourceConfig") suite.Equal(expectedRepo, actualRepo) } func TestStore(t *testing.T) { suite.Run(t, new(storeTest)) }