// Copyright Earl Warren // Copyright Loïc Dachary // SPDX-License-Identifier: MIT package f3 import ( "context" "crypto/sha256" "fmt" "io" "path/filepath" "sort" "strings" "testing" "code.forgejo.org/f3/gof3/v3/f3" filesystem_options "code.forgejo.org/f3/gof3/v3/forges/filesystem/options" tests_repository "code.forgejo.org/f3/gof3/v3/forges/helpers/tests/repository" "code.forgejo.org/f3/gof3/v3/options" "code.forgejo.org/f3/gof3/v3/path" f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3" "code.forgejo.org/f3/gof3/v3/tree/generic" tests_forge "code.forgejo.org/f3/gof3/v3/tree/tests/f3/forge" "github.com/stretchr/testify/assert" ) func TestF3Mirror(t *testing.T) { ctx := context.Background() for _, factory := range tests_forge.GetFactories() { testForge := factory() t.Run(testForge.GetName(), func(t *testing.T) { // testCase.options will t.Skip if the forge instance is not up forgeWriteOptions := testForge.NewOptions(t) forgeReadOptions := testForge.NewOptions(t) forgeReadOptions.(options.URLInterface).SetURL(forgeWriteOptions.(options.URLInterface).GetURL()) fixtureTree := generic.GetFactory("f3")(ctx, tests_forge.GetFactory(filesystem_options.Name)().NewOptions(t)) fixtureTree.Trace("======= build fixture") TreeBuildPartial(t, "F3Mirror"+testForge.GetName(), testForge.GetKindExceptions(), forgeWriteOptions, fixtureTree) fixtureTree.Trace("======= mirror fixture to forge") forgeWriteTree := generic.GetFactory("f3")(ctx, forgeWriteOptions) generic.TreeMirror(ctx, fixtureTree, forgeWriteTree, generic.NewPathFromString(""), generic.NewMirrorOptions()) paths := []string{""} if testForge.GetName() != filesystem_options.Name { paths = []string{"/forge/users/10111", "/forge/users/20222"} } pathPairs := make([][2]path.Path, 0, 5) for _, p := range paths { p := generic.NewPathFromString(p) pathPairs = append(pathPairs, [2]path.Path{p, generic.TreePathRemap(ctx, fixtureTree, p, forgeWriteTree)}) } fixtureTree.Trace("======= read from forge") forgeReadTree := generic.GetFactory("f3")(ctx, forgeReadOptions) forgeReadTree.WalkAndGet(ctx, generic.NewWalkOptions(nil)) fixtureTree.Trace("======= mirror forge to filesystem") verificationTree := generic.GetFactory("f3")(ctx, tests_forge.GetFactory(filesystem_options.Name)().NewOptions(t)) for _, pathPair := range pathPairs { generic.TreeMirror(ctx, forgeReadTree, verificationTree, pathPair[1], generic.NewMirrorOptions()) } fixtureTree.Trace("======= compare fixture with forge mirrored to filesystem") for _, pathPair := range pathPairs { assert.True(t, generic.TreeCompare(ctx, fixtureTree, pathPair[0], verificationTree, pathPair[1])) } TreeDelete(t, testForge.GetNonTestUsers(), forgeWriteOptions, forgeWriteTree) }) } } func TestF3Tree(t *testing.T) { ctx := context.Background() verify := func(tree generic.TreeInterface, expected []string) { collected := make([]string, 0, 10) collect := func(ctx context.Context, path path.Path, node generic.NodeInterface) { path = path.Append(node) collected = append(collected, path.String()) } tree.WalkAndGet(ctx, generic.NewWalkOptions(collect)) sort.Strings(expected) sort.Strings(collected) assert.EqualValues(t, expected, collected) } for _, testCase := range []struct { name string build func(tree generic.TreeInterface) operations func(tree generic.TreeInterface) expected []string }{ { name: "full tree", build: func(tree generic.TreeInterface) { TreeBuild(t, "F3", nil, tree) }, operations: func(tree generic.TreeInterface) {}, expected: []string{ "", "/forge", "/forge/organizations", "/forge/organizations/3330001", "/forge/organizations/3330001/projects", "/forge/topics", "/forge/topics/14411441", "/forge/users", "/forge/users/10111", "/forge/users/10111/projects", "/forge/users/10111/projects/74823", "/forge/users/10111/projects/74823/issues", "/forge/users/10111/projects/74823/issues/1234567", "/forge/users/10111/projects/74823/issues/1234567/comments", "/forge/users/10111/projects/74823/issues/1234567/comments/1111999", "/forge/users/10111/projects/74823/issues/1234567/comments/1111999/reactions", "/forge/users/10111/projects/74823/issues/1234567/reactions", "/forge/users/10111/projects/74823/issues/1234567/reactions/1212", "/forge/users/10111/projects/74823/labels", "/forge/users/10111/projects/74823/labels/7777", "/forge/users/10111/projects/74823/labels/99999", "/forge/users/10111/projects/74823/milestones", "/forge/users/10111/projects/74823/milestones/7888", "/forge/users/10111/projects/74823/pull_requests", "/forge/users/10111/projects/74823/pull_requests/2222", "/forge/users/10111/projects/74823/pull_requests/2222/comments", "/forge/users/10111/projects/74823/pull_requests/2222/reactions", "/forge/users/10111/projects/74823/pull_requests/2222/reviews", "/forge/users/10111/projects/74823/pull_requests/2222/reviews/4593", "/forge/users/10111/projects/74823/pull_requests/2222/reviews/4593/reactions", "/forge/users/10111/projects/74823/pull_requests/2222/reviews/4593/reviewcomments", "/forge/users/10111/projects/74823/pull_requests/2222/reviews/4593/reviewcomments/9876543", "/forge/users/10111/projects/74823/releases", "/forge/users/10111/projects/74823/releases/123", "/forge/users/10111/projects/74823/releases/123/assets", "/forge/users/10111/projects/74823/releases/123/assets/585858", "/forge/users/10111/projects/74823/repositories", "/forge/users/10111/projects/74823/repositories/vcs", "/forge/users/20222", "/forge/users/20222/projects", "/forge/users/20222/projects/99099", "/forge/users/20222/projects/99099/issues", "/forge/users/20222/projects/99099/labels", "/forge/users/20222/projects/99099/milestones", "/forge/users/20222/projects/99099/pull_requests", "/forge/users/20222/projects/99099/releases", "/forge/users/20222/projects/99099/repositories", "/forge/users/20222/projects/99099/repositories/vcs", }, }, } { t.Run(testCase.name, func(t *testing.T) { tree := generic.GetFactory("f3")(ctx, tests_forge.GetFactory(filesystem_options.Name)().NewOptions(t)) tree.Trace("======= BUILD") testCase.build(tree) tree.Trace("======= OPERATIONS") testCase.operations(tree) tree.Trace("======= VERIFY") verify(tree, testCase.expected) tree.Clear(ctx) tree.Trace("======= VERIFY STEP 2") verify(tree, testCase.expected) tree.Trace("======= COMPARE") otherTree := generic.GetFactory("f3")(ctx, tests_forge.GetFactory(filesystem_options.Name)().NewOptions(t)) otherTree.GetOptions().(options.URLInterface).SetURL(tree.GetOptions().(options.URLInterface).GetURL()) otherTree.WalkAndGet(ctx, generic.NewWalkOptions(nil)) assert.True(t, generic.TreeCompare(ctx, tree, generic.NewPathFromString(""), otherTree, generic.NewPathFromString(""))) }) } } func TestF3Repository(t *testing.T) { ctx := context.Background() verify := func(tree generic.TreeInterface, name string) { repositoryPath := generic.NewPathFromString(filepath.Join("/forge/users/10111/projects/74823/repositories", name)) found := false tree.Apply(ctx, repositoryPath, generic.NewApplyOptions(func(ctx context.Context, parent, path path.Path, node generic.NodeInterface) { node.Get(ctx) node.List(ctx) if node.GetKind() != f3_tree.KindRepository { return } helper := tests_repository.NewTestHelper(t, "", node) helper.AssertRepositoryFileExists("README.md") if name == f3.RepositoryNameDefault { helper.AssertRepositoryTagExists("releasetagv12") helper.AssertRepositoryBranchExists("feature") } found = true }).SetWhere(generic.ApplyEachNode)) assert.True(t, found) } for _, name := range []string{f3.RepositoryNameDefault} { t.Run(name, func(t *testing.T) { tree := generic.GetFactory("f3")(ctx, tests_forge.GetFactory(filesystem_options.Name)().NewOptions(t)) tree.Trace("======= BUILD") TreeBuild(t, "F3", nil, tree) tree.Trace("======= VERIFY") verify(tree, name) tree.Clear(ctx) tree.Trace("======= VERIFY STEP 2") verify(tree, name) }) } } func TestF3Asset(t *testing.T) { ctx := context.Background() content := "OTHER CONTENT" expectedSHA256 := fmt.Sprintf("%x", sha256.Sum256([]byte(content))) opts := tests_forge.GetFactory(filesystem_options.Name)().NewOptions(t) { tree := generic.GetFactory("f3")(ctx, opts) TreeBuild(t, "F3", nil, tree) assetPath := generic.NewPathFromString("/forge/users/10111/projects/74823/releases/123/assets/585858") asset := tree.Find(assetPath) assert.False(t, asset.GetIsNil()) assetFormat := asset.ToFormat().(*f3.ReleaseAsset) assetFormat.DownloadFunc = func() io.ReadCloser { rc := io.NopCloser(strings.NewReader(content)) return rc } asset.FromFormat(assetFormat) asset.Upsert(ctx) assetFormat = asset.ToFormat().(*f3.ReleaseAsset) assert.EqualValues(t, expectedSHA256, assetFormat.SHA256) } { tree := generic.GetFactory("f3")(ctx, opts) tree.WalkAndGet(ctx, generic.NewWalkOptions(nil)) assetPath := generic.NewPathFromString("/forge/users/10111/projects/74823/releases/123/assets/585858") asset := tree.Find(assetPath) assert.False(t, asset.GetIsNil()) assetFormat := asset.ToFormat().(*f3.ReleaseAsset) assert.EqualValues(t, expectedSHA256, assetFormat.SHA256) } }