mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-26 06:16:56 +09:00
test: consolidate Go tests (#39962)
Consolidate all Go tests. Coverage is identical to before. Go tests are around 5% faster while being 7% smaller. No non-test code is touched.
This commit is contained in:
1 parent
ce7364e215
commit
8abda62312
388 files changed
+18410
-29561
No files matched your search
@@ -77,12 +77,6 @@ func TestCanGithubEventMatch(t *testing.T) {
|
||||
webhook_module.HookEventPullRequest,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pull_request_target cannot match",
|
||||
GithubEventPullRequest,
|
||||
webhook_module.HookEventPullRequestComment,
|
||||
false,
|
||||
},
|
||||
// pull_request_review event
|
||||
{
|
||||
"pull_request_review matches",
|
||||
|
||||
@@ -18,72 +18,21 @@ import (
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
options []ParseOption
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "multiple_jobs",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "multiple_matrix",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "has_needs",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "has_with",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "has_secrets",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "empty_step",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "job_name_with_matrix",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "prefixed_newline",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "continue_on_error_expr",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
invalidFileTests := []struct {
|
||||
name string
|
||||
}{
|
||||
{name: "null_job_implicit"},
|
||||
{name: "null_job_explicit"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
content := ReadTestdata(t, tt.name+".in.yaml")
|
||||
want := ReadTestdata(t, tt.name+".out.yaml")
|
||||
got, err := Parse(content, append([]ParseOption{WithGitContext(&model.GithubContext{})}, tt.options...)...)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
}
|
||||
for _, name := range []string{
|
||||
"multiple_jobs",
|
||||
"multiple_matrix",
|
||||
"has_needs",
|
||||
"has_with",
|
||||
"has_secrets",
|
||||
"empty_step",
|
||||
"job_name_with_matrix",
|
||||
"prefixed_newline",
|
||||
"continue_on_error_expr",
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
content := ReadTestdata(t, name+".in.yaml")
|
||||
want := ReadTestdata(t, name+".out.yaml")
|
||||
got, err := Parse(content, WithGitContext(&model.GithubContext{}))
|
||||
require.NoError(t, err)
|
||||
|
||||
builder := &strings.Builder{}
|
||||
@@ -102,9 +51,9 @@ func TestParse(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
for _, tt := range invalidFileTests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
content := ReadTestdata(t, tt.name+".in.yaml")
|
||||
for _, name := range []string{"null_job_implicit", "null_job_explicit"} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
content := ReadTestdata(t, name+".in.yaml")
|
||||
require.NotPanics(t, func() {
|
||||
_, err := Parse(content)
|
||||
require.Error(t, err)
|
||||
@@ -460,6 +409,8 @@ func TestExpandMatrixWithNeeds(t *testing.T) {
|
||||
{"empty vector", "\n version: ${{ fromJson(needs.setup.outputs.empty) }}\n", `Matrix vector "version" does not contain any values`},
|
||||
{"empty include", "\n include: ${{ fromJson(needs.setup.outputs.empty) }}\n", "Matrix must define at least one vector"},
|
||||
{"whole matrix not a mapping", " ${{ fromJson(needs.setup.outputs.empty) }}\n", `Matrix "" is not a map of matrix keys to values`},
|
||||
{"unresolved need", "\n v: ${{ fromJson(needs.missing.outputs.v) }}\n", "evaluate matrix"},
|
||||
{"invalid strategy field", "\n os: [linux]\nmax-parallel: ${{ fromJSON('bad') }}\n", "evaluate strategy"},
|
||||
} {
|
||||
t.Run(tt.name+" errors", func(t *testing.T) {
|
||||
_, err := expand(t, tt.matrix)
|
||||
@@ -475,16 +426,6 @@ func TestExpandMatrixWithNeeds(t *testing.T) {
|
||||
assert.Equal(t, 1, got[0].Strategy.JobTotal)
|
||||
})
|
||||
|
||||
t.Run("unresolved need errors", func(t *testing.T) {
|
||||
_, err := expand(t, "\n v: ${{ fromJson(needs.missing.outputs.v) }}\n")
|
||||
require.ErrorContains(t, err, "evaluate matrix")
|
||||
})
|
||||
|
||||
t.Run("invalid strategy field errors", func(t *testing.T) {
|
||||
_, err := expand(t, "\n os: [linux]\nmax-parallel: ${{ fromJSON('bad') }}\n")
|
||||
require.ErrorContains(t, err, "evaluate strategy")
|
||||
})
|
||||
|
||||
// The combination count comes from a runtime output, so it must be rejected before one Job per
|
||||
// combination is built rather than after.
|
||||
t.Run("too many combinations errors", func(t *testing.T) {
|
||||
|
||||
@@ -332,29 +332,17 @@ func TestSingleWorkflow_SetJob(t *testing.T) {
|
||||
|
||||
func TestGetContinueOnError(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
yaml string
|
||||
want bool
|
||||
name string
|
||||
continueOnError string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "absent",
|
||||
yaml: "name: test\non: push\njobs:\n job1:\n runs-on: ubuntu-22.04\n steps:\n - run: echo hi\n",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "static true",
|
||||
yaml: "name: test\non: push\njobs:\n job1:\n runs-on: ubuntu-22.04\n continue-on-error: true\n steps:\n - run: echo hi\n",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "static false",
|
||||
yaml: "name: test\non: push\njobs:\n job1:\n runs-on: ubuntu-22.04\n continue-on-error: false\n steps:\n - run: echo hi\n",
|
||||
want: false,
|
||||
},
|
||||
{name: "absent", want: false},
|
||||
{name: "static true", continueOnError: " continue-on-error: true\n", want: true},
|
||||
{name: "static false", continueOnError: " continue-on-error: false\n", want: false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := Parse([]byte(tt.yaml))
|
||||
got, err := Parse(fmt.Appendf(nil, "name: test\non: push\njobs:\n job1:\n runs-on: ubuntu-22.04\n%s steps:\n - run: echo hi\n", tt.continueOnError))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, got, 1)
|
||||
_, job := got[0].Job()
|
||||
|
||||
@@ -13,404 +13,214 @@ import (
|
||||
|
||||
func TestMatchPattern(t *testing.T) {
|
||||
kases := []struct {
|
||||
inputs []string
|
||||
inputs [][]string
|
||||
patterns []string
|
||||
skipResult bool
|
||||
filterResult bool
|
||||
}{
|
||||
{
|
||||
patterns: []string{"*"},
|
||||
inputs: []string{"path/with/slash"},
|
||||
inputs: [][]string{{"path/with/slash"}},
|
||||
skipResult: true,
|
||||
filterResult: false,
|
||||
},
|
||||
{
|
||||
patterns: []string{"path/a", "path/b", "path/c"},
|
||||
inputs: []string{"meta", "path/b", "otherfile"},
|
||||
inputs: [][]string{{"meta", "path/b", "otherfile"}},
|
||||
skipResult: false,
|
||||
filterResult: false,
|
||||
},
|
||||
{
|
||||
patterns: []string{"path/a", "path/b", "path/c"},
|
||||
inputs: []string{"path/b"},
|
||||
inputs: [][]string{{"path/b"}, {"path/c", "path/b"}, {"path/c", "path/b", "path/a"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"path/a", "path/b", "path/c"},
|
||||
inputs: []string{"path/c", "path/b"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"path/a", "path/b", "path/c"},
|
||||
inputs: []string{"path/c", "path/b", "path/a"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"path/a", "path/b", "path/c"},
|
||||
inputs: []string{"path/c", "path/b", "path/d", "path/a"},
|
||||
inputs: [][]string{{"path/c", "path/b", "path/d", "path/a"}},
|
||||
skipResult: false,
|
||||
filterResult: false,
|
||||
},
|
||||
{
|
||||
patterns: []string{},
|
||||
inputs: []string{},
|
||||
inputs: [][]string{{}},
|
||||
skipResult: false,
|
||||
filterResult: false,
|
||||
},
|
||||
{
|
||||
patterns: []string{"\\!file"},
|
||||
inputs: []string{"!file"},
|
||||
inputs: [][]string{{"!file"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"escape\\\\backslash"},
|
||||
inputs: []string{"escape\\backslash"},
|
||||
inputs: [][]string{{"escape\\backslash"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{".yml"},
|
||||
inputs: []string{"fyml"},
|
||||
inputs: [][]string{{"fyml"}},
|
||||
skipResult: true,
|
||||
filterResult: false,
|
||||
},
|
||||
// https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#patterns-to-match-branches-and-tags
|
||||
{
|
||||
patterns: []string{"feature/*"},
|
||||
inputs: []string{"feature/my-branch"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"feature/*"},
|
||||
inputs: []string{"feature/your-branch"},
|
||||
inputs: [][]string{{"feature/my-branch"}, {"feature/your-branch"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"feature/**"},
|
||||
inputs: []string{"feature/beta-a/my-branch"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"feature/**"},
|
||||
inputs: []string{"feature/beta-a/my-branch"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"feature/**"},
|
||||
inputs: []string{"feature/mona/the/octocat"},
|
||||
inputs: [][]string{{"feature/beta-a/my-branch"}, {"feature/mona/the/octocat"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"main", "releases/mona-the-octocat"},
|
||||
inputs: []string{"main"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"main", "releases/mona-the-octocat"},
|
||||
inputs: []string{"releases/mona-the-octocat"},
|
||||
inputs: [][]string{{"main"}, {"releases/mona-the-octocat"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*"},
|
||||
inputs: []string{"main"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*"},
|
||||
inputs: []string{"releases"},
|
||||
inputs: [][]string{{"main"}, {"releases"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**"},
|
||||
inputs: []string{"all/the/branches"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**"},
|
||||
inputs: []string{"every/tag"},
|
||||
inputs: [][]string{{"all/the/branches"}, {"every/tag"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*feature"},
|
||||
inputs: []string{"mona-feature"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*feature"},
|
||||
inputs: []string{"feature"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*feature"},
|
||||
inputs: []string{"ver-10-feature"},
|
||||
inputs: [][]string{{"mona-feature"}, {"feature"}, {"ver-10-feature"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"v2*"},
|
||||
inputs: []string{"v2"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"v2*"},
|
||||
inputs: []string{"v2.0"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"v2*"},
|
||||
inputs: []string{"v2.9"},
|
||||
inputs: [][]string{{"v2"}, {"v2.0"}, {"v2.9"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"v[12].[0-9]+.[0-9]+"},
|
||||
inputs: []string{"v1.10.1"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"v[12].[0-9]+.[0-9]+"},
|
||||
inputs: []string{"v2.0.0"},
|
||||
inputs: [][]string{{"v1.10.1"}, {"v2.0.0"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
// https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#patterns-to-match-file-paths
|
||||
{
|
||||
patterns: []string{"*"},
|
||||
inputs: []string{"README.md"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*"},
|
||||
inputs: []string{"server.rb"},
|
||||
inputs: [][]string{{"README.md"}, {"server.rb"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*.jsx?"},
|
||||
inputs: []string{"page.js"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*.jsx?"},
|
||||
inputs: []string{"page.jsx"},
|
||||
inputs: [][]string{{"page.js"}, {"page.jsx"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**"},
|
||||
inputs: []string{"all/the/files.md"},
|
||||
inputs: [][]string{{"all/the/files.md"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*.js"},
|
||||
inputs: []string{"app.js"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*.js"},
|
||||
inputs: []string{"index.js"},
|
||||
inputs: [][]string{{"app.js"}, {"index.js"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**.js"},
|
||||
inputs: []string{"index.js"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**.js"},
|
||||
inputs: []string{"js/index.js"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**.js"},
|
||||
inputs: []string{"src/js/app.js"},
|
||||
inputs: [][]string{{"index.js"}, {"js/index.js"}, {"src/js/app.js"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"docs/*"},
|
||||
inputs: []string{"docs/README.md"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"docs/*"},
|
||||
inputs: []string{"docs/file.txt"},
|
||||
inputs: [][]string{{"docs/README.md"}, {"docs/file.txt"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"docs/**"},
|
||||
inputs: []string{"docs/README.md"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"docs/**"},
|
||||
inputs: []string{"docs/mona/octocat.txt"},
|
||||
inputs: [][]string{{"docs/README.md"}, {"docs/mona/octocat.txt"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"docs/**/*.md"},
|
||||
inputs: []string{"docs/README.md"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"docs/**/*.md"},
|
||||
inputs: []string{"docs/mona/hello-world.md"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"docs/**/*.md"},
|
||||
inputs: []string{"docs/a/markdown/file.md"},
|
||||
inputs: [][]string{{"docs/README.md"}, {"docs/mona/hello-world.md"}, {"docs/a/markdown/file.md"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**/docs/**"},
|
||||
inputs: []string{"docs/hello.md"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**/docs/**"},
|
||||
inputs: []string{"dir/docs/my-file.txt"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**/docs/**"},
|
||||
inputs: []string{"space/docs/plan/space.doc"},
|
||||
inputs: [][]string{{"docs/hello.md"}, {"dir/docs/my-file.txt"}, {"space/docs/plan/space.doc"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**/README.md"},
|
||||
inputs: []string{"README.md"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**/README.md"},
|
||||
inputs: []string{"js/README.md"},
|
||||
inputs: [][]string{{"README.md"}, {"js/README.md"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**/*src/**"},
|
||||
inputs: []string{"a/src/app.js"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**/*src/**"},
|
||||
inputs: []string{"my-src/code/js/app.js"},
|
||||
inputs: [][]string{{"a/src/app.js"}, {"my-src/code/js/app.js"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**/*-post.md"},
|
||||
inputs: []string{"my-post.md"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**/*-post.md"},
|
||||
inputs: []string{"path/their-post.md"},
|
||||
inputs: [][]string{{"my-post.md"}, {"path/their-post.md"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**/migrate-*.sql"},
|
||||
inputs: []string{"migrate-10909.sql"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**/migrate-*.sql"},
|
||||
inputs: []string{"db/migrate-v1.0.sql"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"**/migrate-*.sql"},
|
||||
inputs: []string{"db/sept/migrate-v1.sql"},
|
||||
inputs: [][]string{{"migrate-10909.sql"}, {"db/migrate-v1.0.sql"}, {"db/sept/migrate-v1.sql"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*.md", "!README.md"},
|
||||
inputs: []string{"hello.md"},
|
||||
inputs: [][]string{{"hello.md"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*.md", "!README.md"},
|
||||
inputs: []string{"README.md"},
|
||||
skipResult: true,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*.md", "!README.md"},
|
||||
inputs: []string{"docs/hello.md"},
|
||||
inputs: [][]string{{"README.md"}, {"docs/hello.md"}},
|
||||
skipResult: true,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*.md", "!README.md", "README*"},
|
||||
inputs: []string{"hello.md"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*.md", "!README.md", "README*"},
|
||||
inputs: []string{"README.md"},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
{
|
||||
patterns: []string{"*.md", "!README.md", "README*"},
|
||||
inputs: []string{"README.doc"},
|
||||
inputs: [][]string{{"hello.md"}, {"README.md"}, {"README.doc"}},
|
||||
skipResult: false,
|
||||
filterResult: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, kase := range kases {
|
||||
msg := fmt.Sprintf("patterns=%s, input=%s", strings.Join(kase.patterns, ","), strings.Join(kase.inputs, ","))
|
||||
patterns, err := CompilePatterns(kase.patterns...)
|
||||
assert.NoError(t, err, "compile error: %s", msg)
|
||||
assert.Equal(t, kase.skipResult, Skip(patterns, kase.inputs), "unexpected skip result: %s", msg)
|
||||
assert.Equal(t, kase.filterResult, Filter(patterns, kase.inputs), "unexpected filter result: %s", msg)
|
||||
for _, inputs := range kase.inputs {
|
||||
msg := fmt.Sprintf("patterns=%s, input=%s", strings.Join(kase.patterns, ","), strings.Join(inputs, ","))
|
||||
patterns, err := CompilePatterns(kase.patterns...)
|
||||
assert.NoError(t, err, "compile error: %s", msg)
|
||||
assert.Equal(t, kase.skipResult, Skip(patterns, inputs), "unexpected skip result: %s", msg)
|
||||
assert.Equal(t, kase.filterResult, Filter(patterns, inputs), "unexpected filter result: %s", msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -281,6 +281,24 @@ func TestDetectMatched(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMatchIssuesEvent(t *testing.T) {
|
||||
labelChangesPayload := func() *api.IssuePayload {
|
||||
return &api.IssuePayload{
|
||||
Action: api.HookIssueLabelUpdated,
|
||||
Issue: &api.Issue{
|
||||
Labels: []*api.Label{
|
||||
{ID: 789, Name: "new-label"},
|
||||
},
|
||||
},
|
||||
Changes: &api.ChangesPayload{
|
||||
AddedLabels: []*api.Label{
|
||||
{ID: 789, Name: "new-label"},
|
||||
},
|
||||
RemovedLabels: []*api.Label{
|
||||
{ID: 123, Name: "deleted-label"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
testCases := []struct {
|
||||
desc string
|
||||
payload *api.IssuePayload
|
||||
@@ -358,67 +376,22 @@ func TestMatchIssuesEvent(t *testing.T) {
|
||||
eventType: "unlabeled",
|
||||
},
|
||||
{
|
||||
desc: "Both adding and removing labels should trigger labeled event",
|
||||
payload: &api.IssuePayload{
|
||||
Action: api.HookIssueLabelUpdated,
|
||||
Issue: &api.Issue{
|
||||
Labels: []*api.Label{
|
||||
{ID: 789, Name: "new-label"},
|
||||
},
|
||||
},
|
||||
Changes: &api.ChangesPayload{
|
||||
AddedLabels: []*api.Label{
|
||||
{ID: 789, Name: "new-label"},
|
||||
},
|
||||
RemovedLabels: []*api.Label{
|
||||
{ID: 123, Name: "deleted-label"},
|
||||
},
|
||||
},
|
||||
},
|
||||
desc: "Both adding and removing labels should trigger labeled event",
|
||||
payload: labelChangesPayload(),
|
||||
yamlOn: "on:\n issues:\n types: [labeled]",
|
||||
expected: true,
|
||||
eventType: "labeled",
|
||||
},
|
||||
{
|
||||
desc: "Both adding and removing labels should trigger unlabeled event",
|
||||
payload: &api.IssuePayload{
|
||||
Action: api.HookIssueLabelUpdated,
|
||||
Issue: &api.Issue{
|
||||
Labels: []*api.Label{
|
||||
{ID: 789, Name: "new-label"},
|
||||
},
|
||||
},
|
||||
Changes: &api.ChangesPayload{
|
||||
AddedLabels: []*api.Label{
|
||||
{ID: 789, Name: "new-label"},
|
||||
},
|
||||
RemovedLabels: []*api.Label{
|
||||
{ID: 123, Name: "deleted-label"},
|
||||
},
|
||||
},
|
||||
},
|
||||
desc: "Both adding and removing labels should trigger unlabeled event",
|
||||
payload: labelChangesPayload(),
|
||||
yamlOn: "on:\n issues:\n types: [unlabeled]",
|
||||
expected: true,
|
||||
eventType: "unlabeled",
|
||||
},
|
||||
{
|
||||
desc: "Both adding and removing labels should trigger both events",
|
||||
payload: &api.IssuePayload{
|
||||
Action: api.HookIssueLabelUpdated,
|
||||
Issue: &api.Issue{
|
||||
Labels: []*api.Label{
|
||||
{ID: 789, Name: "new-label"},
|
||||
},
|
||||
},
|
||||
Changes: &api.ChangesPayload{
|
||||
AddedLabels: []*api.Label{
|
||||
{ID: 789, Name: "new-label"},
|
||||
},
|
||||
RemovedLabels: []*api.Label{
|
||||
{ID: 123, Name: "deleted-label"},
|
||||
},
|
||||
},
|
||||
},
|
||||
desc: "Both adding and removing labels should trigger both events",
|
||||
payload: labelChangesPayload(),
|
||||
yamlOn: "on:\n issues:\n types: [labeled, unlabeled]",
|
||||
expected: true,
|
||||
eventType: "multiple",
|
||||
|
||||
@@ -74,34 +74,22 @@ func TestLayered(t *testing.T) {
|
||||
|
||||
assertRead("", fs.ErrNotExist, "no-such")
|
||||
|
||||
files, err := assets.ListFiles(".", true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{"f1", "f2", "fa"}, files)
|
||||
|
||||
files, err = assets.ListFiles(".", false)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{"d1", "d2", "da"}, files)
|
||||
|
||||
files, err = assets.ListFiles(".")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{"d1", "d2", "da", "f1", "f2", "fa"}, files)
|
||||
|
||||
files, err = assets.ListAllFiles(".", true)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{"d1/f", "d2/f", "da/f", "f1", "f2", "fa"}, files)
|
||||
|
||||
files, err = assets.ListAllFiles(".", false)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{"d1", "d2", "da", "da/sub1", "da/sub2"}, files)
|
||||
|
||||
files, err = assets.ListAllFiles(".")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{
|
||||
assertList := func(listFiles func(string, ...bool) ([]string, error), expected []string, fileMode ...bool) {
|
||||
files, err := listFiles(".", fileMode...)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, files)
|
||||
}
|
||||
assertList(assets.ListFiles, []string{"f1", "f2", "fa"}, true)
|
||||
assertList(assets.ListFiles, []string{"d1", "d2", "da"}, false)
|
||||
assertList(assets.ListFiles, []string{"d1", "d2", "da", "f1", "f2", "fa"})
|
||||
assertList(assets.ListAllFiles, []string{"d1/f", "d2/f", "da/f", "f1", "f2", "fa"}, true)
|
||||
assertList(assets.ListAllFiles, []string{"d1", "d2", "da", "da/sub1", "da/sub2"}, false)
|
||||
assertList(assets.ListAllFiles, []string{
|
||||
"d1", "d1/f",
|
||||
"d2", "d2/f",
|
||||
"da", "da/f", "da/sub1", "da/sub2",
|
||||
"f1", "f2", "fa",
|
||||
}, files)
|
||||
})
|
||||
|
||||
assert.Empty(t, assets.GetFileLayerName("no-such"))
|
||||
assert.Equal(t, "l1", assets.GetFileLayerName("f1"))
|
||||
|
||||
@@ -48,7 +48,7 @@ func TestComplexity_Generate(t *testing.T) {
|
||||
const maxCount = 50
|
||||
const pwdLen = 50
|
||||
|
||||
test := func(t *testing.T, modes []string) {
|
||||
for _, modes := range [][]string{{"lower"}, {"upper"}, {"lower", "upper", "spec"}, {"off"}, {""}} {
|
||||
testComplextity(modes)
|
||||
for range maxCount {
|
||||
pwd, err := Generate(pwdLen)
|
||||
@@ -58,12 +58,6 @@ func TestComplexity_Generate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
test(t, []string{"lower"})
|
||||
test(t, []string{"upper"})
|
||||
test(t, []string{"lower", "upper", "spec"})
|
||||
test(t, []string{"off"})
|
||||
test(t, []string{""})
|
||||
|
||||
// Remove settings for other tests
|
||||
testComplextity([]string{"off"})
|
||||
}
|
||||
|
||||
@@ -47,25 +47,21 @@ func TestPassword(t *testing.T) {
|
||||
assert.ErrorContains(t, err, "password cannot be empty")
|
||||
assert.EqualValues(t, -1, count)
|
||||
|
||||
count, err = client.CheckPassword(ctx, "pwned", false)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 1, count)
|
||||
|
||||
count, err = client.CheckPassword(ctx, "notpwned", false)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 0, count)
|
||||
|
||||
count, err = client.CheckPassword(ctx, "paddedpwned", true)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 1, count)
|
||||
|
||||
count, err = client.CheckPassword(ctx, "paddednotpwned", true)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 0, count)
|
||||
|
||||
count, err = client.CheckPassword(ctx, "paddednotpwnedzero", true)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 0, count)
|
||||
for _, test := range []struct {
|
||||
password string
|
||||
padding bool
|
||||
count int
|
||||
}{
|
||||
{"pwned", false, 1},
|
||||
{"notpwned", false, 0},
|
||||
{"paddedpwned", true, 1},
|
||||
{"paddednotpwned", true, 0},
|
||||
{"paddednotpwnedzero", true, 0},
|
||||
} {
|
||||
count, err = client.CheckPassword(ctx, test.password, test.padding)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, test.count, count)
|
||||
}
|
||||
|
||||
count, err = client.CheckPassword(ctx, "ratelimited", false)
|
||||
assert.Error(t, err)
|
||||
|
||||
@@ -16,26 +16,19 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_ProcessAvatarPNG(t *testing.T) {
|
||||
setting.Avatar.MaxWidth = 4096
|
||||
setting.Avatar.MaxHeight = 4096
|
||||
func Test_ProcessAvatarFormats(t *testing.T) {
|
||||
for _, format := range []string{"png", "jpeg"} {
|
||||
t.Run(format, func(t *testing.T) {
|
||||
setting.Avatar.MaxWidth = 4096
|
||||
setting.Avatar.MaxHeight = 4096
|
||||
|
||||
data, err := os.ReadFile("testdata/avatar.png")
|
||||
assert.NoError(t, err)
|
||||
data, err := os.ReadFile("testdata/avatar." + format)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = processAvatarImage(data, 262144)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func Test_ProcessAvatarJPEG(t *testing.T) {
|
||||
setting.Avatar.MaxWidth = 4096
|
||||
setting.Avatar.MaxHeight = 4096
|
||||
|
||||
data, err := os.ReadFile("testdata/avatar.jpeg")
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = processAvatarImage(data, 262144)
|
||||
assert.NoError(t, err)
|
||||
_, err = processAvatarImage(data, 262144)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_ProcessAvatarInvalidData(t *testing.T) {
|
||||
|
||||
@@ -87,90 +87,64 @@ func TestToUTF8(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestToUTF8WithFallback(t *testing.T) {
|
||||
// "ABC"
|
||||
res := ToUTF8WithFallback([]byte{0x41, 0x42, 0x43}, ConvertOpts{})
|
||||
assert.Equal(t, []byte{0x41, 0x42, 0x43}, res)
|
||||
for _, converter := range []struct {
|
||||
name string
|
||||
convert func([]byte) []byte
|
||||
}{
|
||||
{"fallback", func(content []byte) []byte { return ToUTF8WithFallback(content, ConvertOpts{}) }},
|
||||
{"drop errors", ToUTF8DropErrors},
|
||||
} {
|
||||
t.Run(converter.name, func(t *testing.T) {
|
||||
// "ABC"
|
||||
res := converter.convert([]byte{0x41, 0x42, 0x43})
|
||||
assert.Equal(t, []byte{0x41, 0x42, 0x43}, res)
|
||||
|
||||
// "áéíóú"
|
||||
res = ToUTF8WithFallback([]byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, ConvertOpts{})
|
||||
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, res)
|
||||
// "áéíóú"
|
||||
res = converter.convert([]byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba})
|
||||
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, res)
|
||||
|
||||
// UTF8 BOM + "áéíóú"
|
||||
res = ToUTF8WithFallback([]byte{0xef, 0xbb, 0xbf, 0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, ConvertOpts{})
|
||||
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, res)
|
||||
// UTF8 BOM + "áéíóú"
|
||||
res = converter.convert([]byte{0xef, 0xbb, 0xbf, 0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba})
|
||||
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, res)
|
||||
|
||||
// "Hola, así cómo ños"
|
||||
res = ToUTF8WithFallback([]byte{
|
||||
0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63,
|
||||
0xF3, 0x6D, 0x6F, 0x20, 0xF1, 0x6F, 0x73,
|
||||
}, ConvertOpts{})
|
||||
assert.Equal(t, []byte{
|
||||
0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xC3, 0xAD, 0x20, 0x63,
|
||||
0xC3, 0xB3, 0x6D, 0x6F, 0x20, 0xC3, 0xB1, 0x6F, 0x73,
|
||||
}, res)
|
||||
// "Hola, así cómo ños"
|
||||
res = converter.convert([]byte{
|
||||
0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63,
|
||||
0xF3, 0x6D, 0x6F, 0x20, 0xF1, 0x6F, 0x73,
|
||||
})
|
||||
if converter.name == "fallback" {
|
||||
assert.Equal(t, []byte{
|
||||
0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xC3, 0xAD, 0x20, 0x63,
|
||||
0xC3, 0xB3, 0x6D, 0x6F, 0x20, 0xC3, 0xB1, 0x6F, 0x73,
|
||||
}, res)
|
||||
} else {
|
||||
assert.Equal(t, []byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73}, res[:8])
|
||||
assert.Equal(t, []byte{0x73}, res[len(res)-1:])
|
||||
}
|
||||
|
||||
// "Hola, así cómo "
|
||||
minmatch := []byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xC3, 0xAD, 0x20, 0x63, 0xC3, 0xB3, 0x6D, 0x6F, 0x20}
|
||||
// "Hola, así cómo "
|
||||
minmatch := []byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xC3, 0xAD, 0x20, 0x63, 0xC3, 0xB3, 0x6D, 0x6F, 0x20}
|
||||
|
||||
res = ToUTF8WithFallback([]byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63, 0xF3, 0x6D, 0x6F, 0x20, 0x07, 0xA4, 0x6F, 0x73}, ConvertOpts{})
|
||||
// Do not fail for differences in invalid cases, as the library might change the conversion criteria for those
|
||||
assert.Equal(t, minmatch, res[0:len(minmatch)])
|
||||
res = converter.convert([]byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63, 0xF3, 0x6D, 0x6F, 0x20, 0x07, 0xA4, 0x6F, 0x73})
|
||||
// Do not fail for differences in invalid cases, as the library might change the conversion criteria for those
|
||||
assert.Equal(t, minmatch, res[0:len(minmatch)])
|
||||
|
||||
res = ToUTF8WithFallback([]byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63, 0xF3, 0x6D, 0x6F, 0x20, 0x81, 0xA4, 0x6F, 0x73}, ConvertOpts{})
|
||||
// Do not fail for differences in invalid cases, as the library might change the conversion criteria for those
|
||||
assert.Equal(t, minmatch, res[0:len(minmatch)])
|
||||
res = converter.convert([]byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63, 0xF3, 0x6D, 0x6F, 0x20, 0x81, 0xA4, 0x6F, 0x73})
|
||||
// Do not fail for differences in invalid cases, as the library might change the conversion criteria for those
|
||||
assert.Equal(t, minmatch, res[0:len(minmatch)])
|
||||
|
||||
// Japanese (Shift-JIS)
|
||||
// "日属秘ぞしちゅ。"
|
||||
res = ToUTF8WithFallback([]byte{0x93, 0xFA, 0x91, 0xAE, 0x94, 0xE9, 0x82, 0xBC, 0x82, 0xB5, 0x82, 0xBF, 0x82, 0xE3, 0x81, 0x42}, ConvertOpts{})
|
||||
assert.Equal(t, []byte{
|
||||
0xE6, 0x97, 0xA5, 0xE5, 0xB1, 0x9E, 0xE7, 0xA7, 0x98, 0xE3,
|
||||
0x81, 0x9E, 0xE3, 0x81, 0x97, 0xE3, 0x81, 0xA1, 0xE3, 0x82, 0x85, 0xE3, 0x80, 0x82,
|
||||
}, res)
|
||||
// Japanese (Shift-JIS)
|
||||
// "日属秘ぞしちゅ。"
|
||||
res = converter.convert([]byte{0x93, 0xFA, 0x91, 0xAE, 0x94, 0xE9, 0x82, 0xBC, 0x82, 0xB5, 0x82, 0xBF, 0x82, 0xE3, 0x81, 0x42})
|
||||
assert.Equal(t, []byte{
|
||||
0xE6, 0x97, 0xA5, 0xE5, 0xB1, 0x9E, 0xE7, 0xA7, 0x98, 0xE3,
|
||||
0x81, 0x9E, 0xE3, 0x81, 0x97, 0xE3, 0x81, 0xA1, 0xE3, 0x82, 0x85, 0xE3, 0x80, 0x82,
|
||||
}, res)
|
||||
|
||||
res = ToUTF8WithFallback([]byte{0x00, 0x00, 0x00, 0x00}, ConvertOpts{})
|
||||
assert.Equal(t, []byte{0x00, 0x00, 0x00, 0x00}, res)
|
||||
}
|
||||
|
||||
func TestToUTF8DropErrors(t *testing.T) {
|
||||
// "ABC"
|
||||
res := ToUTF8DropErrors([]byte{0x41, 0x42, 0x43})
|
||||
assert.Equal(t, []byte{0x41, 0x42, 0x43}, res)
|
||||
|
||||
// "áéíóú"
|
||||
res = ToUTF8DropErrors([]byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba})
|
||||
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, res)
|
||||
|
||||
// UTF8 BOM + "áéíóú"
|
||||
res = ToUTF8DropErrors([]byte{0xef, 0xbb, 0xbf, 0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba})
|
||||
assert.Equal(t, []byte{0xc3, 0xa1, 0xc3, 0xa9, 0xc3, 0xad, 0xc3, 0xb3, 0xc3, 0xba}, res)
|
||||
|
||||
// "Hola, así cómo ños"
|
||||
res = ToUTF8DropErrors([]byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63, 0xF3, 0x6D, 0x6F, 0x20, 0xF1, 0x6F, 0x73})
|
||||
assert.Equal(t, []byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73}, res[:8])
|
||||
assert.Equal(t, []byte{0x73}, res[len(res)-1:])
|
||||
|
||||
// "Hola, así cómo "
|
||||
minmatch := []byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xC3, 0xAD, 0x20, 0x63, 0xC3, 0xB3, 0x6D, 0x6F, 0x20}
|
||||
|
||||
res = ToUTF8DropErrors([]byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63, 0xF3, 0x6D, 0x6F, 0x20, 0x07, 0xA4, 0x6F, 0x73})
|
||||
// Do not fail for differences in invalid cases, as the library might change the conversion criteria for those
|
||||
assert.Equal(t, minmatch, res[0:len(minmatch)])
|
||||
|
||||
res = ToUTF8DropErrors([]byte{0x48, 0x6F, 0x6C, 0x61, 0x2C, 0x20, 0x61, 0x73, 0xED, 0x20, 0x63, 0xF3, 0x6D, 0x6F, 0x20, 0x81, 0xA4, 0x6F, 0x73})
|
||||
// Do not fail for differences in invalid cases, as the library might change the conversion criteria for those
|
||||
assert.Equal(t, minmatch, res[0:len(minmatch)])
|
||||
|
||||
// Japanese (Shift-JIS)
|
||||
// "日属秘ぞしちゅ。"
|
||||
res = ToUTF8DropErrors([]byte{0x93, 0xFA, 0x91, 0xAE, 0x94, 0xE9, 0x82, 0xBC, 0x82, 0xB5, 0x82, 0xBF, 0x82, 0xE3, 0x81, 0x42})
|
||||
assert.Equal(t, []byte{
|
||||
0xE6, 0x97, 0xA5, 0xE5, 0xB1, 0x9E, 0xE7, 0xA7, 0x98, 0xE3,
|
||||
0x81, 0x9E, 0xE3, 0x81, 0x97, 0xE3, 0x81, 0xA1, 0xE3, 0x82, 0x85, 0xE3, 0x80, 0x82,
|
||||
}, res)
|
||||
|
||||
res = ToUTF8DropErrors([]byte{0x00, 0x00, 0x00, 0x00})
|
||||
assert.Equal(t, []byte{0x00, 0x00, 0x00, 0x00}, res)
|
||||
res = converter.convert([]byte{0x00, 0x00, 0x00, 0x00})
|
||||
assert.Equal(t, []byte{0x00, 0x00, 0x00, 0x00}, res)
|
||||
})
|
||||
}
|
||||
|
||||
assert.Equal(t, "caf ", string(ToUTF8DropErrors([]byte("caf\xe9"))))
|
||||
}
|
||||
|
||||
@@ -173,11 +173,6 @@ func TestCombine(t *testing.T) {
|
||||
states: CommitStatusStates{CommitStatusSuccess, CommitStatusError, CommitStatusFailure, CommitStatusWarning},
|
||||
expected: CommitStatusFailure,
|
||||
},
|
||||
{
|
||||
name: "mixed states",
|
||||
states: CommitStatusStates{CommitStatusPending, CommitStatusSuccess, CommitStatusError, CommitStatusWarning},
|
||||
expected: CommitStatusFailure,
|
||||
},
|
||||
{
|
||||
name: "mixed states with all success",
|
||||
states: CommitStatusStates{CommitStatusSuccess, CommitStatusSuccess, CommitStatusPending, CommitStatusWarning},
|
||||
|
||||
+8
-33
@@ -307,6 +307,7 @@ func TestGuessDelimiter(t *testing.T) {
|
||||
cases := []struct {
|
||||
csv string
|
||||
expectedDelimiter rune
|
||||
checkQuotes bool
|
||||
}{
|
||||
// case 0 - single cell, comma delmited
|
||||
{
|
||||
@@ -373,12 +374,14 @@ quoted,
|
||||
quoted,
|
||||
text," d`,
|
||||
expectedDelimiter: '\t',
|
||||
checkQuotes: true,
|
||||
},
|
||||
// case 10 - semicolon delmited with quotes and semicolon in value
|
||||
{
|
||||
csv: `col1;col2
|
||||
"this has a literal "" in the text";"and an ; in the text"`,
|
||||
expectedDelimiter: ';',
|
||||
checkQuotes: true,
|
||||
},
|
||||
// case 11 - pipe delimited with quotes
|
||||
{
|
||||
@@ -389,6 +392,7 @@ World"|123
|
||||
|
|
||||
f" | 4.56 | 789`,
|
||||
expectedDelimiter: '|',
|
||||
checkQuotes: true,
|
||||
},
|
||||
// case 12 - a tab delimited 6 column CSV, but the values are not quoted and have lots of commas.
|
||||
// In the previous bestScore algorithm, this would have picked comma as the delimiter, but now it should guess tab
|
||||
@@ -455,6 +459,10 @@ jkl`,
|
||||
for n, c := range cases {
|
||||
delimiter := guessDelimiter([]byte(decodeSlashes(t, c.csv)))
|
||||
assert.Equal(t, c.expectedDelimiter, delimiter, "case %d: delimiter should be equal, expected '%c' got '%c'", n, c.expectedDelimiter, delimiter)
|
||||
if c.checkQuotes {
|
||||
delimiter = guessFromBeforeAfterQuotes([]byte(decodeSlashes(t, c.csv)))
|
||||
assert.Equal(t, c.expectedDelimiter, delimiter, "case %d: delimiter should be equal, expected '%c' got '%c'", n, c.expectedDelimiter, delimiter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,39 +471,6 @@ func TestGuessFromBeforeAfterQuotes(t *testing.T) {
|
||||
csv string
|
||||
expectedDelimiter rune
|
||||
}{
|
||||
// case 0 - tab delimited with new lines in values, commas in values
|
||||
{
|
||||
csv: `1 "some,""more
|
||||
""
|
||||
quoted,
|
||||
text," a
|
||||
2 "some,
|
||||
quoted,\t
|
||||
text," b
|
||||
3 "some,
|
||||
quoted,
|
||||
text" c
|
||||
4 "some,
|
||||
quoted,
|
||||
text," d`,
|
||||
expectedDelimiter: '\t',
|
||||
},
|
||||
// case 1 - semicolon delmited with quotes and semicolon in value
|
||||
{
|
||||
csv: `col1;col2
|
||||
"this has a literal "" in the text";"and an ; in the text"`,
|
||||
expectedDelimiter: ';',
|
||||
},
|
||||
// case 2 - pipe delimited with quotes
|
||||
{
|
||||
csv: `Col1 | Col2 | Col3
|
||||
abc | "Hello
|
||||
World"|123
|
||||
"de
|
||||
|
|
||||
f" | 4.56 | 789`,
|
||||
expectedDelimiter: '|',
|
||||
},
|
||||
// case 3 - a complicated quoted CSV that is semicolon delmiited
|
||||
{
|
||||
csv: `he; she
|
||||
|
||||
@@ -16,60 +16,36 @@ import (
|
||||
|
||||
func TestRenderEntryIconHTML_WithDifferentThemes(t *testing.T) {
|
||||
// Test that folder icons use the folder theme
|
||||
t.Run("FolderUsesBasicTheme", func(t *testing.T) {
|
||||
defer test.MockVariableValue(&setting.UI.FileIconTheme, "material")()
|
||||
defer test.MockVariableValue(&setting.UI.FolderIconTheme, "basic")()
|
||||
|
||||
folderEntry := &fileicon.EntryInfo{
|
||||
BaseName: "testfolder",
|
||||
EntryMode: git.EntryModeTree,
|
||||
}
|
||||
|
||||
html := fileicon.RenderEntryIconHTML(nil, folderEntry)
|
||||
for _, testCase := range []struct {
|
||||
name, folderTheme, expected string
|
||||
entry fileicon.EntryInfo
|
||||
}{
|
||||
// Basic theme renders octicon classes
|
||||
assert.Contains(t, string(html), "octicon-file-directory-fill")
|
||||
})
|
||||
|
||||
t.Run("FileUsesMaterialTheme", func(t *testing.T) {
|
||||
defer test.MockVariableValue(&setting.UI.FileIconTheme, "material")()
|
||||
defer test.MockVariableValue(&setting.UI.FolderIconTheme, "basic")()
|
||||
|
||||
fileEntry := &fileicon.EntryInfo{
|
||||
BaseName: "test.js",
|
||||
EntryMode: git.EntryModeBlob,
|
||||
}
|
||||
|
||||
html := fileicon.RenderEntryIconHTML(nil, fileEntry)
|
||||
{
|
||||
"FolderUsesBasicTheme", "basic", "octicon-file-directory-fill",
|
||||
fileicon.EntryInfo{BaseName: "testfolder", EntryMode: git.EntryModeTree},
|
||||
},
|
||||
// Material theme for files renders material icons
|
||||
assert.Contains(t, string(html), "svg-mfi-")
|
||||
})
|
||||
|
||||
t.Run("SymlinkToFolderUsesBasicTheme", func(t *testing.T) {
|
||||
defer test.MockVariableValue(&setting.UI.FileIconTheme, "material")()
|
||||
defer test.MockVariableValue(&setting.UI.FolderIconTheme, "basic")()
|
||||
|
||||
symlinkEntry := &fileicon.EntryInfo{
|
||||
BaseName: "link",
|
||||
EntryMode: git.EntryModeSymlink,
|
||||
SymlinkToMode: git.EntryModeTree,
|
||||
}
|
||||
|
||||
html := fileicon.RenderEntryIconHTML(nil, symlinkEntry)
|
||||
{
|
||||
"FileUsesMaterialTheme", "basic", "svg-mfi-",
|
||||
fileicon.EntryInfo{BaseName: "test.js", EntryMode: git.EntryModeBlob},
|
||||
},
|
||||
// Symlinks to folders should use folder theme
|
||||
assert.Contains(t, string(html), "octicon-file-directory-symlink")
|
||||
})
|
||||
|
||||
t.Run("BothMaterialTheme", func(t *testing.T) {
|
||||
defer test.MockVariableValue(&setting.UI.FileIconTheme, "material")()
|
||||
defer test.MockVariableValue(&setting.UI.FolderIconTheme, "material")()
|
||||
|
||||
folderEntry := &fileicon.EntryInfo{
|
||||
BaseName: "testfolder",
|
||||
EntryMode: git.EntryModeTree,
|
||||
}
|
||||
|
||||
html := fileicon.RenderEntryIconHTML(nil, folderEntry)
|
||||
{
|
||||
"SymlinkToFolderUsesBasicTheme", "basic", "octicon-file-directory-symlink",
|
||||
fileicon.EntryInfo{BaseName: "link", EntryMode: git.EntryModeSymlink, SymlinkToMode: git.EntryModeTree},
|
||||
},
|
||||
// Material theme for folders renders material folder icons
|
||||
assert.Contains(t, string(html), "svg-mfi-")
|
||||
})
|
||||
{
|
||||
"BothMaterialTheme", "material", "svg-mfi-",
|
||||
fileicon.EntryInfo{BaseName: "testfolder", EntryMode: git.EntryModeTree},
|
||||
},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
defer test.MockVariableValue(&setting.UI.FileIconTheme, "material")()
|
||||
defer test.MockVariableValue(&setting.UI.FolderIconTheme, testCase.folderTheme)()
|
||||
|
||||
assert.Contains(t, string(fileicon.RenderEntryIconHTML(nil, &testCase.entry)), testCase.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -23,50 +23,31 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
|
||||
|
||||
testStr := ".gitignore\"\n\x00linguist-vendored\x00unspecified\x00"
|
||||
|
||||
n, err := wr.Write([]byte(testStr))
|
||||
|
||||
assert.Len(t, testStr, n)
|
||||
assert.NoError(t, err)
|
||||
select {
|
||||
case attr := <-wr.ReadAttribute():
|
||||
assert.Equal(t, ".gitignore\"\n", attr.Filename)
|
||||
assert.Equal(t, LinguistVendored, attr.Attribute)
|
||||
assert.Equal(t, "unspecified", attr.Value)
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
assert.FailNow(t, "took too long to read an attribute from the list")
|
||||
}
|
||||
// Write a second attribute again
|
||||
n, err = wr.Write([]byte(testStr))
|
||||
|
||||
assert.Len(t, testStr, n)
|
||||
assert.NoError(t, err)
|
||||
|
||||
select {
|
||||
case attr := <-wr.ReadAttribute():
|
||||
assert.Equal(t, ".gitignore\"\n", attr.Filename)
|
||||
assert.Equal(t, LinguistVendored, attr.Attribute)
|
||||
assert.Equal(t, "unspecified", attr.Value)
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
assert.FailNow(t, "took too long to read an attribute from the list")
|
||||
for range 2 {
|
||||
n, err := wr.Write([]byte(testStr))
|
||||
assert.Len(t, testStr, n)
|
||||
assert.NoError(t, err)
|
||||
select {
|
||||
case attr := <-wr.ReadAttribute():
|
||||
assert.Equal(t, ".gitignore\"\n", attr.Filename)
|
||||
assert.Equal(t, LinguistVendored, attr.Attribute)
|
||||
assert.Equal(t, "unspecified", attr.Value)
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
assert.FailNow(t, "took too long to read an attribute from the list")
|
||||
}
|
||||
}
|
||||
|
||||
// Write a partial attribute
|
||||
_, err = wr.Write([]byte("incomplete-file"))
|
||||
_, err := wr.Write([]byte("incomplete-file"))
|
||||
assert.NoError(t, err)
|
||||
_, err = wr.Write([]byte("name\x00"))
|
||||
assert.NoError(t, err)
|
||||
|
||||
select {
|
||||
case <-wr.ReadAttribute():
|
||||
assert.FailNow(t, "There should not be an attribute ready to read")
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
}
|
||||
_, err = wr.Write([]byte("attribute\x00"))
|
||||
assert.NoError(t, err)
|
||||
select {
|
||||
case <-wr.ReadAttribute():
|
||||
assert.FailNow(t, "There should not be an attribute ready to read")
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
for _, part := range []string{"name\x00", "attribute\x00"} {
|
||||
_, err = wr.Write([]byte(part))
|
||||
assert.NoError(t, err)
|
||||
select {
|
||||
case <-wr.ReadAttribute():
|
||||
assert.FailNow(t, "There should not be an attribute ready to read")
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
|
||||
_, err = wr.Write([]byte("value\x00"))
|
||||
@@ -79,27 +60,15 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
|
||||
|
||||
_, err = wr.Write([]byte("shouldbe.vendor\x00linguist-vendored\x00set\x00shouldbe.vendor\x00linguist-generated\x00unspecified\x00shouldbe.vendor\x00linguist-language\x00unspecified\x00"))
|
||||
assert.NoError(t, err)
|
||||
attr = <-wr.ReadAttribute()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, attributeTriple{
|
||||
Filename: "shouldbe.vendor",
|
||||
Attribute: LinguistVendored,
|
||||
Value: "set",
|
||||
}, attr)
|
||||
attr = <-wr.ReadAttribute()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, attributeTriple{
|
||||
Filename: "shouldbe.vendor",
|
||||
Attribute: LinguistGenerated,
|
||||
Value: "unspecified",
|
||||
}, attr)
|
||||
attr = <-wr.ReadAttribute()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, attributeTriple{
|
||||
Filename: "shouldbe.vendor",
|
||||
Attribute: LinguistLanguage,
|
||||
Value: "unspecified",
|
||||
}, attr)
|
||||
for _, expected := range []attributeTriple{
|
||||
{"shouldbe.vendor", LinguistVendored, "set"},
|
||||
{"shouldbe.vendor", LinguistGenerated, "unspecified"},
|
||||
{"shouldbe.vendor", LinguistLanguage, "unspecified"},
|
||||
} {
|
||||
attr = <-wr.ReadAttribute()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, attr)
|
||||
}
|
||||
}
|
||||
|
||||
func expectedAttrs() *Attributes {
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gitea.dev/modules/setting"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestReadingBlameOutputSha256(t *testing.T) {
|
||||
setting.AppDataPath = t.TempDir()
|
||||
ctx := t.Context()
|
||||
|
||||
t.Run("Without .git-blame-ignore-revs", func(t *testing.T) {
|
||||
storage := mockRepository("repo5_pulls_sha256")
|
||||
repo, err := OpenRepository(ctx, storage)
|
||||
assert.NoError(t, err)
|
||||
defer repo.Close()
|
||||
|
||||
commit, err := repo.GetCommit(t.Context(), "0b69b7bb649b5d46e14cabb6468685e5dd721290acc7ffe604d37cde57927345")
|
||||
assert.NoError(t, err)
|
||||
|
||||
parts := []*BlamePart{
|
||||
{
|
||||
Sha: "1e35a51dc00fd7de730344c07061acfe80e8117e075ac979b6a29a3a045190ca",
|
||||
Lines: []string{
|
||||
"# test_repo",
|
||||
"Test repository for testing migration from github to gitea",
|
||||
},
|
||||
},
|
||||
{
|
||||
Sha: "0b69b7bb649b5d46e14cabb6468685e5dd721290acc7ffe604d37cde57927345",
|
||||
Lines: []string{"", "Do not make any changes to this repo it is used for unit testing"},
|
||||
PreviousSha: "1e35a51dc00fd7de730344c07061acfe80e8117e075ac979b6a29a3a045190ca",
|
||||
PreviousPath: "README.md",
|
||||
},
|
||||
}
|
||||
|
||||
for _, bypass := range []bool{false, true} {
|
||||
blameReader, err := CreateBlameReader(ctx, Sha256ObjectFormat, storage, repo, commit, "README.md", bypass)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blameReader)
|
||||
defer blameReader.Close()
|
||||
|
||||
assert.False(t, blameReader.UsesIgnoreRevs())
|
||||
|
||||
for _, part := range parts {
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, part, actualPart)
|
||||
}
|
||||
|
||||
// make sure all parts have been read
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.Nil(t, actualPart)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("With .git-blame-ignore-revs", func(t *testing.T) {
|
||||
storage := mockRepository("repo6_blame_sha256")
|
||||
repo, err := OpenRepository(ctx, storage)
|
||||
assert.NoError(t, err)
|
||||
defer repo.Close()
|
||||
|
||||
full := []*BlamePart{
|
||||
{
|
||||
Sha: "ab2b57a4fa476fb2edb74dafa577caf918561abbaa8fba0c8dc63c412e17a7cc",
|
||||
Lines: []string{"line", "line"},
|
||||
},
|
||||
{
|
||||
Sha: "9347b0198cd1f25017579b79d0938fa89dba34ad2514f0dd92f6bc975ed1a2fe",
|
||||
Lines: []string{"changed line"},
|
||||
PreviousSha: "ab2b57a4fa476fb2edb74dafa577caf918561abbaa8fba0c8dc63c412e17a7cc",
|
||||
PreviousPath: "blame.txt",
|
||||
},
|
||||
{
|
||||
Sha: "ab2b57a4fa476fb2edb74dafa577caf918561abbaa8fba0c8dc63c412e17a7cc",
|
||||
Lines: []string{"line", "line", ""},
|
||||
},
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
CommitID string
|
||||
UsesIgnoreRevs bool
|
||||
Bypass bool
|
||||
Parts []*BlamePart
|
||||
}{
|
||||
{
|
||||
CommitID: "e2f5660e15159082902960af0ed74fc144921d2b0c80e069361853b3ece29ba3",
|
||||
UsesIgnoreRevs: true,
|
||||
Bypass: false,
|
||||
Parts: []*BlamePart{
|
||||
{
|
||||
Sha: "ab2b57a4fa476fb2edb74dafa577caf918561abbaa8fba0c8dc63c412e17a7cc",
|
||||
Lines: []string{"line", "line", "changed line", "line", "line", ""},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CommitID: "e2f5660e15159082902960af0ed74fc144921d2b0c80e069361853b3ece29ba3",
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: true,
|
||||
Parts: full,
|
||||
},
|
||||
{
|
||||
CommitID: "9347b0198cd1f25017579b79d0938fa89dba34ad2514f0dd92f6bc975ed1a2fe",
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: false,
|
||||
Parts: full,
|
||||
},
|
||||
{
|
||||
CommitID: "9347b0198cd1f25017579b79d0938fa89dba34ad2514f0dd92f6bc975ed1a2fe",
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: false,
|
||||
Parts: full,
|
||||
},
|
||||
}
|
||||
|
||||
objectFormat, err := repo.GetObjectFormat(t.Context())
|
||||
assert.NoError(t, err)
|
||||
for _, c := range cases {
|
||||
commit, err := repo.GetCommit(t.Context(), c.CommitID)
|
||||
assert.NoError(t, err)
|
||||
blameReader, err := CreateBlameReader(ctx, objectFormat, storage, repo, commit, "blame.txt", c.Bypass)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blameReader)
|
||||
defer blameReader.Close()
|
||||
|
||||
assert.Equal(t, c.UsesIgnoreRevs, blameReader.UsesIgnoreRevs())
|
||||
|
||||
for _, part := range c.Parts {
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, part, actualPart)
|
||||
}
|
||||
|
||||
// make sure all parts have been read
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.Nil(t, actualPart)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
+155
-122
@@ -24,137 +24,170 @@ func TestLineBlameCommitID(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReadingBlameOutput(t *testing.T) {
|
||||
setting.AppDataPath = t.TempDir()
|
||||
ctx := t.Context()
|
||||
for _, scenario := range []struct {
|
||||
name string
|
||||
repositorySuffix string
|
||||
objectFormat ObjectFormat
|
||||
readmeCommit string
|
||||
readmePrevious string
|
||||
blameCommit string
|
||||
blameChanged string
|
||||
blameOriginal string
|
||||
}{
|
||||
{
|
||||
name: "sha1",
|
||||
objectFormat: Sha1ObjectFormat,
|
||||
readmeCommit: "f32b0a9dfd09a60f616f29158f772cedd89942d2",
|
||||
readmePrevious: "72866af952e98d02a73003501836074b286a78f6",
|
||||
blameCommit: "544d8f7a3b15927cddf2299b4b562d6ebd71b6a7",
|
||||
blameChanged: "45fb6cbc12f970b04eacd5cd4165edd11c8d7376",
|
||||
blameOriginal: "af7486bd54cfc39eea97207ca666aa69c9d6df93",
|
||||
},
|
||||
{
|
||||
name: "sha256",
|
||||
repositorySuffix: "_sha256",
|
||||
objectFormat: Sha256ObjectFormat,
|
||||
readmeCommit: "0b69b7bb649b5d46e14cabb6468685e5dd721290acc7ffe604d37cde57927345",
|
||||
readmePrevious: "1e35a51dc00fd7de730344c07061acfe80e8117e075ac979b6a29a3a045190ca",
|
||||
blameCommit: "e2f5660e15159082902960af0ed74fc144921d2b0c80e069361853b3ece29ba3",
|
||||
blameChanged: "9347b0198cd1f25017579b79d0938fa89dba34ad2514f0dd92f6bc975ed1a2fe",
|
||||
blameOriginal: "ab2b57a4fa476fb2edb74dafa577caf918561abbaa8fba0c8dc63c412e17a7cc",
|
||||
},
|
||||
} {
|
||||
t.Run(scenario.name, func(t *testing.T) {
|
||||
setting.AppDataPath = t.TempDir()
|
||||
ctx := t.Context()
|
||||
|
||||
t.Run("Without .git-blame-ignore-revs", func(t *testing.T) {
|
||||
storage := mockRepository("repo5_pulls")
|
||||
repo, err := OpenRepository(ctx, storage)
|
||||
assert.NoError(t, err)
|
||||
defer repo.Close()
|
||||
commit, err := repo.GetCommit(t.Context(), "f32b0a9dfd09a60f616f29158f772cedd89942d2")
|
||||
assert.NoError(t, err)
|
||||
|
||||
parts := []*BlamePart{
|
||||
{
|
||||
Sha: "72866af952e98d02a73003501836074b286a78f6",
|
||||
Lines: []string{
|
||||
"# test_repo",
|
||||
"Test repository for testing migration from github to gitea",
|
||||
},
|
||||
},
|
||||
{
|
||||
Sha: "f32b0a9dfd09a60f616f29158f772cedd89942d2",
|
||||
Lines: []string{"", "Do not make any changes to this repo it is used for unit testing"},
|
||||
PreviousSha: "72866af952e98d02a73003501836074b286a78f6",
|
||||
PreviousPath: "README.md",
|
||||
},
|
||||
}
|
||||
|
||||
for _, bypass := range []bool{false, true} {
|
||||
blameReader, err := CreateBlameReader(ctx, Sha1ObjectFormat, storage, repo, commit, "README.md", bypass)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blameReader)
|
||||
defer blameReader.Close()
|
||||
|
||||
assert.False(t, blameReader.UsesIgnoreRevs())
|
||||
|
||||
for _, part := range parts {
|
||||
actualPart, err := blameReader.NextPart()
|
||||
t.Run("Without .git-blame-ignore-revs", func(t *testing.T) {
|
||||
storage := mockRepository("repo5_pulls" + scenario.repositorySuffix)
|
||||
repo, err := OpenRepository(ctx, storage)
|
||||
assert.NoError(t, err)
|
||||
defer repo.Close()
|
||||
commit, err := repo.GetCommit(t.Context(), scenario.readmeCommit)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, part, actualPart)
|
||||
}
|
||||
|
||||
// make sure all parts have been read
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.Nil(t, actualPart)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("With .git-blame-ignore-revs", func(t *testing.T) {
|
||||
storage := mockRepository("repo6_blame")
|
||||
repo, err := OpenRepository(ctx, storage)
|
||||
assert.NoError(t, err)
|
||||
defer repo.Close()
|
||||
|
||||
full := []*BlamePart{
|
||||
{
|
||||
Sha: "af7486bd54cfc39eea97207ca666aa69c9d6df93",
|
||||
Lines: []string{"line", "line"},
|
||||
},
|
||||
{
|
||||
Sha: "45fb6cbc12f970b04eacd5cd4165edd11c8d7376",
|
||||
Lines: []string{"changed line"},
|
||||
PreviousSha: "af7486bd54cfc39eea97207ca666aa69c9d6df93",
|
||||
PreviousPath: "blame.txt",
|
||||
},
|
||||
{
|
||||
Sha: "af7486bd54cfc39eea97207ca666aa69c9d6df93",
|
||||
Lines: []string{"line", "line", ""},
|
||||
},
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
CommitID string
|
||||
UsesIgnoreRevs bool
|
||||
Bypass bool
|
||||
Parts []*BlamePart
|
||||
}{
|
||||
{
|
||||
CommitID: "544d8f7a3b15927cddf2299b4b562d6ebd71b6a7",
|
||||
UsesIgnoreRevs: true,
|
||||
Bypass: false,
|
||||
Parts: []*BlamePart{
|
||||
parts := []*BlamePart{
|
||||
{
|
||||
Sha: "af7486bd54cfc39eea97207ca666aa69c9d6df93",
|
||||
Lines: []string{"line", "line", "changed line", "line", "line", ""},
|
||||
Sha: scenario.readmePrevious,
|
||||
Lines: []string{
|
||||
"# test_repo",
|
||||
"Test repository for testing migration from github to gitea",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CommitID: "544d8f7a3b15927cddf2299b4b562d6ebd71b6a7",
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: true,
|
||||
Parts: full,
|
||||
},
|
||||
{
|
||||
CommitID: "45fb6cbc12f970b04eacd5cd4165edd11c8d7376",
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: false,
|
||||
Parts: full,
|
||||
},
|
||||
{
|
||||
CommitID: "45fb6cbc12f970b04eacd5cd4165edd11c8d7376",
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: false,
|
||||
Parts: full,
|
||||
},
|
||||
}
|
||||
{
|
||||
Sha: scenario.readmeCommit,
|
||||
Lines: []string{"", "Do not make any changes to this repo it is used for unit testing"},
|
||||
PreviousSha: scenario.readmePrevious,
|
||||
PreviousPath: "README.md",
|
||||
},
|
||||
}
|
||||
|
||||
objectFormat, err := repo.GetObjectFormat(t.Context())
|
||||
assert.NoError(t, err)
|
||||
for _, c := range cases {
|
||||
commit, err := repo.GetCommit(t.Context(), c.CommitID)
|
||||
assert.NoError(t, err)
|
||||
for _, bypass := range []bool{false, true} {
|
||||
blameReader, err := CreateBlameReader(ctx, scenario.objectFormat, storage, repo, commit, "README.md", bypass)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blameReader)
|
||||
defer blameReader.Close()
|
||||
|
||||
blameReader, err := CreateBlameReader(ctx, objectFormat, storage, repo, commit, "blame.txt", c.Bypass)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blameReader)
|
||||
defer blameReader.Close()
|
||||
assert.False(t, blameReader.UsesIgnoreRevs())
|
||||
|
||||
assert.Equal(t, c.UsesIgnoreRevs, blameReader.UsesIgnoreRevs())
|
||||
for _, part := range parts {
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, part, actualPart)
|
||||
}
|
||||
|
||||
for _, part := range c.Parts {
|
||||
actualPart, err := blameReader.NextPart()
|
||||
// make sure all parts have been read
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.Nil(t, actualPart)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("With .git-blame-ignore-revs", func(t *testing.T) {
|
||||
storage := mockRepository("repo6_blame" + scenario.repositorySuffix)
|
||||
repo, err := OpenRepository(ctx, storage)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, part, actualPart)
|
||||
}
|
||||
defer repo.Close()
|
||||
|
||||
// make sure all parts have been read
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.Nil(t, actualPart)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
full := []*BlamePart{
|
||||
{
|
||||
Sha: scenario.blameOriginal,
|
||||
Lines: []string{"line", "line"},
|
||||
},
|
||||
{
|
||||
Sha: scenario.blameChanged,
|
||||
Lines: []string{"changed line"},
|
||||
PreviousSha: scenario.blameOriginal,
|
||||
PreviousPath: "blame.txt",
|
||||
},
|
||||
{
|
||||
Sha: scenario.blameOriginal,
|
||||
Lines: []string{"line", "line", ""},
|
||||
},
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
CommitID string
|
||||
UsesIgnoreRevs bool
|
||||
Bypass bool
|
||||
Parts []*BlamePart
|
||||
}{
|
||||
{
|
||||
CommitID: scenario.blameCommit,
|
||||
UsesIgnoreRevs: true,
|
||||
Bypass: false,
|
||||
Parts: []*BlamePart{
|
||||
{
|
||||
Sha: scenario.blameOriginal,
|
||||
Lines: []string{"line", "line", "changed line", "line", "line", ""},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CommitID: scenario.blameCommit,
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: true,
|
||||
Parts: full,
|
||||
},
|
||||
{
|
||||
CommitID: scenario.blameChanged,
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: false,
|
||||
Parts: full,
|
||||
},
|
||||
{
|
||||
CommitID: scenario.blameChanged,
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: false,
|
||||
Parts: full,
|
||||
},
|
||||
}
|
||||
|
||||
objectFormat, err := repo.GetObjectFormat(t.Context())
|
||||
assert.NoError(t, err)
|
||||
for _, c := range cases {
|
||||
commit, err := repo.GetCommit(t.Context(), c.CommitID)
|
||||
assert.NoError(t, err)
|
||||
|
||||
blameReader, err := CreateBlameReader(ctx, objectFormat, storage, repo, commit, "blame.txt", c.Bypass)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blameReader)
|
||||
defer blameReader.Close()
|
||||
|
||||
assert.Equal(t, c.UsesIgnoreRevs, blameReader.UsesIgnoreRevs())
|
||||
|
||||
for _, part := range c.Parts {
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, part, actualPart)
|
||||
}
|
||||
|
||||
// make sure all parts have been read
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.Nil(t, actualPart)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
+10
-41
@@ -11,60 +11,29 @@ import (
|
||||
|
||||
func TestCommitsCount(t *testing.T) {
|
||||
bareRepo1 := mockRepository("repo1_bare")
|
||||
|
||||
commitsCount, err := CommitsCount(t.Context(), bareRepo1,
|
||||
CommitsCountOptions{
|
||||
Revision: []string{"8006ff9adbf0cb94da7dad9e537e53817f9fa5c0"},
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(3), commitsCount)
|
||||
}
|
||||
|
||||
func TestCommitsCountWithSinceUntil(t *testing.T) {
|
||||
bareRepo1 := mockRepository("repo1_bare")
|
||||
revision := []string{"8006ff9adbf0cb94da7dad9e537e53817f9fa5c0"}
|
||||
|
||||
// The three commits on this revision are dated 2018-04-18, 2017-12-19 and 2017-12-19.
|
||||
cases := []struct {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
since string
|
||||
until string
|
||||
options CommitsCountOptions
|
||||
expected int64
|
||||
}{
|
||||
{name: "no filter", expected: 3},
|
||||
{name: "since keeps newer commits", since: "2018-01-01", expected: 1},
|
||||
{name: "until keeps older commits", until: "2018-01-01", expected: 2},
|
||||
{name: "since and until bound the range", since: "2017-12-19T22:16:00-08:00", until: "2018-01-01", expected: 1},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
{"revision", CommitsCountOptions{Revision: revision}, 3},
|
||||
{"no filter", CommitsCountOptions{Revision: revision}, 3},
|
||||
{"since keeps newer commits", CommitsCountOptions{Revision: revision, Since: "2018-01-01"}, 1},
|
||||
{"until keeps older commits", CommitsCountOptions{Revision: revision, Until: "2018-01-01"}, 2},
|
||||
{"since and until bound the range", CommitsCountOptions{Revision: revision, Since: "2017-12-19T22:16:00-08:00", Until: "2018-01-01"}, 1},
|
||||
{"without base", CommitsCountOptions{Not: "master", Revision: []string{"branch1"}}, 2},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
commitsCount, err := CommitsCount(t.Context(), bareRepo1,
|
||||
CommitsCountOptions{
|
||||
Revision: revision,
|
||||
Since: tc.since,
|
||||
Until: tc.until,
|
||||
})
|
||||
|
||||
commitsCount, err := CommitsCount(t.Context(), bareRepo1, tc.options)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.expected, commitsCount)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitsCountWithoutBase(t *testing.T) {
|
||||
bareRepo1 := mockRepository("repo1_bare")
|
||||
|
||||
commitsCount, err := CommitsCount(t.Context(), bareRepo1,
|
||||
CommitsCountOptions{
|
||||
Not: "master",
|
||||
Revision: []string{"branch1"},
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(2), commitsCount)
|
||||
}
|
||||
|
||||
func TestGetLatestCommitTime(t *testing.T) {
|
||||
bareRepo1 := mockRepository("repo1_bare")
|
||||
lct, err := GetLatestCommitTime(t.Context(), bareRepo1)
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
func TestParseCommitFileStatus(t *testing.T) {
|
||||
type testcase struct {
|
||||
output string
|
||||
outputs []string
|
||||
added []string
|
||||
removed []string
|
||||
modified []string
|
||||
@@ -21,7 +21,11 @@ func TestParseCommitFileStatus(t *testing.T) {
|
||||
kases := []testcase{
|
||||
{
|
||||
// Merge commit
|
||||
output: "MM\x00options/locale/locale_en-US.ini\x00",
|
||||
outputs: []string{
|
||||
"MM\x00options/locale/locale_en-US.ini\x00",
|
||||
// git 1.7.2 adds an unnecessary \x00 on merge commit
|
||||
"\x00MM\x00options/locale/locale_en-US.ini\x00",
|
||||
},
|
||||
modified: []string{
|
||||
"options/locale/locale_en-US.ini",
|
||||
},
|
||||
@@ -30,7 +34,11 @@ func TestParseCommitFileStatus(t *testing.T) {
|
||||
},
|
||||
{
|
||||
// Spaces commit
|
||||
output: "D\x00b\x00D\x00b b/b\x00A\x00b b/b b/b b/b\x00A\x00b b/b b/b b/b b/b\x00",
|
||||
outputs: []string{
|
||||
"D\x00b\x00D\x00b b/b\x00A\x00b b/b b/b b/b\x00A\x00b b/b b/b b/b b/b\x00",
|
||||
// git 1.7.2 adds an unnecessary \n on normal commit
|
||||
"\nD\x00b\x00D\x00b b/b\x00A\x00b b/b b/b b/b\x00A\x00b b/b b/b b/b b/b\x00",
|
||||
},
|
||||
removed: []string{
|
||||
"b",
|
||||
"b b/b",
|
||||
@@ -43,7 +51,7 @@ func TestParseCommitFileStatus(t *testing.T) {
|
||||
},
|
||||
{
|
||||
// larger commit
|
||||
output: "M\x00go.mod\x00M\x00go.sum\x00M\x00modules/ssh/ssh.go\x00M\x00vendor/github.com/gliderlabs/ssh/circle.yml\x00M\x00vendor/github.com/gliderlabs/ssh/context.go\x00A\x00vendor/github.com/gliderlabs/ssh/go.mod\x00A\x00vendor/github.com/gliderlabs/ssh/go.sum\x00M\x00vendor/github.com/gliderlabs/ssh/server.go\x00M\x00vendor/github.com/gliderlabs/ssh/session.go\x00M\x00vendor/github.com/gliderlabs/ssh/ssh.go\x00M\x00vendor/golang.org/x/sys/unix/mkerrors.sh\x00M\x00vendor/golang.org/x/sys/unix/syscall_darwin.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_linux.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go\x00M\x00vendor/modules.txt\x00",
|
||||
outputs: []string{"M\x00go.mod\x00M\x00go.sum\x00M\x00modules/ssh/ssh.go\x00M\x00vendor/github.com/gliderlabs/ssh/circle.yml\x00M\x00vendor/github.com/gliderlabs/ssh/context.go\x00A\x00vendor/github.com/gliderlabs/ssh/go.mod\x00A\x00vendor/github.com/gliderlabs/ssh/go.sum\x00M\x00vendor/github.com/gliderlabs/ssh/server.go\x00M\x00vendor/github.com/gliderlabs/ssh/session.go\x00M\x00vendor/github.com/gliderlabs/ssh/ssh.go\x00M\x00vendor/golang.org/x/sys/unix/mkerrors.sh\x00M\x00vendor/golang.org/x/sys/unix/syscall_darwin.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go\x00M\x00vendor/golang.org/x/sys/unix/zerrors_linux.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go\x00M\x00vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go\x00M\x00vendor/modules.txt\x00"},
|
||||
modified: []string{
|
||||
"go.mod",
|
||||
"go.sum",
|
||||
@@ -81,37 +89,17 @@ func TestParseCommitFileStatus(t *testing.T) {
|
||||
},
|
||||
removed: []string{},
|
||||
},
|
||||
{
|
||||
// git 1.7.2 adds an unnecessary \x00 on merge commit
|
||||
output: "\x00MM\x00options/locale/locale_en-US.ini\x00",
|
||||
modified: []string{
|
||||
"options/locale/locale_en-US.ini",
|
||||
},
|
||||
added: []string{},
|
||||
removed: []string{},
|
||||
},
|
||||
{
|
||||
// git 1.7.2 adds an unnecessary \n on normal commit
|
||||
output: "\nD\x00b\x00D\x00b b/b\x00A\x00b b/b b/b b/b\x00A\x00b b/b b/b b/b b/b\x00",
|
||||
removed: []string{
|
||||
"b",
|
||||
"b b/b",
|
||||
},
|
||||
modified: []string{},
|
||||
added: []string{
|
||||
"b b/b b/b b/b",
|
||||
"b b/b b/b b/b b/b",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, kase := range kases {
|
||||
fileStatus := NewCommitFileStatus()
|
||||
parseCommitFileStatus(fileStatus, strings.NewReader(kase.output))
|
||||
for _, output := range kase.outputs {
|
||||
fileStatus := NewCommitFileStatus()
|
||||
parseCommitFileStatus(fileStatus, strings.NewReader(output))
|
||||
|
||||
assert.Equal(t, kase.added, fileStatus.Added)
|
||||
assert.Equal(t, kase.removed, fileStatus.Removed)
|
||||
assert.Equal(t, kase.modified, fileStatus.Modified)
|
||||
assert.Equal(t, kase.added, fileStatus.Added)
|
||||
assert.Equal(t, kase.removed, fileStatus.Removed)
|
||||
assert.Equal(t, kase.modified, fileStatus.Modified)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,35 +129,23 @@ func TestGetCommitFileStatusMerges(t *testing.T) {
|
||||
func TestGetCommitFileStatusMergesSha256(t *testing.T) {
|
||||
bareRepo6Sha256 := mockRepository("repo6_merge_sha256")
|
||||
|
||||
commitFileStatus, err := GetCommitFileStatus(t.Context(), bareRepo6Sha256, "d2e5609f630dd8db500f5298d05d16def282412e3e66ed68cc7d0833b29129a1")
|
||||
assert.NoError(t, err)
|
||||
|
||||
expected := CommitFileStatus{
|
||||
[]string{
|
||||
"add_file.txt",
|
||||
for _, tc := range []struct {
|
||||
commitID string
|
||||
expected CommitFileStatus
|
||||
}{
|
||||
{
|
||||
"d2e5609f630dd8db500f5298d05d16def282412e3e66ed68cc7d0833b29129a1",
|
||||
CommitFileStatus{[]string{"add_file.txt"}, []string{}, []string{"to_modify.txt"}},
|
||||
},
|
||||
[]string{},
|
||||
[]string{
|
||||
"to_modify.txt",
|
||||
{
|
||||
"da1ded40dc8e5b7c564171f4bf2fc8370487decfb1cb6a99ef28f3ed73d09172",
|
||||
CommitFileStatus{[]string{}, []string{"to_remove.txt"}, []string{}},
|
||||
},
|
||||
} {
|
||||
commitFileStatus, err := GetCommitFileStatus(t.Context(), bareRepo6Sha256, tc.commitID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.expected.Added, commitFileStatus.Added)
|
||||
assert.Equal(t, tc.expected.Removed, commitFileStatus.Removed)
|
||||
assert.Equal(t, tc.expected.Modified, commitFileStatus.Modified)
|
||||
}
|
||||
|
||||
assert.Equal(t, expected.Added, commitFileStatus.Added)
|
||||
assert.Equal(t, expected.Removed, commitFileStatus.Removed)
|
||||
assert.Equal(t, expected.Modified, commitFileStatus.Modified)
|
||||
|
||||
expected = CommitFileStatus{
|
||||
[]string{},
|
||||
[]string{
|
||||
"to_remove.txt",
|
||||
},
|
||||
[]string{},
|
||||
}
|
||||
|
||||
commitFileStatus, err = GetCommitFileStatus(t.Context(), bareRepo6Sha256, "da1ded40dc8e5b7c564171f4bf2fc8370487decfb1cb6a99ef28f3ed73d09172")
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, expected.Added, commitFileStatus.Added)
|
||||
assert.Equal(t, expected.Removed, commitFileStatus.Removed)
|
||||
assert.Equal(t, expected.Modified, commitFileStatus.Modified)
|
||||
}
|
||||
@@ -5,11 +5,9 @@ package git
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetFullCommitIDSha256(t *testing.T) {
|
||||
@@ -26,74 +24,6 @@ func TestGetFullCommitIDErrorSha256(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitFromReaderSha256(t *testing.T) {
|
||||
commitString := `tree e7f9e96dd79c09b078cac8b303a7d3b9d65ff9b734e86060a4d20409fd379f9e
|
||||
parent 26e9ccc29fad747e9c5d9f4c9ddeb7eff61cc45ef6a8dc258cbeb181afc055e8
|
||||
author Adam Majer <amajer@suse.de> 1698676906 +0100
|
||||
committer Adam Majer <amajer@suse.de> 1698676906 +0100
|
||||
gpgsig-sha256 -----BEGIN PGP SIGNATURE-----
|
||||
` + " " + `
|
||||
iQIrBAABCgAtFiEES+fB08xlgTrzSdQvhkUIsBsmec8FAmU/wKoPHGFtYWplckBz
|
||||
dXNlLmRlAAoJEIZFCLAbJnnP4s4PQIJATa++WPzR6/H4etT7bsOGoMyguEJYyWOd
|
||||
aTybplzT7QAL7h2to0QszGabtzMJPIA39xSFZNYNN30voK5YyyYibXluPKgjemfK
|
||||
WNXwF+gkwgZI38gSvKf+vlqI+EYyIFe19wOhiju0m8SIlB5NEPiWHa17q2mqmqqx
|
||||
1FWa2JdqLPYjAtSLFXeSZegrY5V1FxdemyMUONkg8YO9OSIMZiE0GsnnOXQ3xcT4
|
||||
JTCnmlUxIKw689UiEY80JopUIq+Wl7+qq9507IYYSUCyB6JazL42AKMzVCbD+qBP
|
||||
oOzh/hafYgk9H9qCQXaLbmvs17zXRpicig1bAzqgAy1FDelvpERyRTydEajSLIG6
|
||||
U1cRCkgXCZ0NfsYNPPmBa8b3+rnstypXYTbyMwTln7FfUAaGo6o9JYiPMkzxlmsy
|
||||
zfp/tcaY8+LlBL9aOJjtv+a0p+HrpCGd6CCa4ARfphTLq8QRSSh8uzlB9N+6HnRI
|
||||
VAEUo6ecdDxSpyt2naeg9pKus/BRi7P6g4B1hkk/zZstUX/QP4IQuAJbXjkvsC+X
|
||||
HKRr3NlRM/DygzTyj0gN74uoa0goCIbyAQhiT42nm0cuhM7uN/W0ayrlZjGF1cbR
|
||||
8NCJUL2Nwj0ywKIavC99Ipkb8AsFwpVT6U6effs6
|
||||
=xybZ
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
signed commit`
|
||||
|
||||
sha := &Sha256Hash{
|
||||
0x94, 0x33, 0xb2, 0xa6, 0x2b, 0x96, 0x4c, 0x17, 0xa4, 0x48, 0x5a, 0xe1, 0x80, 0xf4, 0x5f, 0x59,
|
||||
0x5d, 0x3e, 0x69, 0xd3, 0x1b, 0x78, 0x60, 0x87, 0x77, 0x5e, 0x28, 0xc6, 0xb6, 0x39, 0x9d, 0xf0,
|
||||
}
|
||||
gitRepo, err := OpenRepositoryLocal(t.Context(), filepath.Join(testReposDir, "repo1_bare_sha256"))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, gitRepo)
|
||||
defer gitRepo.Close()
|
||||
|
||||
commitFromReader, err := CommitFromReader(sha, strings.NewReader(commitString))
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, commitFromReader)
|
||||
assert.EqualValues(t, sha, commitFromReader.ID)
|
||||
assert.Equal(t, `-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIrBAABCgAtFiEES+fB08xlgTrzSdQvhkUIsBsmec8FAmU/wKoPHGFtYWplckBz
|
||||
dXNlLmRlAAoJEIZFCLAbJnnP4s4PQIJATa++WPzR6/H4etT7bsOGoMyguEJYyWOd
|
||||
aTybplzT7QAL7h2to0QszGabtzMJPIA39xSFZNYNN30voK5YyyYibXluPKgjemfK
|
||||
WNXwF+gkwgZI38gSvKf+vlqI+EYyIFe19wOhiju0m8SIlB5NEPiWHa17q2mqmqqx
|
||||
1FWa2JdqLPYjAtSLFXeSZegrY5V1FxdemyMUONkg8YO9OSIMZiE0GsnnOXQ3xcT4
|
||||
JTCnmlUxIKw689UiEY80JopUIq+Wl7+qq9507IYYSUCyB6JazL42AKMzVCbD+qBP
|
||||
oOzh/hafYgk9H9qCQXaLbmvs17zXRpicig1bAzqgAy1FDelvpERyRTydEajSLIG6
|
||||
U1cRCkgXCZ0NfsYNPPmBa8b3+rnstypXYTbyMwTln7FfUAaGo6o9JYiPMkzxlmsy
|
||||
zfp/tcaY8+LlBL9aOJjtv+a0p+HrpCGd6CCa4ARfphTLq8QRSSh8uzlB9N+6HnRI
|
||||
VAEUo6ecdDxSpyt2naeg9pKus/BRi7P6g4B1hkk/zZstUX/QP4IQuAJbXjkvsC+X
|
||||
HKRr3NlRM/DygzTyj0gN74uoa0goCIbyAQhiT42nm0cuhM7uN/W0ayrlZjGF1cbR
|
||||
8NCJUL2Nwj0ywKIavC99Ipkb8AsFwpVT6U6effs6
|
||||
=xybZ
|
||||
-----END PGP SIGNATURE-----`, commitFromReader.Signature.Signature)
|
||||
assert.Equal(t, `tree e7f9e96dd79c09b078cac8b303a7d3b9d65ff9b734e86060a4d20409fd379f9e
|
||||
parent 26e9ccc29fad747e9c5d9f4c9ddeb7eff61cc45ef6a8dc258cbeb181afc055e8
|
||||
author Adam Majer <amajer@suse.de> 1698676906 +0100
|
||||
committer Adam Majer <amajer@suse.de> 1698676906 +0100
|
||||
|
||||
signed commit`, commitFromReader.Signature.Payload)
|
||||
assert.Equal(t, "Adam Majer <amajer@suse.de>", commitFromReader.Author.String())
|
||||
|
||||
commitFromReader2, err := CommitFromReader(sha, strings.NewReader(commitString+"\n\n"))
|
||||
assert.NoError(t, err)
|
||||
commitFromReader.CommitMessage.MessageRaw += "\n\n"
|
||||
commitFromReader.Signature.Payload += "\n\n"
|
||||
assert.Equal(t, commitFromReader, commitFromReader2)
|
||||
}
|
||||
|
||||
func TestHasPreviousCommitSha256(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256")
|
||||
|
||||
|
||||
+100
-50
@@ -28,7 +28,15 @@ func TestGetFullCommitIDError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCommitFromReader(t *testing.T) {
|
||||
commitString := `tree f1a6cb52b2d16773290cefe49ad0684b50a4f930
|
||||
for _, testCase := range []struct {
|
||||
name, repo string
|
||||
sha ObjectID
|
||||
commitString, signature, payload, author string
|
||||
}{
|
||||
{
|
||||
"TestCommitFromReader", "repo1_bare",
|
||||
&Sha1Hash{0xfe, 0xaf, 0x4b, 0xa6, 0xbc, 0x63, 0x5f, 0xec, 0x44, 0x2f, 0x46, 0xdd, 0xd4, 0x51, 0x24, 0x16, 0xec, 0x43, 0xc2, 0xc2},
|
||||
`tree f1a6cb52b2d16773290cefe49ad0684b50a4f930
|
||||
parent 37991dec2c8e592043f47155ce4808d4580f9123
|
||||
author silverwind <me@silverwind.io> 1563741793 +0200
|
||||
committer silverwind <me@silverwind.io> 1563741793 +0200
|
||||
@@ -49,19 +57,8 @@ gpgsig -----BEGIN PGP SIGNATURE-----
|
||||
=FRsO
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
empty commit`
|
||||
|
||||
sha := &Sha1Hash{0xfe, 0xaf, 0x4b, 0xa6, 0xbc, 0x63, 0x5f, 0xec, 0x44, 0x2f, 0x46, 0xdd, 0xd4, 0x51, 0x24, 0x16, 0xec, 0x43, 0xc2, 0xc2}
|
||||
gitRepo, err := OpenRepositoryLocal(t.Context(), filepath.Join(testReposDir, "repo1_bare"))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, gitRepo)
|
||||
defer gitRepo.Close()
|
||||
|
||||
commitFromReader, err := CommitFromReader(sha, strings.NewReader(commitString))
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, commitFromReader)
|
||||
assert.EqualValues(t, sha, commitFromReader.ID)
|
||||
assert.Equal(t, `-----BEGIN PGP SIGNATURE-----
|
||||
empty commit`,
|
||||
`-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAABCAAdFiEEWPb2jX6FS2mqyJRQLmK0HJOGlEMFAl00zmEACgkQLmK0HJOG
|
||||
lEMDFBAAhQKKqLD1VICygJMEB8t1gBmNLgvziOLfpX4KPWdPtBk3v/QJ7OrfMrVK
|
||||
@@ -76,24 +73,19 @@ sD53z/f0J+We4VZjY+pidvA9BGZPFVdR3wd3xGs8/oH6UWaLJAMGkLG6dDb3qDLm
|
||||
mfeFhT57UbE4qukTDIQ0Y0WM40UYRTakRaDY7ubhXgLgx09Cnp9XTVMsHgT6j9/i
|
||||
1pxsB104XLWjQHTjr1JtiaBQEwFh9r2OKTcpvaLcbNtYpo7CzOs=
|
||||
=FRsO
|
||||
-----END PGP SIGNATURE-----`, commitFromReader.Signature.Signature)
|
||||
assert.Equal(t, `tree f1a6cb52b2d16773290cefe49ad0684b50a4f930
|
||||
-----END PGP SIGNATURE-----`,
|
||||
`tree f1a6cb52b2d16773290cefe49ad0684b50a4f930
|
||||
parent 37991dec2c8e592043f47155ce4808d4580f9123
|
||||
author silverwind <me@silverwind.io> 1563741793 +0200
|
||||
committer silverwind <me@silverwind.io> 1563741793 +0200
|
||||
|
||||
empty commit`, commitFromReader.Signature.Payload)
|
||||
assert.Equal(t, "silverwind <me@silverwind.io>", commitFromReader.Author.String())
|
||||
|
||||
commitFromReader2, err := CommitFromReader(sha, strings.NewReader(commitString+"\n\n"))
|
||||
assert.NoError(t, err)
|
||||
commitFromReader.CommitMessage.MessageRaw += "\n\n"
|
||||
commitFromReader.Signature.Payload += "\n\n"
|
||||
assert.Equal(t, commitFromReader, commitFromReader2)
|
||||
}
|
||||
|
||||
func TestCommitWithEncodingFromReader(t *testing.T) {
|
||||
commitString := `tree ca3fad42080dd1a6d291b75acdfc46e5b9b307e5
|
||||
empty commit`,
|
||||
"silverwind <me@silverwind.io>",
|
||||
},
|
||||
{
|
||||
"TestCommitWithEncodingFromReader", "repo1_bare",
|
||||
&Sha1Hash{0xfe, 0xaf, 0x4b, 0xa6, 0xbc, 0x63, 0x5f, 0xec, 0x44, 0x2f, 0x46, 0xdd, 0xd4, 0x51, 0x24, 0x16, 0xec, 0x43, 0xc2, 0xc2},
|
||||
strings.ReplaceAll(`tree ca3fad42080dd1a6d291b75acdfc46e5b9b307e5
|
||||
parent 47b24e7ab977ed31c5a39989d570847d6d0052af
|
||||
author KN4CK3R <admin@oldschoolhack.me> 1711702962 +0100
|
||||
committer KN4CK3R <admin@oldschoolhack.me> 1711702962 +0100
|
||||
@@ -113,19 +105,8 @@ gpgsig -----BEGIN PGP SIGNATURE-----
|
||||
=r3UU
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
ISO-8859-1`
|
||||
commitString = strings.ReplaceAll(commitString, "<SPACE>", " ")
|
||||
sha := &Sha1Hash{0xfe, 0xaf, 0x4b, 0xa6, 0xbc, 0x63, 0x5f, 0xec, 0x44, 0x2f, 0x46, 0xdd, 0xd4, 0x51, 0x24, 0x16, 0xec, 0x43, 0xc2, 0xc2}
|
||||
gitRepo, err := OpenRepositoryLocal(t.Context(), filepath.Join(testReposDir, "repo1_bare"))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, gitRepo)
|
||||
defer gitRepo.Close()
|
||||
|
||||
commitFromReader, err := CommitFromReader(sha, strings.NewReader(commitString))
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, commitFromReader)
|
||||
assert.EqualValues(t, sha, commitFromReader.ID)
|
||||
assert.Equal(t, `-----BEGIN PGP SIGNATURE-----
|
||||
ISO-8859-1`, "<SPACE>", " "),
|
||||
`-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEE9HRrbqvYxPT8PXbefPSEkrowAa8FAmYGg7IACgkQfPSEkrow
|
||||
Aa9olwv+P0HhtCM6CRvlUmPaqswRsDPNR4i66xyXGiSxdI9V5oJL7HLiQIM7KrFR
|
||||
@@ -138,21 +119,90 @@ SONRzusmu5n3DgV956REL7x62h7JuqmBz/12HZkr0z0zgXkcZ04q08pSJATX5N1F
|
||||
yN+tWxTsWg+zhDk96d5Esdo9JMjcFvPv0eioo30GAERaz1hoD7zCMT4jgUFTQwgz
|
||||
jw4YcO5u
|
||||
=r3UU
|
||||
-----END PGP SIGNATURE-----`, commitFromReader.Signature.Signature)
|
||||
assert.Equal(t, `tree ca3fad42080dd1a6d291b75acdfc46e5b9b307e5
|
||||
-----END PGP SIGNATURE-----`,
|
||||
`tree ca3fad42080dd1a6d291b75acdfc46e5b9b307e5
|
||||
parent 47b24e7ab977ed31c5a39989d570847d6d0052af
|
||||
author KN4CK3R <admin@oldschoolhack.me> 1711702962 +0100
|
||||
committer KN4CK3R <admin@oldschoolhack.me> 1711702962 +0100
|
||||
encoding ISO-8859-1
|
||||
|
||||
ISO-8859-1`, commitFromReader.Signature.Payload)
|
||||
assert.Equal(t, "KN4CK3R <admin@oldschoolhack.me>", commitFromReader.Author.String())
|
||||
ISO-8859-1`,
|
||||
"KN4CK3R <admin@oldschoolhack.me>",
|
||||
},
|
||||
{
|
||||
"TestCommitFromReaderSha256", "repo1_bare_sha256",
|
||||
&Sha256Hash{
|
||||
0x94, 0x33, 0xb2, 0xa6, 0x2b, 0x96, 0x4c, 0x17, 0xa4, 0x48, 0x5a, 0xe1, 0x80, 0xf4, 0x5f, 0x59,
|
||||
0x5d, 0x3e, 0x69, 0xd3, 0x1b, 0x78, 0x60, 0x87, 0x77, 0x5e, 0x28, 0xc6, 0xb6, 0x39, 0x9d, 0xf0,
|
||||
},
|
||||
`tree e7f9e96dd79c09b078cac8b303a7d3b9d65ff9b734e86060a4d20409fd379f9e
|
||||
parent 26e9ccc29fad747e9c5d9f4c9ddeb7eff61cc45ef6a8dc258cbeb181afc055e8
|
||||
author Adam Majer <amajer@suse.de> 1698676906 +0100
|
||||
committer Adam Majer <amajer@suse.de> 1698676906 +0100
|
||||
gpgsig-sha256 -----BEGIN PGP SIGNATURE-----
|
||||
` + " " + `
|
||||
iQIrBAABCgAtFiEES+fB08xlgTrzSdQvhkUIsBsmec8FAmU/wKoPHGFtYWplckBz
|
||||
dXNlLmRlAAoJEIZFCLAbJnnP4s4PQIJATa++WPzR6/H4etT7bsOGoMyguEJYyWOd
|
||||
aTybplzT7QAL7h2to0QszGabtzMJPIA39xSFZNYNN30voK5YyyYibXluPKgjemfK
|
||||
WNXwF+gkwgZI38gSvKf+vlqI+EYyIFe19wOhiju0m8SIlB5NEPiWHa17q2mqmqqx
|
||||
1FWa2JdqLPYjAtSLFXeSZegrY5V1FxdemyMUONkg8YO9OSIMZiE0GsnnOXQ3xcT4
|
||||
JTCnmlUxIKw689UiEY80JopUIq+Wl7+qq9507IYYSUCyB6JazL42AKMzVCbD+qBP
|
||||
oOzh/hafYgk9H9qCQXaLbmvs17zXRpicig1bAzqgAy1FDelvpERyRTydEajSLIG6
|
||||
U1cRCkgXCZ0NfsYNPPmBa8b3+rnstypXYTbyMwTln7FfUAaGo6o9JYiPMkzxlmsy
|
||||
zfp/tcaY8+LlBL9aOJjtv+a0p+HrpCGd6CCa4ARfphTLq8QRSSh8uzlB9N+6HnRI
|
||||
VAEUo6ecdDxSpyt2naeg9pKus/BRi7P6g4B1hkk/zZstUX/QP4IQuAJbXjkvsC+X
|
||||
HKRr3NlRM/DygzTyj0gN74uoa0goCIbyAQhiT42nm0cuhM7uN/W0ayrlZjGF1cbR
|
||||
8NCJUL2Nwj0ywKIavC99Ipkb8AsFwpVT6U6effs6
|
||||
=xybZ
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
commitFromReader2, err := CommitFromReader(sha, strings.NewReader(commitString+"\n\n"))
|
||||
assert.NoError(t, err)
|
||||
commitFromReader.CommitMessage.MessageRaw += "\n\n"
|
||||
commitFromReader.Signature.Payload += "\n\n"
|
||||
assert.Equal(t, commitFromReader, commitFromReader2)
|
||||
signed commit`,
|
||||
`-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIrBAABCgAtFiEES+fB08xlgTrzSdQvhkUIsBsmec8FAmU/wKoPHGFtYWplckBz
|
||||
dXNlLmRlAAoJEIZFCLAbJnnP4s4PQIJATa++WPzR6/H4etT7bsOGoMyguEJYyWOd
|
||||
aTybplzT7QAL7h2to0QszGabtzMJPIA39xSFZNYNN30voK5YyyYibXluPKgjemfK
|
||||
WNXwF+gkwgZI38gSvKf+vlqI+EYyIFe19wOhiju0m8SIlB5NEPiWHa17q2mqmqqx
|
||||
1FWa2JdqLPYjAtSLFXeSZegrY5V1FxdemyMUONkg8YO9OSIMZiE0GsnnOXQ3xcT4
|
||||
JTCnmlUxIKw689UiEY80JopUIq+Wl7+qq9507IYYSUCyB6JazL42AKMzVCbD+qBP
|
||||
oOzh/hafYgk9H9qCQXaLbmvs17zXRpicig1bAzqgAy1FDelvpERyRTydEajSLIG6
|
||||
U1cRCkgXCZ0NfsYNPPmBa8b3+rnstypXYTbyMwTln7FfUAaGo6o9JYiPMkzxlmsy
|
||||
zfp/tcaY8+LlBL9aOJjtv+a0p+HrpCGd6CCa4ARfphTLq8QRSSh8uzlB9N+6HnRI
|
||||
VAEUo6ecdDxSpyt2naeg9pKus/BRi7P6g4B1hkk/zZstUX/QP4IQuAJbXjkvsC+X
|
||||
HKRr3NlRM/DygzTyj0gN74uoa0goCIbyAQhiT42nm0cuhM7uN/W0ayrlZjGF1cbR
|
||||
8NCJUL2Nwj0ywKIavC99Ipkb8AsFwpVT6U6effs6
|
||||
=xybZ
|
||||
-----END PGP SIGNATURE-----`,
|
||||
`tree e7f9e96dd79c09b078cac8b303a7d3b9d65ff9b734e86060a4d20409fd379f9e
|
||||
parent 26e9ccc29fad747e9c5d9f4c9ddeb7eff61cc45ef6a8dc258cbeb181afc055e8
|
||||
author Adam Majer <amajer@suse.de> 1698676906 +0100
|
||||
committer Adam Majer <amajer@suse.de> 1698676906 +0100
|
||||
|
||||
signed commit`,
|
||||
"Adam Majer <amajer@suse.de>",
|
||||
},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
gitRepo, err := OpenRepositoryLocal(t.Context(), filepath.Join(testReposDir, testCase.repo))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, gitRepo)
|
||||
defer gitRepo.Close()
|
||||
|
||||
commitFromReader, err := CommitFromReader(testCase.sha, strings.NewReader(testCase.commitString))
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, commitFromReader)
|
||||
assert.Equal(t, testCase.sha, commitFromReader.ID)
|
||||
assert.Equal(t, testCase.signature, commitFromReader.Signature.Signature)
|
||||
assert.Equal(t, testCase.payload, commitFromReader.Signature.Payload)
|
||||
assert.Equal(t, testCase.author, commitFromReader.Author.String())
|
||||
|
||||
commitFromReader2, err := CommitFromReader(testCase.sha, strings.NewReader(testCase.commitString+"\n\n"))
|
||||
assert.NoError(t, err)
|
||||
commitFromReader.CommitMessage.MessageRaw += "\n\n"
|
||||
commitFromReader.Signature.Payload += "\n\n"
|
||||
assert.Equal(t, commitFromReader, commitFromReader2)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasPreviousCommit(t *testing.T) {
|
||||
|
||||
+34
-83
@@ -43,96 +43,47 @@ Hello from 2
|
||||
|
||||
func TestRepoGetDivergingCommits(t *testing.T) {
|
||||
repo := mockRepository("repo1_bare")
|
||||
do, err := GetDivergingCommits(t.Context(), repo, "master", "branch2")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &DivergeObject{
|
||||
Ahead: 1,
|
||||
Behind: 5,
|
||||
}, do)
|
||||
|
||||
do, err = GetDivergingCommits(t.Context(), repo, "master", "master")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &DivergeObject{
|
||||
Ahead: 0,
|
||||
Behind: 0,
|
||||
}, do)
|
||||
|
||||
do, err = GetDivergingCommits(t.Context(), repo, "master", "test")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &DivergeObject{
|
||||
Ahead: 0,
|
||||
Behind: 2,
|
||||
}, do)
|
||||
for _, testcase := range []struct {
|
||||
branch string
|
||||
expected DivergeObject
|
||||
}{
|
||||
{"branch2", DivergeObject{Ahead: 1, Behind: 5}},
|
||||
{"master", DivergeObject{Ahead: 0, Behind: 0}},
|
||||
{"test", DivergeObject{Ahead: 0, Behind: 2}},
|
||||
} {
|
||||
do, err := GetDivergingCommits(t.Context(), repo, "master", testcase.branch)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &testcase.expected, do)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCommitIDsBetweenReverse(t *testing.T) {
|
||||
repo := mockRepository("repo1_bare")
|
||||
|
||||
// tests raw commit IDs
|
||||
commitIDs, err := GetCommitIDsBetweenReverse(t.Context(), repo,
|
||||
"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
|
||||
"ce064814f4a0d337b333e646ece456cd39fab612",
|
||||
"",
|
||||
100,
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{
|
||||
startRef := "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2"
|
||||
endRef := "ce064814f4a0d337b333e646ece456cd39fab612"
|
||||
expectedCommitIDs := []string{
|
||||
"8006ff9adbf0cb94da7dad9e537e53817f9fa5c0",
|
||||
"6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1",
|
||||
"37991dec2c8e592043f47155ce4808d4580f9123",
|
||||
"feaf4ba6bc635fec442f46ddd4512416ec43c2c2",
|
||||
"ce064814f4a0d337b333e646ece456cd39fab612",
|
||||
}, commitIDs)
|
||||
|
||||
commitIDs, err = GetCommitIDsBetweenReverse(t.Context(), repo,
|
||||
"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
|
||||
"ce064814f4a0d337b333e646ece456cd39fab612",
|
||||
"6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1",
|
||||
100,
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{
|
||||
"37991dec2c8e592043f47155ce4808d4580f9123",
|
||||
"feaf4ba6bc635fec442f46ddd4512416ec43c2c2",
|
||||
"ce064814f4a0d337b333e646ece456cd39fab612",
|
||||
}, commitIDs)
|
||||
|
||||
commitIDs, err = GetCommitIDsBetweenReverse(t.Context(), repo,
|
||||
"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
|
||||
"ce064814f4a0d337b333e646ece456cd39fab612",
|
||||
"",
|
||||
3,
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{
|
||||
"37991dec2c8e592043f47155ce4808d4580f9123",
|
||||
"feaf4ba6bc635fec442f46ddd4512416ec43c2c2",
|
||||
"ce064814f4a0d337b333e646ece456cd39fab612",
|
||||
}, commitIDs)
|
||||
|
||||
// test branch names instead of raw commit IDs.
|
||||
commitIDs, err = GetCommitIDsBetweenReverse(t.Context(), repo,
|
||||
"test",
|
||||
"master",
|
||||
"",
|
||||
100,
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{
|
||||
"feaf4ba6bc635fec442f46ddd4512416ec43c2c2",
|
||||
"ce064814f4a0d337b333e646ece456cd39fab612",
|
||||
}, commitIDs)
|
||||
|
||||
// add notref to exclude test
|
||||
commitIDs, err = GetCommitIDsBetweenReverse(t.Context(), repo,
|
||||
"test",
|
||||
"master",
|
||||
"test",
|
||||
100,
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{
|
||||
"feaf4ba6bc635fec442f46ddd4512416ec43c2c2",
|
||||
"ce064814f4a0d337b333e646ece456cd39fab612",
|
||||
}, commitIDs)
|
||||
}
|
||||
for _, testcase := range []struct {
|
||||
startRef, endRef, notRef string
|
||||
limit int
|
||||
expected []string
|
||||
}{
|
||||
// tests raw commit IDs
|
||||
{startRef, endRef, "", 100, expectedCommitIDs},
|
||||
{startRef, endRef, expectedCommitIDs[1], 100, expectedCommitIDs[2:]},
|
||||
{startRef, endRef, "", 3, expectedCommitIDs[2:]},
|
||||
// test branch names instead of raw commit IDs.
|
||||
{"test", "master", "", 100, expectedCommitIDs[3:]},
|
||||
// add notref to exclude test
|
||||
{"test", "master", "test", 100, expectedCommitIDs[3:]},
|
||||
} {
|
||||
commitIDs, err := GetCommitIDsBetweenReverse(t.Context(), repo, testcase.startRef, testcase.endRef, testcase.notRef, testcase.limit)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, testcase.expected, commitIDs)
|
||||
}
|
||||
}
|
||||
+23
-45
@@ -20,9 +20,7 @@ func TestGrepSearch(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
defer repo.Close()
|
||||
|
||||
res, err := GrepSearch(t.Context(), repo, "void", GrepOptions{})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []*GrepResult{
|
||||
expectedResults := []*GrepResult{
|
||||
{
|
||||
Filename: "java-hello/main.java",
|
||||
LineNumbers: []int{3},
|
||||
@@ -33,49 +31,29 @@ func TestGrepSearch(t *testing.T) {
|
||||
LineNumbers: []int{3},
|
||||
LineCodes: []string{" public static void main(String[] args)"},
|
||||
},
|
||||
}, res)
|
||||
}
|
||||
for _, testcase := range []struct {
|
||||
options GrepOptions
|
||||
expected []*GrepResult
|
||||
}{
|
||||
{GrepOptions{}, expectedResults},
|
||||
{GrepOptions{PathspecList: []string{":(glob)java-hello/*"}}, expectedResults[:1]},
|
||||
{GrepOptions{PathspecList: []string{":(glob,exclude)java-hello/*"}}, expectedResults[1:]},
|
||||
{GrepOptions{MaxResultLimit: 1}, expectedResults[:1]},
|
||||
{GrepOptions{MaxResultLimit: 1, MaxLineLength: 39}, []*GrepResult{
|
||||
{
|
||||
Filename: "java-hello/main.java",
|
||||
LineNumbers: []int{3},
|
||||
LineCodes: []string{" public static void main(String[] arg"},
|
||||
},
|
||||
}},
|
||||
} {
|
||||
res, err := GrepSearch(t.Context(), repo, "void", testcase.options)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, testcase.expected, res)
|
||||
}
|
||||
|
||||
res, err = GrepSearch(t.Context(), repo, "void", GrepOptions{PathspecList: []string{":(glob)java-hello/*"}})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []*GrepResult{
|
||||
{
|
||||
Filename: "java-hello/main.java",
|
||||
LineNumbers: []int{3},
|
||||
LineCodes: []string{" public static void main(String[] args)"},
|
||||
},
|
||||
}, res)
|
||||
|
||||
res, err = GrepSearch(t.Context(), repo, "void", GrepOptions{PathspecList: []string{":(glob,exclude)java-hello/*"}})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []*GrepResult{
|
||||
{
|
||||
Filename: "main.vendor.java",
|
||||
LineNumbers: []int{3},
|
||||
LineCodes: []string{" public static void main(String[] args)"},
|
||||
},
|
||||
}, res)
|
||||
|
||||
res, err = GrepSearch(t.Context(), repo, "void", GrepOptions{MaxResultLimit: 1})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []*GrepResult{
|
||||
{
|
||||
Filename: "java-hello/main.java",
|
||||
LineNumbers: []int{3},
|
||||
LineCodes: []string{" public static void main(String[] args)"},
|
||||
},
|
||||
}, res)
|
||||
|
||||
res, err = GrepSearch(t.Context(), repo, "void", GrepOptions{MaxResultLimit: 1, MaxLineLength: 39})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []*GrepResult{
|
||||
{
|
||||
Filename: "java-hello/main.java",
|
||||
LineNumbers: []int{3},
|
||||
LineCodes: []string{" public static void main(String[] arg"},
|
||||
},
|
||||
}, res)
|
||||
|
||||
res, err = GrepSearch(t.Context(), repo, "no-such-content", GrepOptions{})
|
||||
res, err := GrepSearch(t.Context(), repo, "no-such-content", GrepOptions{})
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, res)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParseTreeEntriesLong(t *testing.T) {
|
||||
func TestParseTreeEntries(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Input string
|
||||
Expected []*TreeEntry
|
||||
@@ -53,22 +53,6 @@ func TestParseTreeEntriesLong(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
entries, err := ParseTreeEntries([]byte(testCase.Input))
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, entries, len(testCase.Expected))
|
||||
for i, entry := range entries {
|
||||
assert.Equal(t, testCase.Expected[i], entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTreeEntriesShort(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Input string
|
||||
Expected []*TreeEntry
|
||||
}{
|
||||
{
|
||||
Input: `100644 blob ea0d83c9081af9500ac9f804101b3fd0a5c293af README.md
|
||||
040000 tree 84b90550547016f73c5dd3f50dea662389e67b6d assets
|
||||
|
||||
@@ -40,30 +40,23 @@ func TestRepository_GetBlob_Found(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepository_GetBlob_NotExist(t *testing.T) {
|
||||
repoPath := filepath.Join(testReposDir, "repo1_bare")
|
||||
r, err := OpenRepositoryLocal(t.Context(), repoPath)
|
||||
assert.NoError(t, err)
|
||||
defer r.Close()
|
||||
func TestRepository_GetBlob_Errors(t *testing.T) {
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
id string
|
||||
err error
|
||||
}{
|
||||
{"NotExist", "0000000000000000000000000000000000000000", ErrNotExist{"0000000000000000000000000000000000000000", ""}},
|
||||
{"NoId", "", fmt.Errorf("length %d has no matched object format: %s", len(""), "")},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
r, err := OpenRepositoryLocal(t.Context(), filepath.Join(testReposDir, "repo1_bare"))
|
||||
assert.NoError(t, err)
|
||||
defer r.Close()
|
||||
|
||||
testCase := "0000000000000000000000000000000000000000"
|
||||
testError := ErrNotExist{testCase, ""}
|
||||
|
||||
blob, err := r.GetBlob(testCase)
|
||||
assert.Nil(t, blob)
|
||||
assert.EqualError(t, err, testError.Error())
|
||||
}
|
||||
|
||||
func TestRepository_GetBlob_NoId(t *testing.T) {
|
||||
repoPath := filepath.Join(testReposDir, "repo1_bare")
|
||||
r, err := OpenRepositoryLocal(t.Context(), repoPath)
|
||||
assert.NoError(t, err)
|
||||
defer r.Close()
|
||||
|
||||
testCase := ""
|
||||
testError := fmt.Errorf("length %d has no matched object format: %s", len(testCase), testCase)
|
||||
|
||||
blob, err := r.GetBlob(testCase)
|
||||
assert.Nil(t, blob)
|
||||
assert.EqualError(t, err, testError.Error())
|
||||
blob, err := r.GetBlob(testCase.id)
|
||||
assert.Nil(t, blob)
|
||||
assert.EqualError(t, err, testCase.err.Error())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
package git
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
@@ -96,100 +97,37 @@ func BenchmarkGetRefsBySha(b *testing.B) {
|
||||
_, _ = bareRepo5.GetRefsBySha(b.Context(), "58a4bcc53ac13e7ff76127e0fb518b5262bf09af", "")
|
||||
}
|
||||
|
||||
func TestRepository_IsObjectExist(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
repo, err := OpenRepositoryLocal(ctx, filepath.Join(testReposDir, "repo1_bare"))
|
||||
require.NoError(t, err)
|
||||
defer repo.Close()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
arg string
|
||||
want bool
|
||||
func TestRepository_Existence(t *testing.T) {
|
||||
for _, method := range []struct {
|
||||
name string
|
||||
exists func(*Repository, context.Context, string) bool
|
||||
branchExists bool
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
arg: "",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "branch",
|
||||
arg: "master",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "commit hash",
|
||||
arg: "ce064814f4a0d337b333e646ece456cd39fab612",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "short commit hash",
|
||||
arg: "ce06481",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "blob hash",
|
||||
arg: "153f451b9ee7fa1da317ab17a127e9fd9d384310",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "short blob hash",
|
||||
arg: "153f451",
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equal(t, tt.want, repo.IsObjectExist(ctx, tt.arg))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepository_IsReferenceExist(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
repo, err := OpenRepositoryLocal(ctx, filepath.Join(testReposDir, "repo1_bare"))
|
||||
require.NoError(t, err)
|
||||
defer repo.Close()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
arg string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
arg: "",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "branch",
|
||||
arg: "master",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "commit hash",
|
||||
arg: "ce064814f4a0d337b333e646ece456cd39fab612",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "short commit hash",
|
||||
arg: "ce06481",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "blob hash",
|
||||
arg: "153f451b9ee7fa1da317ab17a127e9fd9d384310",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "short blob hash",
|
||||
arg: "153f451",
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equal(t, tt.want, repo.IsReferenceExist(ctx, tt.arg))
|
||||
{"IsObjectExist", (*Repository).IsObjectExist, false},
|
||||
{"IsReferenceExist", (*Repository).IsReferenceExist, true},
|
||||
} {
|
||||
t.Run(method.name, func(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
repo, err := OpenRepositoryLocal(ctx, filepath.Join(testReposDir, "repo1_bare"))
|
||||
require.NoError(t, err)
|
||||
defer repo.Close()
|
||||
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
arg string
|
||||
want bool
|
||||
}{
|
||||
{"empty", "", false},
|
||||
{"branch", "master", method.branchExists},
|
||||
{"commit hash", "ce064814f4a0d337b333e646ece456cd39fab612", true},
|
||||
{"short commit hash", "ce06481", true},
|
||||
{"blob hash", "153f451b9ee7fa1da317ab17a127e9fd9d384310", true},
|
||||
{"short blob hash", "153f451", true},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
assert.Equal(t, testCase.want, method.exists(repo, ctx, testCase.arg))
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
+88
-108
@@ -16,91 +16,96 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRepository_GetCommitBranches(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
|
||||
bareRepo1, err := OpenRepositoryLocal(t.Context(), bareRepo1Path)
|
||||
assert.NoError(t, err)
|
||||
defer bareRepo1.Close()
|
||||
|
||||
// these test case are specific to the repo1_bare test repo
|
||||
testCases := []struct {
|
||||
CommitID string
|
||||
ExpectedBranches []string
|
||||
func TestRepository_CommitQueries(t *testing.T) {
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
run func(*testing.T, *Repository)
|
||||
}{
|
||||
{"2839944139e0de9737a044f78b0e4b40d989a9e3", []string{"branch1"}},
|
||||
{"5c80b0245c1c6f8343fa418ec374b13b5d4ee658", []string{"branch2"}},
|
||||
{"37991dec2c8e592043f47155ce4808d4580f9123", []string{"master"}},
|
||||
{"95bb4d39648ee7e325106df01a621c530863a653", []string{"branch1", "branch2"}},
|
||||
{"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2", []string{"branch2", "master"}},
|
||||
{"master", []string{"master"}},
|
||||
{"TestRepository_GetCommitBranches", func(t *testing.T, bareRepo1 *Repository) {
|
||||
// these test case are specific to the repo1_bare test repo
|
||||
testCases := []struct {
|
||||
CommitID string
|
||||
ExpectedBranches []string
|
||||
}{
|
||||
{"2839944139e0de9737a044f78b0e4b40d989a9e3", []string{"branch1"}},
|
||||
{"5c80b0245c1c6f8343fa418ec374b13b5d4ee658", []string{"branch2"}},
|
||||
{"37991dec2c8e592043f47155ce4808d4580f9123", []string{"master"}},
|
||||
{"95bb4d39648ee7e325106df01a621c530863a653", []string{"branch1", "branch2"}},
|
||||
{"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2", []string{"branch2", "master"}},
|
||||
{"master", []string{"master"}},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
commit, err := bareRepo1.GetCommit(t.Context(), testCase.CommitID)
|
||||
assert.NoError(t, err)
|
||||
branches, err := bareRepo1.getBranches(t.Context(), nil, commit.ID.String(), 2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, testCase.ExpectedBranches, branches)
|
||||
}
|
||||
}},
|
||||
{"TestGetTagCommitWithSignature", func(t *testing.T, bareRepo1 *Repository) {
|
||||
// both the tag and the commit are signed here, this validates only the commit signature
|
||||
commit, err := bareRepo1.GetCommit(t.Context(), "28b55526e7100924d864dd89e35c1ea62e7a5a32")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, commit)
|
||||
assert.NotNil(t, commit.Signature)
|
||||
// test that signature is not in message
|
||||
assert.Equal(t, "signed-commit\n", commit.CommitMessage.MessageRaw)
|
||||
}},
|
||||
{"TestGetCommitWithBadCommitID", func(t *testing.T, bareRepo1 *Repository) {
|
||||
commit, err := bareRepo1.GetCommit(t.Context(), "bad_branch")
|
||||
assert.Nil(t, commit)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNotExist(err))
|
||||
}},
|
||||
{"TestIsCommitInRepo", func(t *testing.T, bareRepo1 *Repository) {
|
||||
exist, err := IsCommitInRepo(t.Context(), bareRepo1, "2839944139e0de9737a044f78b0e4b40d989a9e3")
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, exist)
|
||||
|
||||
exist, err = IsCommitInRepo(t.Context(), bareRepo1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, exist)
|
||||
}},
|
||||
{"TestIsCommitInBranch", func(t *testing.T, bareRepo1 *Repository) {
|
||||
result, err := IsCommitInBranch(t.Context(), bareRepo1, "2839944139e0de9737a044f78b0e4b40d989a9e3", "branch1")
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, result)
|
||||
|
||||
result, err = IsCommitInBranch(t.Context(), bareRepo1, "2839944139e0de9737a044f78b0e4b40d989a9e3", "branch2")
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, result)
|
||||
|
||||
result, err = IsCommitInBranch(t.Context(), bareRepo1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "branch1")
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, result)
|
||||
}},
|
||||
{"TestGetRefCommitID", func(t *testing.T, bareRepo1 *Repository) {
|
||||
// these test case are specific to the repo1_bare test repo
|
||||
testCases := []struct {
|
||||
Ref string
|
||||
ExpectedCommitID string
|
||||
}{
|
||||
{RefNameFromBranch("master").String(), "ce064814f4a0d337b333e646ece456cd39fab612"},
|
||||
{RefNameFromBranch("branch1").String(), "2839944139e0de9737a044f78b0e4b40d989a9e3"},
|
||||
{RefNameFromTag("test").String(), "3ad28a9149a2864384548f3d17ed7f38014c9e8a"},
|
||||
{"ce064814f4a0d337b333e646ece456cd39fab612", "ce064814f4a0d337b333e646ece456cd39fab612"},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
commitID, err := bareRepo1.GetRefCommitID(t.Context(), testCase.Ref)
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, testCase.ExpectedCommitID, commitID)
|
||||
}
|
||||
}
|
||||
}},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
bareRepo1, err := OpenRepositoryLocal(t.Context(), filepath.Join(testReposDir, "repo1_bare"))
|
||||
assert.NoError(t, err)
|
||||
defer bareRepo1.Close()
|
||||
testCase.run(t, bareRepo1)
|
||||
})
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
commit, err := bareRepo1.GetCommit(t.Context(), testCase.CommitID)
|
||||
assert.NoError(t, err)
|
||||
branches, err := bareRepo1.getBranches(t.Context(), nil, commit.ID.String(), 2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, testCase.ExpectedBranches, branches)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTagCommitWithSignature(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
|
||||
bareRepo1, err := OpenRepositoryLocal(t.Context(), bareRepo1Path)
|
||||
assert.NoError(t, err)
|
||||
defer bareRepo1.Close()
|
||||
|
||||
// both the tag and the commit are signed here, this validates only the commit signature
|
||||
commit, err := bareRepo1.GetCommit(t.Context(), "28b55526e7100924d864dd89e35c1ea62e7a5a32")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, commit)
|
||||
assert.NotNil(t, commit.Signature)
|
||||
// test that signature is not in message
|
||||
assert.Equal(t, "signed-commit\n", commit.CommitMessage.MessageRaw)
|
||||
}
|
||||
|
||||
func TestGetCommitWithBadCommitID(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
|
||||
bareRepo1, err := OpenRepositoryLocal(t.Context(), bareRepo1Path)
|
||||
assert.NoError(t, err)
|
||||
defer bareRepo1.Close()
|
||||
|
||||
commit, err := bareRepo1.GetCommit(t.Context(), "bad_branch")
|
||||
assert.Nil(t, commit)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNotExist(err))
|
||||
}
|
||||
|
||||
func TestIsCommitInRepo(t *testing.T) {
|
||||
bareRepo1, err := OpenRepositoryLocal(t.Context(), filepath.Join(testReposDir, "repo1_bare"))
|
||||
assert.NoError(t, err)
|
||||
defer bareRepo1.Close()
|
||||
|
||||
exist, err := IsCommitInRepo(t.Context(), bareRepo1, "2839944139e0de9737a044f78b0e4b40d989a9e3")
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, exist)
|
||||
|
||||
exist, err = IsCommitInRepo(t.Context(), bareRepo1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, exist)
|
||||
}
|
||||
|
||||
func TestIsCommitInBranch(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
|
||||
bareRepo1, err := OpenRepositoryLocal(t.Context(), bareRepo1Path)
|
||||
assert.NoError(t, err)
|
||||
defer bareRepo1.Close()
|
||||
|
||||
result, err := IsCommitInBranch(t.Context(), bareRepo1, "2839944139e0de9737a044f78b0e4b40d989a9e3", "branch1")
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, result)
|
||||
|
||||
result, err = IsCommitInBranch(t.Context(), bareRepo1, "2839944139e0de9737a044f78b0e4b40d989a9e3", "branch2")
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, result)
|
||||
|
||||
result, err = IsCommitInBranch(t.Context(), bareRepo1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "branch1")
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, result)
|
||||
}
|
||||
|
||||
func TestRepository_CommitsBetween(t *testing.T) {
|
||||
@@ -125,31 +130,6 @@ func TestRepository_CommitsBetween(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRefCommitID(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
|
||||
bareRepo1, err := OpenRepositoryLocal(t.Context(), bareRepo1Path)
|
||||
assert.NoError(t, err)
|
||||
defer bareRepo1.Close()
|
||||
|
||||
// these test case are specific to the repo1_bare test repo
|
||||
testCases := []struct {
|
||||
Ref string
|
||||
ExpectedCommitID string
|
||||
}{
|
||||
{RefNameFromBranch("master").String(), "ce064814f4a0d337b333e646ece456cd39fab612"},
|
||||
{RefNameFromBranch("branch1").String(), "2839944139e0de9737a044f78b0e4b40d989a9e3"},
|
||||
{RefNameFromTag("test").String(), "3ad28a9149a2864384548f3d17ed7f38014c9e8a"},
|
||||
{"ce064814f4a0d337b333e646ece456cd39fab612", "ce064814f4a0d337b333e646ece456cd39fab612"},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
commitID, err := bareRepo1.GetRefCommitID(t.Context(), testCase.Ref)
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, testCase.ExpectedCommitID, commitID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitsByFileAndRange(t *testing.T) {
|
||||
defer test.MockVariableValue(&setting.Git.CommitsRangeSize, 2)()
|
||||
|
||||
|
||||
@@ -185,6 +185,22 @@ func TestRepository_GetAnnotatedTag(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRepository_parseTagRef(t *testing.T) {
|
||||
signature := `-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
aBCGzBAABCgAdFiEEyWRwv/q1Q6IjSv+D4IPOwzt33PoFAmI8jbIACgkQ4IPOwzt3
|
||||
3PoRuAv9FVSbPBXvzECubls9KQd7urwEvcfG20Uf79iBwifQJUv+egNQojrs6APT
|
||||
T4CdIXeGRpwJZaGTUX9RWnoDO1SLXAWnc82CypWraNwrHq8Go2YeoVu0Iy3vb0EU
|
||||
REdob/tXYZecMuP8AjhUR0XfdYaERYAvJ2dYsH/UkFrqDjM3V4kPXWG+R5DCaZiE
|
||||
slB5U01i4Dwb/zm/ckzhUGEcOgcnpOKX8SnY5kYRVDY47dl/yJZ1u2XWir3mu60G
|
||||
1geIitH7StBddHi/8rz+sJwTfcVaLjn2p59p/Dr9aGbk17GIaKq1j0pZA2lKT0Xt
|
||||
f9jDqU+9vCxnKgjSDhrwN69LF2jT47ZFjEMGV/wFPOa1EBxVWpgQ/CfEolBlbUqx
|
||||
yVpbxi/6AOK2lmG130e9jEZJcu+WeZUeq851WgKSEkf2d5f/JpwtSTEOlOedu6V6
|
||||
kl845zu5oE2nKM4zMQ7XrYQn538I31ps+VGQ0H8R07WrZP8WKUWugL2cU8KmXFwg
|
||||
qbHDASXl
|
||||
=2yGi
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
`
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -273,38 +289,8 @@ func TestRepository_parseTagRef(t *testing.T) {
|
||||
* add changelog of v1.9.1
|
||||
* Update CHANGELOG.md
|
||||
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
aBCGzBAABCgAdFiEEyWRwv/q1Q6IjSv+D4IPOwzt33PoFAmI8jbIACgkQ4IPOwzt3
|
||||
3PoRuAv9FVSbPBXvzECubls9KQd7urwEvcfG20Uf79iBwifQJUv+egNQojrs6APT
|
||||
T4CdIXeGRpwJZaGTUX9RWnoDO1SLXAWnc82CypWraNwrHq8Go2YeoVu0Iy3vb0EU
|
||||
REdob/tXYZecMuP8AjhUR0XfdYaERYAvJ2dYsH/UkFrqDjM3V4kPXWG+R5DCaZiE
|
||||
slB5U01i4Dwb/zm/ckzhUGEcOgcnpOKX8SnY5kYRVDY47dl/yJZ1u2XWir3mu60G
|
||||
1geIitH7StBddHi/8rz+sJwTfcVaLjn2p59p/Dr9aGbk17GIaKq1j0pZA2lKT0Xt
|
||||
f9jDqU+9vCxnKgjSDhrwN69LF2jT47ZFjEMGV/wFPOa1EBxVWpgQ/CfEolBlbUqx
|
||||
yVpbxi/6AOK2lmG130e9jEZJcu+WeZUeq851WgKSEkf2d5f/JpwtSTEOlOedu6V6
|
||||
kl845zu5oE2nKM4zMQ7XrYQn538I31ps+VGQ0H8R07WrZP8WKUWugL2cU8KmXFwg
|
||||
qbHDASXl
|
||||
=2yGi
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
`,
|
||||
"contents:signature": `-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
aBCGzBAABCgAdFiEEyWRwv/q1Q6IjSv+D4IPOwzt33PoFAmI8jbIACgkQ4IPOwzt3
|
||||
3PoRuAv9FVSbPBXvzECubls9KQd7urwEvcfG20Uf79iBwifQJUv+egNQojrs6APT
|
||||
T4CdIXeGRpwJZaGTUX9RWnoDO1SLXAWnc82CypWraNwrHq8Go2YeoVu0Iy3vb0EU
|
||||
REdob/tXYZecMuP8AjhUR0XfdYaERYAvJ2dYsH/UkFrqDjM3V4kPXWG+R5DCaZiE
|
||||
slB5U01i4Dwb/zm/ckzhUGEcOgcnpOKX8SnY5kYRVDY47dl/yJZ1u2XWir3mu60G
|
||||
1geIitH7StBddHi/8rz+sJwTfcVaLjn2p59p/Dr9aGbk17GIaKq1j0pZA2lKT0Xt
|
||||
f9jDqU+9vCxnKgjSDhrwN69LF2jT47ZFjEMGV/wFPOa1EBxVWpgQ/CfEolBlbUqx
|
||||
yVpbxi/6AOK2lmG130e9jEZJcu+WeZUeq851WgKSEkf2d5f/JpwtSTEOlOedu6V6
|
||||
kl845zu5oE2nKM4zMQ7XrYQn538I31ps+VGQ0H8R07WrZP8WKUWugL2cU8KmXFwg
|
||||
qbHDASXl
|
||||
=2yGi
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
`,
|
||||
` + signature,
|
||||
"contents:signature": signature,
|
||||
},
|
||||
|
||||
want: &Tag{
|
||||
@@ -315,22 +301,7 @@ qbHDASXl
|
||||
Tagger: parseSignatureFromCommitLine("Foo Bar <foo@bar.com> 1565789218 +0300"),
|
||||
CommitMessage: CommitMessage{MessageRaw: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n"},
|
||||
Signature: &CommitSignature{
|
||||
Signature: `-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
aBCGzBAABCgAdFiEEyWRwv/q1Q6IjSv+D4IPOwzt33PoFAmI8jbIACgkQ4IPOwzt3
|
||||
3PoRuAv9FVSbPBXvzECubls9KQd7urwEvcfG20Uf79iBwifQJUv+egNQojrs6APT
|
||||
T4CdIXeGRpwJZaGTUX9RWnoDO1SLXAWnc82CypWraNwrHq8Go2YeoVu0Iy3vb0EU
|
||||
REdob/tXYZecMuP8AjhUR0XfdYaERYAvJ2dYsH/UkFrqDjM3V4kPXWG+R5DCaZiE
|
||||
slB5U01i4Dwb/zm/ckzhUGEcOgcnpOKX8SnY5kYRVDY47dl/yJZ1u2XWir3mu60G
|
||||
1geIitH7StBddHi/8rz+sJwTfcVaLjn2p59p/Dr9aGbk17GIaKq1j0pZA2lKT0Xt
|
||||
f9jDqU+9vCxnKgjSDhrwN69LF2jT47ZFjEMGV/wFPOa1EBxVWpgQ/CfEolBlbUqx
|
||||
yVpbxi/6AOK2lmG130e9jEZJcu+WeZUeq851WgKSEkf2d5f/JpwtSTEOlOedu6V6
|
||||
kl845zu5oE2nKM4zMQ7XrYQn538I31ps+VGQ0H8R07WrZP8WKUWugL2cU8KmXFwg
|
||||
qbHDASXl
|
||||
=2yGi
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
`,
|
||||
Signature: signature,
|
||||
Payload: `object 3325fd8a973321fd59455492976c042dde3fd1ca
|
||||
type commit
|
||||
tag v0.0.1
|
||||
|
||||
@@ -11,37 +11,18 @@ import (
|
||||
)
|
||||
|
||||
func TestParseSignatureFromCommitLine(t *testing.T) {
|
||||
tests := []struct {
|
||||
line string
|
||||
want *Signature
|
||||
}{
|
||||
{
|
||||
line: "a b <c@d.com> 12345 +0100",
|
||||
want: &Signature{
|
||||
Name: "a b",
|
||||
Email: "c@d.com",
|
||||
When: time.Unix(12345, 0).In(time.FixedZone("", 3600)),
|
||||
},
|
||||
},
|
||||
{
|
||||
line: "bad line",
|
||||
want: &Signature{Name: "bad line"},
|
||||
},
|
||||
{
|
||||
line: "bad < line",
|
||||
want: &Signature{Name: "bad < line"},
|
||||
},
|
||||
{
|
||||
line: "bad > line",
|
||||
want: &Signature{Name: "bad > line"},
|
||||
},
|
||||
{
|
||||
line: "bad-line <name@example.com>",
|
||||
want: &Signature{Name: "bad-line <name@example.com>"},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
got := parseSignatureFromCommitLine(test.line)
|
||||
assert.Equal(t, test.want, got)
|
||||
assert.Equal(t, &Signature{
|
||||
Name: "a b",
|
||||
Email: "c@d.com",
|
||||
When: time.Unix(12345, 0).In(time.FixedZone("", 3600)),
|
||||
}, parseSignatureFromCommitLine("a b <c@d.com> 12345 +0100"))
|
||||
|
||||
for _, line := range []string{
|
||||
"bad line",
|
||||
"bad < line",
|
||||
"bad > line",
|
||||
"bad-line <name@example.com>",
|
||||
} {
|
||||
assert.Equal(t, &Signature{Name: line}, parseSignatureFromCommitLine(line))
|
||||
}
|
||||
}
|
||||
@@ -46,32 +46,22 @@ func TestFollowLink(t *testing.T) {
|
||||
assert.Nil(t, res)
|
||||
}
|
||||
|
||||
{
|
||||
// should error for broken links
|
||||
entry, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, "foo/broken_link")
|
||||
for _, test := range []struct {
|
||||
fullPath string
|
||||
symlinkContent string
|
||||
checkLink bool
|
||||
}{
|
||||
{"foo/broken_link", "nar/broken_link", true}, // should error for broken links
|
||||
{"foo/outside_repo", "../../outside_repo", true}, // should error for external links
|
||||
{"foo/link_short", "a", false}, // testing fix for short link bug
|
||||
} {
|
||||
entry, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, test.fullPath)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, entry.IsLink())
|
||||
res, err := EntryFollowLink(t.Context(), r, commit, "foo/broken_link", entry)
|
||||
if test.checkLink {
|
||||
assert.True(t, entry.IsLink())
|
||||
}
|
||||
res, err := EntryFollowLink(t.Context(), r, commit, test.fullPath, entry)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
assert.Equal(t, "nar/broken_link", res.SymlinkContent)
|
||||
}
|
||||
|
||||
{
|
||||
// should error for external links
|
||||
entry, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, "foo/outside_repo")
|
||||
require.NoError(t, err)
|
||||
assert.True(t, entry.IsLink())
|
||||
res, err := EntryFollowLink(t.Context(), r, commit, "foo/outside_repo", entry)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
assert.Equal(t, "../../outside_repo", res.SymlinkContent)
|
||||
}
|
||||
|
||||
{
|
||||
// testing fix for short link bug
|
||||
entry, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, "foo/link_short")
|
||||
require.NoError(t, err)
|
||||
res, err := EntryFollowLink(t.Context(), r, commit, "foo/link_short", entry)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
assert.Equal(t, "a", res.SymlinkContent)
|
||||
assert.Equal(t, test.symlinkContent, res.SymlinkContent)
|
||||
}
|
||||
}
|
||||
+41
-169
@@ -17,156 +17,37 @@ import (
|
||||
)
|
||||
|
||||
func TestParseGitURLs(t *testing.T) {
|
||||
kases := []struct {
|
||||
kase string
|
||||
expected *GitURL
|
||||
for _, kase := range []struct {
|
||||
kase, scheme, host, path string
|
||||
user *url.Userinfo
|
||||
extraMark int
|
||||
}{
|
||||
{
|
||||
kase: "git@127.0.0.1:go-gitea/gitea.git",
|
||||
expected: &GitURL{
|
||||
URL: &url.URL{
|
||||
Scheme: "ssh",
|
||||
User: url.User("git"),
|
||||
Host: "127.0.0.1",
|
||||
Path: "go-gitea/gitea.git",
|
||||
},
|
||||
extraMark: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
kase: "git@[fe80::14fc:cec5:c174:d88%2510]:go-gitea/gitea.git",
|
||||
expected: &GitURL{
|
||||
URL: &url.URL{
|
||||
Scheme: "ssh",
|
||||
User: url.User("git"),
|
||||
Host: "[fe80::14fc:cec5:c174:d88%10]",
|
||||
Path: "go-gitea/gitea.git",
|
||||
},
|
||||
extraMark: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
kase: "git@[::1]:go-gitea/gitea.git",
|
||||
expected: &GitURL{
|
||||
URL: &url.URL{
|
||||
Scheme: "ssh",
|
||||
User: url.User("git"),
|
||||
Host: "[::1]",
|
||||
Path: "go-gitea/gitea.git",
|
||||
},
|
||||
extraMark: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
kase: "git@github.com:go-gitea/gitea.git",
|
||||
expected: &GitURL{
|
||||
URL: &url.URL{
|
||||
Scheme: "ssh",
|
||||
User: url.User("git"),
|
||||
Host: "github.com",
|
||||
Path: "go-gitea/gitea.git",
|
||||
},
|
||||
extraMark: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
kase: "ssh://git@github.com/go-gitea/gitea.git",
|
||||
expected: &GitURL{
|
||||
URL: &url.URL{
|
||||
Scheme: "ssh",
|
||||
User: url.User("git"),
|
||||
Host: "github.com",
|
||||
Path: "/go-gitea/gitea.git",
|
||||
},
|
||||
extraMark: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
kase: "ssh://git@[::1]/go-gitea/gitea.git",
|
||||
expected: &GitURL{
|
||||
URL: &url.URL{
|
||||
Scheme: "ssh",
|
||||
User: url.User("git"),
|
||||
Host: "[::1]",
|
||||
Path: "/go-gitea/gitea.git",
|
||||
},
|
||||
extraMark: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
kase: "/repositories/go-gitea/gitea.git",
|
||||
expected: &GitURL{
|
||||
URL: &url.URL{
|
||||
Scheme: "file",
|
||||
Path: "/repositories/go-gitea/gitea.git",
|
||||
},
|
||||
extraMark: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
kase: "file:///repositories/go-gitea/gitea.git",
|
||||
expected: &GitURL{
|
||||
URL: &url.URL{
|
||||
Scheme: "file",
|
||||
Path: "/repositories/go-gitea/gitea.git",
|
||||
},
|
||||
extraMark: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
kase: "https://github.com/go-gitea/gitea.git",
|
||||
expected: &GitURL{
|
||||
URL: &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "github.com",
|
||||
Path: "/go-gitea/gitea.git",
|
||||
},
|
||||
extraMark: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
kase: "https://git:git@github.com/go-gitea/gitea.git",
|
||||
expected: &GitURL{
|
||||
URL: &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "github.com",
|
||||
User: url.UserPassword("git", "git"),
|
||||
Path: "/go-gitea/gitea.git",
|
||||
},
|
||||
extraMark: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
kase: "https://[fe80::14fc:cec5:c174:d88%2510]:20/go-gitea/gitea.git",
|
||||
expected: &GitURL{
|
||||
URL: &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "[fe80::14fc:cec5:c174:d88%10]:20",
|
||||
Path: "/go-gitea/gitea.git",
|
||||
},
|
||||
extraMark: 0,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
kase: "git://github.com/go-gitea/gitea.git",
|
||||
expected: &GitURL{
|
||||
URL: &url.URL{
|
||||
Scheme: "git",
|
||||
Host: "github.com",
|
||||
Path: "/go-gitea/gitea.git",
|
||||
},
|
||||
extraMark: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, kase := range kases {
|
||||
{"git@127.0.0.1:go-gitea/gitea.git", "ssh", "127.0.0.1", "go-gitea/gitea.git", url.User("git"), 1},
|
||||
{"git@[fe80::14fc:cec5:c174:d88%2510]:go-gitea/gitea.git", "ssh", "[fe80::14fc:cec5:c174:d88%10]", "go-gitea/gitea.git", url.User("git"), 1},
|
||||
{"git@[::1]:go-gitea/gitea.git", "ssh", "[::1]", "go-gitea/gitea.git", url.User("git"), 1},
|
||||
{"git@github.com:go-gitea/gitea.git", "ssh", "github.com", "go-gitea/gitea.git", url.User("git"), 1},
|
||||
{"ssh://git@github.com/go-gitea/gitea.git", "ssh", "github.com", "/go-gitea/gitea.git", url.User("git"), 0},
|
||||
{"ssh://git@[::1]/go-gitea/gitea.git", "ssh", "[::1]", "/go-gitea/gitea.git", url.User("git"), 0},
|
||||
{"/repositories/go-gitea/gitea.git", "file", "", "/repositories/go-gitea/gitea.git", nil, 2},
|
||||
{"file:///repositories/go-gitea/gitea.git", "file", "", "/repositories/go-gitea/gitea.git", nil, 0},
|
||||
{"https://github.com/go-gitea/gitea.git", "https", "github.com", "/go-gitea/gitea.git", nil, 0},
|
||||
{"https://git:git@github.com/go-gitea/gitea.git", "https", "github.com", "/go-gitea/gitea.git", url.UserPassword("git", "git"), 0},
|
||||
{"https://[fe80::14fc:cec5:c174:d88%2510]:20/go-gitea/gitea.git", "https", "[fe80::14fc:cec5:c174:d88%10]:20", "/go-gitea/gitea.git", nil, 0},
|
||||
{"git://github.com/go-gitea/gitea.git", "git", "github.com", "/go-gitea/gitea.git", nil, 0},
|
||||
} {
|
||||
t.Run(kase.kase, func(t *testing.T) {
|
||||
u, err := ParseGitURL(kase.kase)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, kase.expected.extraMark, u.extraMark)
|
||||
assert.Equal(t, *kase.expected, *u)
|
||||
assert.Equal(t, kase.extraMark, u.extraMark)
|
||||
assert.Equal(t, GitURL{
|
||||
URL: &url.URL{
|
||||
Scheme: kase.scheme,
|
||||
User: kase.user,
|
||||
Host: kase.host,
|
||||
Path: kase.path,
|
||||
},
|
||||
extraMark: kase.extraMark,
|
||||
}, *u)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -251,27 +132,18 @@ func TestMakeRepositoryBaseLink(t *testing.T) {
|
||||
defer test.MockVariableValue(&setting.AppURL, "https://localhost:3000/subpath")()
|
||||
defer test.MockVariableValue(&setting.AppSubURL, "/subpath")()
|
||||
|
||||
u, err := ParseRepositoryURL(t.Context(), "https://localhost:3000/subpath/user/repo.git")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "/subpath/user/repo", MakeRepositoryWebLink(u))
|
||||
|
||||
u, err = ParseRepositoryURL(t.Context(), "https://github.com/owner/repo.git")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "https://github.com/owner/repo", MakeRepositoryWebLink(u))
|
||||
|
||||
u, err = ParseRepositoryURL(t.Context(), "git@github.com:owner/repo.git")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "https://github.com/owner/repo", MakeRepositoryWebLink(u))
|
||||
|
||||
u, err = ParseRepositoryURL(t.Context(), "git+ssh://other:123/owner/repo.git")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "https://other/owner/repo", MakeRepositoryWebLink(u))
|
||||
|
||||
u, err = ParseRepositoryURL(t.Context(), "git+ssh://[::1]/owner/repo.git")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "https://[::1]/owner/repo", MakeRepositoryWebLink(u))
|
||||
|
||||
u, err = ParseRepositoryURL(t.Context(), "git+ssh://[::1]:2222/owner/repo.git")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "https://[::1]/owner/repo", MakeRepositoryWebLink(u))
|
||||
for _, kase := range []struct {
|
||||
input, expected string
|
||||
}{
|
||||
{"https://localhost:3000/subpath/user/repo.git", "/subpath/user/repo"},
|
||||
{"https://github.com/owner/repo.git", "https://github.com/owner/repo"},
|
||||
{"git@github.com:owner/repo.git", "https://github.com/owner/repo"},
|
||||
{"git+ssh://other:123/owner/repo.git", "https://other/owner/repo"},
|
||||
{"git+ssh://[::1]/owner/repo.git", "https://[::1]/owner/repo"},
|
||||
{"git+ssh://[::1]:2222/owner/repo.git", "https://[::1]/owner/repo"},
|
||||
} {
|
||||
u, err := ParseRepositoryURL(t.Context(), kase.input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, kase.expected, MakeRepositoryWebLink(u))
|
||||
}
|
||||
}
|
||||
@@ -34,12 +34,14 @@ func TestFile(t *testing.T) {
|
||||
name string
|
||||
code string
|
||||
want []template.HTML
|
||||
plainWant []template.HTML
|
||||
lexerName string
|
||||
}{
|
||||
{
|
||||
name: "empty.py",
|
||||
code: "",
|
||||
want: lines(""),
|
||||
plainWant: lines(""),
|
||||
lexerName: "Python",
|
||||
},
|
||||
{
|
||||
@@ -64,18 +66,21 @@ func TestFile(t *testing.T) {
|
||||
name: "tags.py",
|
||||
code: "<>",
|
||||
want: lines(`<span class="o"><></span>`),
|
||||
plainWant: lines("<>"),
|
||||
lexerName: "Python",
|
||||
},
|
||||
{
|
||||
name: "eol-no.py",
|
||||
code: "a=1",
|
||||
want: lines(`<span class="n">a</span><span class="o">=</span><span class="mi">1</span>`),
|
||||
plainWant: lines(`a=1`),
|
||||
lexerName: "Python",
|
||||
},
|
||||
{
|
||||
name: "eol-newline1.py",
|
||||
code: "a=1\n",
|
||||
want: lines(`<span class="n">a</span><span class="o">=</span><span class="mi">1</span>\n`),
|
||||
plainWant: lines(`a=1\n`),
|
||||
lexerName: "Python",
|
||||
},
|
||||
{
|
||||
@@ -86,6 +91,10 @@ func TestFile(t *testing.T) {
|
||||
\n
|
||||
`,
|
||||
),
|
||||
plainWant: lines(`
|
||||
a=1\n
|
||||
\n
|
||||
`),
|
||||
lexerName: "Python",
|
||||
},
|
||||
{
|
||||
@@ -106,6 +115,13 @@ c=2
|
||||
\n
|
||||
<span class="n">c</span><span class="o">=</span><span class="mi">2</span>`,
|
||||
),
|
||||
plainWant: lines(`
|
||||
def:\n
|
||||
a=1\n
|
||||
\n
|
||||
b=''\n
|
||||
\n
|
||||
c=2`),
|
||||
lexerName: "Python",
|
||||
},
|
||||
{
|
||||
@@ -135,67 +151,14 @@ Content-Type: text/html
|
||||
assert.Equal(t, tt.lexerName, lexerName)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlainText(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
code string
|
||||
want []template.HTML
|
||||
}{
|
||||
{
|
||||
name: "empty.py",
|
||||
code: "",
|
||||
want: lines(""),
|
||||
},
|
||||
{
|
||||
name: "tags.py",
|
||||
code: "<>",
|
||||
want: lines("<>"),
|
||||
},
|
||||
{
|
||||
name: "eol-no.py",
|
||||
code: "a=1",
|
||||
want: lines(`a=1`),
|
||||
},
|
||||
{
|
||||
name: "eol-newline1.py",
|
||||
code: "a=1\n",
|
||||
want: lines(`a=1\n`),
|
||||
},
|
||||
{
|
||||
name: "eol-newline2.py",
|
||||
code: "a=1\n\n",
|
||||
want: lines(`
|
||||
a=1\n
|
||||
\n
|
||||
`),
|
||||
},
|
||||
{
|
||||
name: "empty-line-with-space.py",
|
||||
code: strings.ReplaceAll(strings.TrimSpace(`
|
||||
def:
|
||||
a=1
|
||||
|
||||
b=''
|
||||
{space}
|
||||
c=2
|
||||
`), "{space}", " "),
|
||||
want: lines(`
|
||||
def:\n
|
||||
a=1\n
|
||||
\n
|
||||
b=''\n
|
||||
\n
|
||||
c=2`),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
out := renderPlainText([]byte(tt.code))
|
||||
assert.Equal(t, tt.want, out)
|
||||
})
|
||||
if tt.plainWant != nil {
|
||||
t.Run("plaintext/"+tt.name, func(t *testing.T) {
|
||||
out := renderPlainText([]byte(tt.code))
|
||||
assert.Equal(t, tt.plainWant, out)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,76 +25,58 @@ func TestHandleGenericETagCache(t *testing.T) {
|
||||
respEtag string
|
||||
reqHeaders map[string]string
|
||||
wantHandled bool
|
||||
wantHeaders map[string]string
|
||||
wantStatus int
|
||||
}
|
||||
cases := []testCase{
|
||||
{
|
||||
name: "No If-None-Match",
|
||||
wantHandled: false,
|
||||
wantHeaders: map[string]string{"Last-Modified": lastModified, "Cache-Control": cacheControl, "Etag": matchedEtag},
|
||||
},
|
||||
{
|
||||
name: "Mismatched If-None-Match",
|
||||
reqHeaders: map[string]string{"If-None-Match": `"mismatched-etag"`},
|
||||
wantHandled: false,
|
||||
wantHeaders: map[string]string{"Last-Modified": lastModified, "Cache-Control": cacheControl, "Etag": matchedEtag},
|
||||
},
|
||||
{
|
||||
name: "Matched If-None-Match",
|
||||
reqHeaders: map[string]string{"If-None-Match": matchedEtag},
|
||||
wantHandled: true,
|
||||
wantHeaders: map[string]string{"Last-Modified": lastModified, "Cache-Control": "", "Etag": matchedEtag},
|
||||
wantStatus: http.StatusNotModified,
|
||||
},
|
||||
{
|
||||
name: "Multiple Mismatched If-None-Match",
|
||||
reqHeaders: map[string]string{"If-None-Match": `"mismatched-etag1", "mismatched-etag2"`},
|
||||
wantHandled: false,
|
||||
wantHeaders: map[string]string{"Last-Modified": lastModified, "Cache-Control": cacheControl, "Etag": matchedEtag},
|
||||
},
|
||||
{
|
||||
name: "Wildcard If-None-Match matches any current representation",
|
||||
reqHeaders: map[string]string{"If-None-Match": "*"},
|
||||
wantHandled: true,
|
||||
wantHeaders: map[string]string{"Last-Modified": lastModified, "Cache-Control": "", "Etag": matchedEtag},
|
||||
wantStatus: http.StatusNotModified,
|
||||
},
|
||||
{
|
||||
name: "Weak response tag matched by a strong request tag",
|
||||
respEtag: weakEtag,
|
||||
reqHeaders: map[string]string{"If-None-Match": matchedEtag},
|
||||
wantHandled: true,
|
||||
wantHeaders: map[string]string{"Last-Modified": lastModified, "Cache-Control": "", "Etag": weakEtag},
|
||||
wantStatus: http.StatusNotModified,
|
||||
},
|
||||
{
|
||||
name: "Weak response tag matched by a weak request tag",
|
||||
respEtag: weakEtag,
|
||||
reqHeaders: map[string]string{"If-None-Match": weakEtag},
|
||||
wantHandled: true,
|
||||
wantHeaders: map[string]string{"Last-Modified": lastModified, "Cache-Control": "", "Etag": weakEtag},
|
||||
wantStatus: http.StatusNotModified,
|
||||
},
|
||||
{
|
||||
name: "If-Modified-Since without If-None-Match",
|
||||
reqHeaders: map[string]string{"If-Modified-Since": lastModified},
|
||||
wantHandled: true,
|
||||
wantHeaders: map[string]string{"Last-Modified": lastModified, "Cache-Control": "", "Etag": matchedEtag},
|
||||
wantStatus: http.StatusNotModified,
|
||||
},
|
||||
{
|
||||
name: "Mismatched If-None-Match takes precedence over If-Modified-Since",
|
||||
reqHeaders: map[string]string{"If-None-Match": `"mismatched-etag"`, "If-Modified-Since": lastModified},
|
||||
wantHandled: false,
|
||||
wantHeaders: map[string]string{"Last-Modified": lastModified, "Cache-Control": cacheControl, "Etag": matchedEtag},
|
||||
},
|
||||
{
|
||||
name: "Multiple Matched If-None-Match",
|
||||
reqHeaders: map[string]string{"If-None-Match": `"mismatched-etag", ` + matchedEtag},
|
||||
wantHandled: true,
|
||||
wantHeaders: map[string]string{"Last-Modified": lastModified, "Cache-Control": "", "Etag": matchedEtag},
|
||||
wantStatus: http.StatusNotModified,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -107,10 +89,14 @@ func TestHandleGenericETagCache(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
assert.Equal(t, tc.wantHandled, HandleGenericETagPrivateCache(req, w, util.IfZero(tc.respEtag, matchedEtag), lastModifiedTime))
|
||||
resp := w.Result()
|
||||
for k, v := range tc.wantHeaders {
|
||||
for k, v := range map[string]string{
|
||||
"Last-Modified": lastModified,
|
||||
"Cache-Control": util.Iif(tc.wantHandled, "", cacheControl),
|
||||
"Etag": util.IfZero(tc.respEtag, matchedEtag),
|
||||
} {
|
||||
assert.Equal(t, v, resp.Header.Get(k))
|
||||
}
|
||||
assert.Equal(t, tc.wantStatus, util.Iif(resp.StatusCode == http.StatusOK, 0, resp.StatusCode))
|
||||
assert.Equal(t, util.Iif(tc.wantHandled, http.StatusNotModified, 0), util.Iif(resp.StatusCode == http.StatusOK, 0, resp.StatusCode))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -18,95 +18,51 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestServeUserContentByReader(t *testing.T) {
|
||||
func TestServeUserContent(t *testing.T) {
|
||||
data := "0123456789abcdef"
|
||||
|
||||
test := func(t *testing.T, expectedStatusCode int, expectedContent string) {
|
||||
_, rangeStr, _ := strings.Cut(t.Name(), "_range_")
|
||||
r := &http.Request{Header: http.Header{}, Form: url.Values{}}
|
||||
if rangeStr != "" {
|
||||
r.Header.Set("Range", "bytes="+rangeStr)
|
||||
}
|
||||
reader := strings.NewReader(data)
|
||||
w := httptest.NewRecorder()
|
||||
ServeUserContentByReader(r, w, int64(len(data)), reader, ServeHeaderOptions{})
|
||||
assert.Equal(t, expectedStatusCode, w.Code)
|
||||
if expectedStatusCode == http.StatusPartialContent || expectedStatusCode == http.StatusOK {
|
||||
assert.Equal(t, strconv.Itoa(len(expectedContent)), w.Header().Get("Content-Length"))
|
||||
assert.Equal(t, expectedContent, w.Body.String())
|
||||
}
|
||||
for _, source := range []string{"reader", "file"} {
|
||||
t.Run(source, func(t *testing.T) {
|
||||
var tmpFile string
|
||||
if source == "file" {
|
||||
tmpFile = t.TempDir() + "/test"
|
||||
assert.NoError(t, os.WriteFile(tmpFile, []byte(data), 0o644))
|
||||
}
|
||||
for _, tc := range []struct {
|
||||
rangeStr string
|
||||
expectedStatusCode int
|
||||
expectedContent string
|
||||
}{
|
||||
{"", http.StatusOK, data},
|
||||
{"0-", http.StatusPartialContent, data},
|
||||
{"0-15", http.StatusPartialContent, data},
|
||||
{"1-", http.StatusPartialContent, data[1:]},
|
||||
{"1-3", http.StatusPartialContent, data[1 : 3+1]},
|
||||
{"16-", http.StatusRequestedRangeNotSatisfiable, ""},
|
||||
{"1-99999", http.StatusPartialContent, data[1:]},
|
||||
} {
|
||||
t.Run("_range_"+tc.rangeStr, func(t *testing.T) {
|
||||
r := &http.Request{Header: http.Header{}, Form: url.Values{}}
|
||||
if tc.rangeStr != "" {
|
||||
r.Header.Set("Range", "bytes="+tc.rangeStr)
|
||||
}
|
||||
w := httptest.NewRecorder()
|
||||
if source == "file" {
|
||||
seekReader, err := os.OpenFile(tmpFile, os.O_RDONLY, 0o644)
|
||||
require.NoError(t, err)
|
||||
defer seekReader.Close()
|
||||
ServeUserContentByFile(r, w, seekReader, ServeHeaderOptions{})
|
||||
} else {
|
||||
ServeUserContentByReader(r, w, int64(len(data)), strings.NewReader(data), ServeHeaderOptions{})
|
||||
}
|
||||
assert.Equal(t, tc.expectedStatusCode, w.Code)
|
||||
if tc.expectedStatusCode == http.StatusPartialContent || tc.expectedStatusCode == http.StatusOK {
|
||||
assert.Equal(t, strconv.Itoa(len(tc.expectedContent)), w.Header().Get("Content-Length"))
|
||||
assert.Equal(t, tc.expectedContent, w.Body.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("_range_", func(t *testing.T) {
|
||||
test(t, http.StatusOK, data)
|
||||
})
|
||||
t.Run("_range_0-", func(t *testing.T) {
|
||||
test(t, http.StatusPartialContent, data)
|
||||
})
|
||||
t.Run("_range_0-15", func(t *testing.T) {
|
||||
test(t, http.StatusPartialContent, data)
|
||||
})
|
||||
t.Run("_range_1-", func(t *testing.T) {
|
||||
test(t, http.StatusPartialContent, data[1:])
|
||||
})
|
||||
t.Run("_range_1-3", func(t *testing.T) {
|
||||
test(t, http.StatusPartialContent, data[1:3+1])
|
||||
})
|
||||
t.Run("_range_16-", func(t *testing.T) {
|
||||
test(t, http.StatusRequestedRangeNotSatisfiable, "")
|
||||
})
|
||||
t.Run("_range_1-99999", func(t *testing.T) {
|
||||
test(t, http.StatusPartialContent, data[1:])
|
||||
})
|
||||
}
|
||||
|
||||
func TestServeUserContentByFile(t *testing.T) {
|
||||
data := "0123456789abcdef"
|
||||
tmpFile := t.TempDir() + "/test"
|
||||
err := os.WriteFile(tmpFile, []byte(data), 0o644)
|
||||
assert.NoError(t, err)
|
||||
|
||||
test := func(t *testing.T, expectedStatusCode int, expectedContent string) {
|
||||
_, rangeStr, _ := strings.Cut(t.Name(), "_range_")
|
||||
r := &http.Request{Header: http.Header{}, Form: url.Values{}}
|
||||
if rangeStr != "" {
|
||||
r.Header.Set("Range", "bytes="+rangeStr)
|
||||
}
|
||||
|
||||
seekReader, err := os.OpenFile(tmpFile, os.O_RDONLY, 0o644)
|
||||
require.NoError(t, err)
|
||||
defer seekReader.Close()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
ServeUserContentByFile(r, w, seekReader, ServeHeaderOptions{})
|
||||
assert.Equal(t, expectedStatusCode, w.Code)
|
||||
if expectedStatusCode == http.StatusPartialContent || expectedStatusCode == http.StatusOK {
|
||||
assert.Equal(t, strconv.Itoa(len(expectedContent)), w.Header().Get("Content-Length"))
|
||||
assert.Equal(t, expectedContent, w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("_range_", func(t *testing.T) {
|
||||
test(t, http.StatusOK, data)
|
||||
})
|
||||
t.Run("_range_0-", func(t *testing.T) {
|
||||
test(t, http.StatusPartialContent, data)
|
||||
})
|
||||
t.Run("_range_0-15", func(t *testing.T) {
|
||||
test(t, http.StatusPartialContent, data)
|
||||
})
|
||||
t.Run("_range_1-", func(t *testing.T) {
|
||||
test(t, http.StatusPartialContent, data[1:])
|
||||
})
|
||||
t.Run("_range_1-3", func(t *testing.T) {
|
||||
test(t, http.StatusPartialContent, data[1:3+1])
|
||||
})
|
||||
t.Run("_range_16-", func(t *testing.T) {
|
||||
test(t, http.StatusRequestedRangeNotSatisfiable, "")
|
||||
})
|
||||
t.Run("_range_1-99999", func(t *testing.T) {
|
||||
test(t, http.StatusPartialContent, data[1:])
|
||||
})
|
||||
}
|
||||
|
||||
func TestServeSetHeaderContentRelated(t *testing.T) {
|
||||
|
||||
@@ -21,99 +21,72 @@ func TestBleveIndexer(t *testing.T) {
|
||||
tests.TestIndexer(t, indexer)
|
||||
}
|
||||
|
||||
func TestBleveIndexerNoAssignee(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
indexer := NewIndexer(dir)
|
||||
defer indexer.Close()
|
||||
|
||||
_, err := indexer.Init(t.Context())
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, indexer.Index(t.Context(),
|
||||
&internal.IndexerData{ID: 1, Title: "assigned through assignee_ids", AssigneeIDs: []int64{2}},
|
||||
&internal.IndexerData{ID: 2, Title: "unassigned", NoAssignee: true},
|
||||
&internal.IndexerData{ID: 3, Title: "assigned through multiple assignee_ids", AssigneeIDs: []int64{3, 4}},
|
||||
))
|
||||
|
||||
testCases := []struct {
|
||||
func TestBleveIndexerSearch(t *testing.T) {
|
||||
type searchCase struct {
|
||||
name string
|
||||
opts *internal.SearchOptions
|
||||
expectedIDs []int64
|
||||
}
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
data []*internal.IndexerData
|
||||
searches []searchCase
|
||||
checkTotal bool
|
||||
}{
|
||||
{
|
||||
name: "none",
|
||||
opts: &internal.SearchOptions{AssigneeID: "(none)"},
|
||||
expectedIDs: []int64{2},
|
||||
name: "no assignee",
|
||||
data: []*internal.IndexerData{
|
||||
{ID: 1, Title: "assigned through assignee_ids", AssigneeIDs: []int64{2}},
|
||||
{ID: 2, Title: "unassigned", NoAssignee: true},
|
||||
{ID: 3, Title: "assigned through multiple assignee_ids", AssigneeIDs: []int64{3, 4}},
|
||||
},
|
||||
searches: []searchCase{
|
||||
{"none", &internal.SearchOptions{AssigneeID: "(none)"}, []int64{2}},
|
||||
{"any", &internal.SearchOptions{AssigneeID: "(any)"}, []int64{1, 3}},
|
||||
{"specific", &internal.SearchOptions{AssigneeID: "2"}, []int64{1}},
|
||||
{"specific first multi-assignee", &internal.SearchOptions{AssigneeID: "3"}, []int64{3}},
|
||||
{"specific second multi-assignee", &internal.SearchOptions{AssigneeID: "4"}, []int64{3}},
|
||||
},
|
||||
checkTotal: true,
|
||||
},
|
||||
{
|
||||
name: "any",
|
||||
opts: &internal.SearchOptions{AssigneeID: "(any)"},
|
||||
expectedIDs: []int64{1, 3},
|
||||
name: "token filter",
|
||||
data: []*internal.IndexerData{
|
||||
{ID: 1, Title: "fix(packages): SomeThing needs a rewrite (#12345)"},
|
||||
{ID: 2, Title: "add support for mDNS discovery abc1234"},
|
||||
},
|
||||
searches: []searchCase{
|
||||
{"exact original case", &internal.SearchOptions{Keyword: "SomeThing"}, []int64{1}},
|
||||
{"case matching original transitions", &internal.SearchOptions{Keyword: "someThing"}, []int64{1}},
|
||||
{"all lower case", &internal.SearchOptions{Keyword: "something"}, []int64{1}},
|
||||
{"all upper case", &internal.SearchOptions{Keyword: "SOMETHING"}, []int64{1}},
|
||||
{"number match", &internal.SearchOptions{Keyword: "12345"}, []int64{1}},
|
||||
{"number as part", &internal.SearchOptions{Keyword: "1234"}, []int64{2}},
|
||||
{"sub-word search still works", &internal.SearchOptions{Keyword: "DNS"}, []int64{2}},
|
||||
{"sub-word search, lower case", &internal.SearchOptions{Keyword: "mdns"}, []int64{2}},
|
||||
{"keyword is camel case", &internal.SearchOptions{Keyword: "addSupport"}, []int64{2}},
|
||||
{"keyword not match", &internal.SearchOptions{Keyword: "addsupport"}, []int64{}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "specific",
|
||||
opts: &internal.SearchOptions{AssigneeID: "2"},
|
||||
expectedIDs: []int64{1},
|
||||
},
|
||||
{
|
||||
name: "specific first multi-assignee",
|
||||
opts: &internal.SearchOptions{AssigneeID: "3"},
|
||||
expectedIDs: []int64{3},
|
||||
},
|
||||
{
|
||||
name: "specific second multi-assignee",
|
||||
opts: &internal.SearchOptions{AssigneeID: "4"},
|
||||
expectedIDs: []int64{3},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
result, err := indexer.Search(t.Context(), testCase.opts)
|
||||
indexer := NewIndexer(t.TempDir())
|
||||
defer indexer.Close()
|
||||
|
||||
_, err := indexer.Init(t.Context())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(len(testCase.expectedIDs)), result.Total)
|
||||
assert.ElementsMatch(t, testCase.expectedIDs, searchResultIDs(result))
|
||||
})
|
||||
}
|
||||
}
|
||||
require.NoError(t, indexer.Index(t.Context(), testCase.data...))
|
||||
|
||||
func TestBleveIndexerTokenFilter(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
indexer := NewIndexer(dir)
|
||||
defer indexer.Close()
|
||||
|
||||
_, err := indexer.Init(t.Context())
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, indexer.Index(t.Context(),
|
||||
&internal.IndexerData{ID: 1, Title: "fix(packages): SomeThing needs a rewrite (#12345)"},
|
||||
&internal.IndexerData{ID: 2, Title: "add support for mDNS discovery abc1234"},
|
||||
))
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
keyword string
|
||||
expectedIDs []int64
|
||||
}{
|
||||
{name: "exact original case", keyword: "SomeThing", expectedIDs: []int64{1}},
|
||||
{name: "case matching original transitions", keyword: "someThing", expectedIDs: []int64{1}},
|
||||
{name: "all lower case", keyword: "something", expectedIDs: []int64{1}},
|
||||
{name: "all upper case", keyword: "SOMETHING", expectedIDs: []int64{1}},
|
||||
{name: "number match", keyword: "12345", expectedIDs: []int64{1}},
|
||||
{name: "number as part", keyword: "1234", expectedIDs: []int64{2}},
|
||||
{name: "sub-word search still works", keyword: "DNS", expectedIDs: []int64{2}},
|
||||
{name: "sub-word search, lower case", keyword: "mdns", expectedIDs: []int64{2}},
|
||||
{name: "keyword is camel case", keyword: "addSupport", expectedIDs: []int64{2}},
|
||||
{name: "keyword not match", keyword: "addsupport", expectedIDs: []int64{}},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
result, err := indexer.Search(t.Context(), &internal.SearchOptions{
|
||||
Keyword: testCase.keyword,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.ElementsMatch(t, testCase.expectedIDs, searchResultIDs(result))
|
||||
for _, search := range testCase.searches {
|
||||
t.Run(search.name, func(t *testing.T) {
|
||||
result, err := indexer.Search(t.Context(), search.opts)
|
||||
require.NoError(t, err)
|
||||
if testCase.checkTotal {
|
||||
assert.Equal(t, int64(len(search.expectedIDs)), result.Total)
|
||||
}
|
||||
assert.ElementsMatch(t, search.expectedIDs, searchResultIDs(result))
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,5 @@ func TestDoubleQuoteKeyword(t *testing.T) {
|
||||
assert.Empty(t, doubleQuoteKeyword(""))
|
||||
assert.Equal(t, `"a" "b" "c"`, doubleQuoteKeyword("a b c"))
|
||||
assert.Equal(t, `"a" "d" "g"`, doubleQuoteKeyword("a d g"))
|
||||
assert.Equal(t, `"a" "d" "g"`, doubleQuoteKeyword("a d g"))
|
||||
assert.Equal(t, `"a" "d" "g"`, doubleQuoteKeyword(`a "" "d" """g`))
|
||||
}
|
||||
@@ -15,6 +15,11 @@ import (
|
||||
)
|
||||
|
||||
func TestValidate(t *testing.T) {
|
||||
const metadata = `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
`
|
||||
tests := []struct {
|
||||
name string
|
||||
filename string
|
||||
@@ -44,21 +49,13 @@ about: "this is about"
|
||||
},
|
||||
{
|
||||
name: "markdown miss value",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "markdown"
|
||||
content: metadata + ` - type: "markdown"
|
||||
`,
|
||||
wantErr: "body[0](markdown): 'value' is required",
|
||||
},
|
||||
{
|
||||
name: "markdown invalid value",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "markdown"
|
||||
content: metadata + ` - type: "markdown"
|
||||
attributes:
|
||||
value: true
|
||||
`,
|
||||
@@ -66,11 +63,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "markdown empty value",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "markdown"
|
||||
content: metadata + ` - type: "markdown"
|
||||
attributes:
|
||||
value: ""
|
||||
`,
|
||||
@@ -78,33 +71,21 @@ body:
|
||||
},
|
||||
{
|
||||
name: "textarea invalid id",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "textarea"
|
||||
content: metadata + ` - type: "textarea"
|
||||
id: "?"
|
||||
`,
|
||||
wantErr: "body[0](textarea): 'id' should contain only alphanumeric, '-' and '_'",
|
||||
},
|
||||
{
|
||||
name: "textarea miss label",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "textarea"
|
||||
content: metadata + ` - type: "textarea"
|
||||
id: "1"
|
||||
`,
|
||||
wantErr: "body[0](textarea): 'label' is required",
|
||||
},
|
||||
{
|
||||
name: "textarea conflict id",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "textarea"
|
||||
content: metadata + ` - type: "textarea"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -117,11 +98,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "textarea invalid description",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "textarea"
|
||||
content: metadata + ` - type: "textarea"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -131,11 +108,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "textarea invalid required",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "textarea"
|
||||
content: metadata + ` - type: "textarea"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -146,11 +119,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "input invalid description",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "input"
|
||||
content: metadata + ` - type: "input"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -160,11 +129,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "input invalid is_number",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "input"
|
||||
content: metadata + ` - type: "input"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -175,11 +140,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "input invalid regex",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "input"
|
||||
content: metadata + ` - type: "input"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -190,11 +151,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "dropdown invalid description",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "dropdown"
|
||||
content: metadata + ` - type: "dropdown"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -204,11 +161,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "dropdown invalid multiple",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "dropdown"
|
||||
content: metadata + ` - type: "dropdown"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -218,11 +171,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "dropdown invalid list",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "dropdown"
|
||||
content: metadata + ` - type: "dropdown"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -232,11 +181,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "checkboxes invalid description",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "checkboxes"
|
||||
content: metadata + ` - type: "checkboxes"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -246,11 +191,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "invalid type",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "video"
|
||||
content: metadata + ` - type: "video"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -259,11 +200,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "dropdown miss options",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "dropdown"
|
||||
content: metadata + ` - type: "dropdown"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -272,11 +209,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "dropdown invalid options",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "dropdown"
|
||||
content: metadata + ` - type: "dropdown"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -288,11 +221,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "checkboxes invalid options",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "checkboxes"
|
||||
content: metadata + ` - type: "checkboxes"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -304,11 +233,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "checkboxes option miss label",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "checkboxes"
|
||||
content: metadata + ` - type: "checkboxes"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -319,11 +244,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "checkboxes option invalid required",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "checkboxes"
|
||||
content: metadata + ` - type: "checkboxes"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -335,11 +256,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "field is required but hidden",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: "input"
|
||||
content: metadata + ` - type: "input"
|
||||
id: "1"
|
||||
attributes:
|
||||
label: "a"
|
||||
@@ -351,11 +268,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "checkboxes is required but hidden",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: checkboxes
|
||||
content: metadata + ` - type: checkboxes
|
||||
id: "1"
|
||||
attributes:
|
||||
label: Label of checkboxes
|
||||
@@ -371,11 +284,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "dropdown default is not an integer",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: dropdown
|
||||
content: metadata + ` - type: dropdown
|
||||
id: "1"
|
||||
attributes:
|
||||
label: Label of dropdown
|
||||
@@ -393,11 +302,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "dropdown default is out of range",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: dropdown
|
||||
content: metadata + ` - type: dropdown
|
||||
id: "1"
|
||||
attributes:
|
||||
label: Label of dropdown
|
||||
@@ -415,11 +320,7 @@ body:
|
||||
},
|
||||
{
|
||||
name: "dropdown without default is valid",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: dropdown
|
||||
content: metadata + ` - type: dropdown
|
||||
id: "1"
|
||||
attributes:
|
||||
label: Label of dropdown
|
||||
@@ -770,19 +671,8 @@ Content
|
||||
}
|
||||
|
||||
func TestRenderToMarkdown(t *testing.T) {
|
||||
type args struct {
|
||||
template string
|
||||
values url.Values
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "normal",
|
||||
args: args{
|
||||
template: `
|
||||
t.Run("normal", func(t *testing.T) {
|
||||
template, err := Unmarshal("test.yaml", []byte(`
|
||||
name: Name
|
||||
title: Title
|
||||
about: About
|
||||
@@ -860,18 +750,11 @@ body:
|
||||
visible: [form]
|
||||
- label: Hidden Option of checkboxes
|
||||
visible: [content]
|
||||
`,
|
||||
values: map[string][]string{
|
||||
"form-field-id3": {"Value of id3"},
|
||||
"form-field-id4": {"Value of id4"},
|
||||
"form-field-id5": {"0,1"},
|
||||
"form-field-id6": {"1,2"},
|
||||
"form-field-id7-0": {"on"},
|
||||
"form-field-id7-2": {"on"},
|
||||
},
|
||||
},
|
||||
|
||||
want: `Value of the markdown shown in created issue
|
||||
`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := `Value of the markdown shown in created issue
|
||||
|
||||
### Label of textarea
|
||||
|
||||
@@ -894,70 +777,35 @@ Option 1 of dropdown, Option 2 of dropdown
|
||||
- [ ] Option 2 of checkboxes
|
||||
- [ ] Hidden Option of checkboxes
|
||||
|
||||
`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
template, err := Unmarshal("test.yaml", []byte(tt.args.template))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := RenderToMarkdown(template, tt.args.values); got != tt.want {
|
||||
assert.Equal(t, tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
`
|
||||
if got := RenderToMarkdown(template, url.Values{
|
||||
"form-field-id3": {"Value of id3"},
|
||||
"form-field-id4": {"Value of id4"},
|
||||
"form-field-id5": {"0,1"},
|
||||
"form-field-id6": {"1,2"},
|
||||
"form-field-id7-0": {"on"},
|
||||
"form-field-id7-2": {"on"},
|
||||
}); got != want {
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Test_minQuotes(t *testing.T) {
|
||||
type args struct {
|
||||
value string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
name string
|
||||
value string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "without quote",
|
||||
args: args{
|
||||
value: "Hello\nWorld",
|
||||
},
|
||||
want: "```",
|
||||
},
|
||||
{
|
||||
name: "with 1 quote",
|
||||
args: args{
|
||||
value: "Hello\nWorld\n`text`\n",
|
||||
},
|
||||
want: "```",
|
||||
},
|
||||
{
|
||||
name: "with 3 quotes",
|
||||
args: args{
|
||||
value: "Hello\nWorld\n`text`\n```go\ntext\n```\n",
|
||||
},
|
||||
want: "````",
|
||||
},
|
||||
{
|
||||
name: "with more quotes",
|
||||
args: args{
|
||||
value: "Hello\nWorld\n`text`\n```go\ntext\n```\n``````````bash\ntext\n``````````\n",
|
||||
},
|
||||
want: "```````````",
|
||||
},
|
||||
{
|
||||
name: "not leading quotes",
|
||||
args: args{
|
||||
value: "Hello\nWorld`text````go\ntext`````````````bash\ntext``````````\n",
|
||||
},
|
||||
want: "```",
|
||||
},
|
||||
{"without quote", "Hello\nWorld", "```"},
|
||||
{"with 1 quote", "Hello\nWorld\n`text`\n", "```"},
|
||||
{"with 3 quotes", "Hello\nWorld\n`text`\n```go\ntext\n```\n", "````"},
|
||||
{"with more quotes", "Hello\nWorld\n`text`\n```go\ntext\n```\n``````````bash\ntext\n``````````\n", "```````````"},
|
||||
{"not leading quotes", "Hello\nWorld`text````go\ntext`````````````bash\ntext``````````\n", "```"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := minQuotes(tt.args.value)
|
||||
got := minQuotes(tt.value)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
|
||||
+94
-191
@@ -162,209 +162,112 @@ func lfsTestRoundtripHandler(req *http.Request) *http.Response {
|
||||
return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(payload)}
|
||||
}
|
||||
|
||||
func TestHTTPClientDownload(t *testing.T) {
|
||||
p := Pointer{Oid: "fb8f7d8435968c4f82a726a92395be4d16f2f63116caf36c8ad35c60831ab041", Size: 6}
|
||||
|
||||
hc := &http.Client{Transport: RoundTripFunc(func(req *http.Request) *http.Response {
|
||||
assert.Equal(t, "POST", req.Method)
|
||||
assert.Equal(t, MediaType, req.Header.Get("Content-type"))
|
||||
assert.Equal(t, AcceptHeader, req.Header.Get("Accept"))
|
||||
|
||||
var batchRequest BatchRequest
|
||||
err := json.NewDecoder(req.Body).Decode(&batchRequest)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "download", batchRequest.Operation)
|
||||
assert.Equal(t, &Reference{Name: "refs/heads/main"}, batchRequest.Ref)
|
||||
assert.Len(t, batchRequest.Objects, 1)
|
||||
assert.Equal(t, p.Oid, batchRequest.Objects[0].Oid)
|
||||
assert.Equal(t, p.Size, batchRequest.Objects[0].Size)
|
||||
|
||||
return lfsTestRoundtripHandler(req)
|
||||
})}
|
||||
dummy := &DummyTransferAdapter{}
|
||||
|
||||
cases := []struct {
|
||||
func TestHTTPClientTransfers(t *testing.T) {
|
||||
type clientCase struct {
|
||||
endpoint string
|
||||
expectedError string
|
||||
}
|
||||
for _, operation := range []struct {
|
||||
name string
|
||||
cases []clientCase
|
||||
}{
|
||||
{
|
||||
endpoint: "https://status-not-ok.io",
|
||||
expectedError: io.ErrUnexpectedEOF.Error(),
|
||||
name: "download",
|
||||
cases: []clientCase{
|
||||
{"https://status-not-ok.io", io.ErrUnexpectedEOF.Error()},
|
||||
{"https://invalid-json-response.io", "/(invalid json|invalid character)/"},
|
||||
{"https://valid-batch-request-download.io", ""},
|
||||
{"https://response-no-objects.io", ""},
|
||||
{"https://unknown-transfer-adapter.io", "TransferAdapter not found: "},
|
||||
{"https://error-in-response-objects.io", "Object not found"},
|
||||
{"https://empty-actions-map.io", "missing action 'download'"},
|
||||
{"https://download-actions-map.io", ""},
|
||||
{"https://upload-actions-map.io", "missing action 'download'"},
|
||||
{"https://verify-actions-map.io", "missing action 'download'"},
|
||||
{"https://unknown-actions-map.io", "missing action 'download'"},
|
||||
{"https://legacy-batch-request-download.io", ""},
|
||||
},
|
||||
},
|
||||
{
|
||||
endpoint: "https://invalid-json-response.io",
|
||||
expectedError: "/(invalid json|invalid character)/",
|
||||
name: "upload",
|
||||
cases: []clientCase{
|
||||
{"https://status-not-ok.io", io.ErrUnexpectedEOF.Error()},
|
||||
{"https://invalid-json-response.io", "/(invalid json|invalid character)/"},
|
||||
{"https://valid-batch-request-upload.io", ""},
|
||||
{"https://response-no-objects.io", ""},
|
||||
{"https://unknown-transfer-adapter.io", "TransferAdapter not found: "},
|
||||
{"https://error-in-response-objects.io", "Object not found"},
|
||||
{"https://empty-actions-map.io", ""},
|
||||
{"https://download-actions-map.io", "missing action 'upload'"},
|
||||
{"https://upload-actions-map.io", ""},
|
||||
{"https://verify-actions-map.io", "missing action 'upload'"},
|
||||
{"https://unknown-actions-map.io", "missing action 'upload'"},
|
||||
},
|
||||
},
|
||||
{
|
||||
endpoint: "https://valid-batch-request-download.io",
|
||||
expectedError: "",
|
||||
},
|
||||
{
|
||||
endpoint: "https://response-no-objects.io",
|
||||
expectedError: "",
|
||||
},
|
||||
{
|
||||
endpoint: "https://unknown-transfer-adapter.io",
|
||||
expectedError: "TransferAdapter not found: ",
|
||||
},
|
||||
{
|
||||
endpoint: "https://error-in-response-objects.io",
|
||||
expectedError: "Object not found",
|
||||
},
|
||||
{
|
||||
endpoint: "https://empty-actions-map.io",
|
||||
expectedError: "missing action 'download'",
|
||||
},
|
||||
{
|
||||
endpoint: "https://download-actions-map.io",
|
||||
expectedError: "",
|
||||
},
|
||||
{
|
||||
endpoint: "https://upload-actions-map.io",
|
||||
expectedError: "missing action 'download'",
|
||||
},
|
||||
{
|
||||
endpoint: "https://verify-actions-map.io",
|
||||
expectedError: "missing action 'download'",
|
||||
},
|
||||
{
|
||||
endpoint: "https://unknown-actions-map.io",
|
||||
expectedError: "missing action 'download'",
|
||||
},
|
||||
{
|
||||
endpoint: "https://legacy-batch-request-download.io",
|
||||
expectedError: "",
|
||||
},
|
||||
}
|
||||
} {
|
||||
t.Run(operation.name, func(t *testing.T) {
|
||||
p := Pointer{Oid: "fb8f7d8435968c4f82a726a92395be4d16f2f63116caf36c8ad35c60831ab041", Size: 6}
|
||||
|
||||
defer test.MockVariableValue(&setting.LFSClient.BatchOperationConcurrency, 8)()
|
||||
for _, c := range cases {
|
||||
t.Run(c.endpoint, func(t *testing.T) {
|
||||
client := &HTTPClient{
|
||||
client: hc,
|
||||
endpoint: c.endpoint,
|
||||
transfers: map[string]TransferAdapter{
|
||||
"dummy": dummy,
|
||||
},
|
||||
}
|
||||
hc := &http.Client{Transport: RoundTripFunc(func(req *http.Request) *http.Response {
|
||||
assert.Equal(t, "POST", req.Method)
|
||||
assert.Equal(t, MediaType, req.Header.Get("Content-type"))
|
||||
assert.Equal(t, AcceptHeader, req.Header.Get("Accept"))
|
||||
|
||||
err := client.Download(t.Context(), "refs/heads/main", []Pointer{p}, func(p Pointer, content io.ReadCloser, objectError error) error {
|
||||
if objectError != nil {
|
||||
return objectError
|
||||
}
|
||||
b, err := io.ReadAll(content)
|
||||
var batchRequest BatchRequest
|
||||
err := json.NewDecoder(req.Body).Decode(&batchRequest)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("dummy"), b)
|
||||
return nil
|
||||
})
|
||||
if c.expectedError != "" {
|
||||
if strings.HasPrefix(c.expectedError, "/") && strings.HasSuffix(c.expectedError, "/") {
|
||||
assert.Regexp(t, strings.Trim(c.expectedError, "/"), err.Error())
|
||||
|
||||
assert.Equal(t, operation.name, batchRequest.Operation)
|
||||
if operation.name == "download" {
|
||||
assert.Equal(t, &Reference{Name: "refs/heads/main"}, batchRequest.Ref)
|
||||
} else {
|
||||
assert.ErrorContains(t, err, c.expectedError)
|
||||
assert.Nil(t, batchRequest.Ref)
|
||||
}
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPClientUpload(t *testing.T) {
|
||||
p := Pointer{Oid: "fb8f7d8435968c4f82a726a92395be4d16f2f63116caf36c8ad35c60831ab041", Size: 6}
|
||||
|
||||
hc := &http.Client{Transport: RoundTripFunc(func(req *http.Request) *http.Response {
|
||||
assert.Equal(t, "POST", req.Method)
|
||||
assert.Equal(t, MediaType, req.Header.Get("Content-type"))
|
||||
assert.Equal(t, AcceptHeader, req.Header.Get("Accept"))
|
||||
|
||||
var batchRequest BatchRequest
|
||||
err := json.NewDecoder(req.Body).Decode(&batchRequest)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "upload", batchRequest.Operation)
|
||||
assert.Nil(t, batchRequest.Ref)
|
||||
assert.Len(t, batchRequest.Objects, 1)
|
||||
assert.Equal(t, p.Oid, batchRequest.Objects[0].Oid)
|
||||
assert.Equal(t, p.Size, batchRequest.Objects[0].Size)
|
||||
|
||||
return lfsTestRoundtripHandler(req)
|
||||
})}
|
||||
dummy := &DummyTransferAdapter{}
|
||||
|
||||
cases := []struct {
|
||||
endpoint string
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
endpoint: "https://status-not-ok.io",
|
||||
expectedError: io.ErrUnexpectedEOF.Error(),
|
||||
},
|
||||
{
|
||||
endpoint: "https://invalid-json-response.io",
|
||||
expectedError: "/(invalid json|invalid character)/",
|
||||
},
|
||||
{
|
||||
endpoint: "https://valid-batch-request-upload.io",
|
||||
expectedError: "",
|
||||
},
|
||||
{
|
||||
endpoint: "https://response-no-objects.io",
|
||||
expectedError: "",
|
||||
},
|
||||
{
|
||||
endpoint: "https://unknown-transfer-adapter.io",
|
||||
expectedError: "TransferAdapter not found: ",
|
||||
},
|
||||
{
|
||||
endpoint: "https://error-in-response-objects.io",
|
||||
expectedError: "Object not found",
|
||||
},
|
||||
{
|
||||
endpoint: "https://empty-actions-map.io",
|
||||
expectedError: "",
|
||||
},
|
||||
{
|
||||
endpoint: "https://download-actions-map.io",
|
||||
expectedError: "missing action 'upload'",
|
||||
},
|
||||
{
|
||||
endpoint: "https://upload-actions-map.io",
|
||||
expectedError: "",
|
||||
},
|
||||
{
|
||||
endpoint: "https://verify-actions-map.io",
|
||||
expectedError: "missing action 'upload'",
|
||||
},
|
||||
{
|
||||
endpoint: "https://unknown-actions-map.io",
|
||||
expectedError: "missing action 'upload'",
|
||||
},
|
||||
}
|
||||
|
||||
defer test.MockVariableValue(&setting.LFSClient.BatchOperationConcurrency, 8)()
|
||||
for _, c := range cases {
|
||||
t.Run(c.endpoint, func(t *testing.T) {
|
||||
client := &HTTPClient{
|
||||
client: hc,
|
||||
endpoint: c.endpoint,
|
||||
transfers: map[string]TransferAdapter{
|
||||
"dummy": dummy,
|
||||
},
|
||||
}
|
||||
|
||||
err := client.Upload(t.Context(), []Pointer{p}, func(p Pointer, objectError error) (io.ReadCloser, error) {
|
||||
return io.NopCloser(new(bytes.Buffer)), objectError
|
||||
})
|
||||
if c.expectedError != "" {
|
||||
if strings.HasPrefix(c.expectedError, "/") && strings.HasSuffix(c.expectedError, "/") {
|
||||
assert.Regexp(t, strings.Trim(c.expectedError, "/"), err.Error())
|
||||
} else {
|
||||
assert.ErrorContains(t, err, c.expectedError)
|
||||
}
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, batchRequest.Objects, 1)
|
||||
assert.Equal(t, p.Oid, batchRequest.Objects[0].Oid)
|
||||
assert.Equal(t, p.Size, batchRequest.Objects[0].Size)
|
||||
|
||||
return lfsTestRoundtripHandler(req)
|
||||
})}
|
||||
dummy := &DummyTransferAdapter{}
|
||||
|
||||
defer test.MockVariableValue(&setting.LFSClient.BatchOperationConcurrency, 8)()
|
||||
for _, testCase := range operation.cases {
|
||||
t.Run(testCase.endpoint, func(t *testing.T) {
|
||||
client := &HTTPClient{
|
||||
client: hc,
|
||||
endpoint: testCase.endpoint,
|
||||
transfers: map[string]TransferAdapter{
|
||||
"dummy": dummy,
|
||||
},
|
||||
}
|
||||
|
||||
var err error
|
||||
if operation.name == "download" {
|
||||
err = client.Download(t.Context(), "refs/heads/main", []Pointer{p}, func(p Pointer, content io.ReadCloser, objectError error) error {
|
||||
if objectError != nil {
|
||||
return objectError
|
||||
}
|
||||
b, err := io.ReadAll(content)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("dummy"), b)
|
||||
return nil
|
||||
})
|
||||
} else {
|
||||
err = client.Upload(t.Context(), []Pointer{p}, func(p Pointer, objectError error) (io.ReadCloser, error) {
|
||||
return io.NopCloser(new(bytes.Buffer)), objectError
|
||||
})
|
||||
}
|
||||
if testCase.expectedError != "" {
|
||||
if strings.HasPrefix(testCase.expectedError, "/") && strings.HasSuffix(testCase.expectedError, "/") {
|
||||
assert.Regexp(t, strings.Trim(testCase.expectedError, "/"), err.Error())
|
||||
} else {
|
||||
assert.ErrorContains(t, err, testCase.expectedError)
|
||||
}
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ func TestBasicTransferAdapter(t *testing.T) {
|
||||
hc := &http.Client{Transport: RoundTripFunc(roundTripHandler)}
|
||||
a := &BasicTransferAdapter{hc}
|
||||
|
||||
t.Run("Download", func(t *testing.T) {
|
||||
testOperation := func(t *testing.T, endpoint string, transfer func(*Link) error) {
|
||||
cases := []struct {
|
||||
link *Link
|
||||
expectederror string
|
||||
@@ -77,7 +77,7 @@ func TestBasicTransferAdapter(t *testing.T) {
|
||||
// case 0
|
||||
{
|
||||
link: &Link{
|
||||
Href: "https://download-request.io",
|
||||
Href: endpoint,
|
||||
Header: map[string]string{"test-header": "test-value"},
|
||||
},
|
||||
expectederror: "",
|
||||
@@ -93,46 +93,26 @@ func TestBasicTransferAdapter(t *testing.T) {
|
||||
}
|
||||
|
||||
for n, c := range cases {
|
||||
_, err := a.Download(t.Context(), c.link)
|
||||
err := transfer(c.link)
|
||||
if len(c.expectederror) > 0 {
|
||||
assert.Contains(t, err.Error(), c.expectederror, "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
||||
} else {
|
||||
assert.NoError(t, err, "case %d", n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("Download", func(t *testing.T) {
|
||||
testOperation(t, "https://download-request.io", func(link *Link) error {
|
||||
_, err := a.Download(t.Context(), link)
|
||||
return err
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Upload", func(t *testing.T) {
|
||||
cases := []struct {
|
||||
link *Link
|
||||
expectederror string
|
||||
}{
|
||||
// case 0
|
||||
{
|
||||
link: &Link{
|
||||
Href: "https://upload-request.io",
|
||||
Header: map[string]string{"test-header": "test-value"},
|
||||
},
|
||||
expectederror: "",
|
||||
},
|
||||
// case 1
|
||||
{
|
||||
link: &Link{
|
||||
Href: "https://error-response.io",
|
||||
Header: map[string]string{"test-header": "test-value"},
|
||||
},
|
||||
expectederror: "Object not found",
|
||||
},
|
||||
}
|
||||
|
||||
for n, c := range cases {
|
||||
err := a.Upload(t.Context(), c.link, p, strings.NewReader("dummy"))
|
||||
if len(c.expectederror) > 0 {
|
||||
assert.Contains(t, err.Error(), c.expectederror, "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
||||
} else {
|
||||
assert.NoError(t, err, "case %d", n)
|
||||
}
|
||||
}
|
||||
testOperation(t, "https://upload-request.io", func(link *Link) error {
|
||||
return a.Upload(t.Context(), link, p, strings.NewReader("dummy"))
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Upload created", func(t *testing.T) {
|
||||
@@ -145,35 +125,8 @@ func TestBasicTransferAdapter(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Verify", func(t *testing.T) {
|
||||
cases := []struct {
|
||||
link *Link
|
||||
expectederror string
|
||||
}{
|
||||
// case 0
|
||||
{
|
||||
link: &Link{
|
||||
Href: "https://verify-request.io",
|
||||
Header: map[string]string{"test-header": "test-value"},
|
||||
},
|
||||
expectederror: "",
|
||||
},
|
||||
// case 1
|
||||
{
|
||||
link: &Link{
|
||||
Href: "https://error-response.io",
|
||||
Header: map[string]string{"test-header": "test-value"},
|
||||
},
|
||||
expectederror: "Object not found",
|
||||
},
|
||||
}
|
||||
|
||||
for n, c := range cases {
|
||||
err := a.Verify(t.Context(), c.link, p)
|
||||
if len(c.expectederror) > 0 {
|
||||
assert.Contains(t, err.Error(), c.expectederror, "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
||||
} else {
|
||||
assert.NoError(t, err, "case %d", n)
|
||||
}
|
||||
}
|
||||
testOperation(t, "https://verify-request.io", func(link *Link) error {
|
||||
return a.Verify(t.Context(), link, p)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -11,45 +11,33 @@ import (
|
||||
)
|
||||
|
||||
func TestItoa(t *testing.T) {
|
||||
b := itoa(nil, 0, 0)
|
||||
assert.Equal(t, "0", string(b))
|
||||
|
||||
b = itoa(nil, 0, 1)
|
||||
assert.Equal(t, "0", string(b))
|
||||
|
||||
b = itoa(nil, 0, 2)
|
||||
assert.Equal(t, "00", string(b))
|
||||
for width, expected := range []string{"0", "0", "00"} {
|
||||
assert.Equal(t, expected, string(itoa(nil, 0, width)))
|
||||
}
|
||||
}
|
||||
|
||||
func TestEventFormatTextMessage(t *testing.T) {
|
||||
res := EventFormatTextMessage(&WriterMode{Prefix: "[PREFIX] ", Colorize: false, Flags: Flags{defined: true, flags: 0xffffffff}},
|
||||
&Event{
|
||||
Time: time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC),
|
||||
Caller: "caller",
|
||||
Filename: "filename",
|
||||
Line: 123,
|
||||
Level: ERROR,
|
||||
Stacktrace: "stacktrace",
|
||||
},
|
||||
"msg format: %v %v", "arg0", NewColoredValue("arg1", FgBlue),
|
||||
)
|
||||
|
||||
assert.Equal(t, `[PREFIX] 2020/01/02 03:04:05.000000 filename:123:caller [E] [no-gopid] msg format: arg0 arg1
|
||||
for _, testCase := range []struct {
|
||||
colorize bool
|
||||
expected string
|
||||
}{
|
||||
{false, `[PREFIX] 2020/01/02 03:04:05.000000 filename:123:caller [E] [no-gopid] msg format: arg0 arg1
|
||||
stacktrace
|
||||
|
||||
`, string(res))
|
||||
|
||||
res = EventFormatTextMessage(&WriterMode{Prefix: "[PREFIX] ", Colorize: true, Flags: Flags{defined: true, flags: 0xffffffff}},
|
||||
&Event{
|
||||
Time: time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC),
|
||||
Caller: "caller",
|
||||
Filename: "filename",
|
||||
Line: 123,
|
||||
Level: ERROR,
|
||||
Stacktrace: "stacktrace",
|
||||
},
|
||||
"msg format: %v %v", "arg0", NewColoredValue("arg1", FgBlue),
|
||||
)
|
||||
|
||||
assert.Equal(t, "[PREFIX] \x1b[36m2020/01/02 03:04:05.000000 \x1b[0m\x1b[32mfilename:123:\x1b[32mcaller\x1b[0m \x1b[1;31m[E]\x1b[0m [\x1b[93mno-gopid\x1b[0m] msg format: arg0 \x1b[34marg1\x1b[0m\n\tstacktrace\n\n", string(res))
|
||||
`},
|
||||
{true, "[PREFIX] \x1b[36m2020/01/02 03:04:05.000000 \x1b[0m\x1b[32mfilename:123:\x1b[32mcaller\x1b[0m \x1b[1;31m[E]\x1b[0m [\x1b[93mno-gopid\x1b[0m] msg format: arg0 \x1b[34marg1\x1b[0m\n\tstacktrace\n\n"},
|
||||
} {
|
||||
res := EventFormatTextMessage(&WriterMode{Prefix: "[PREFIX] ", Colorize: testCase.colorize, Flags: Flags{defined: true, flags: 0xffffffff}},
|
||||
&Event{
|
||||
Time: time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC),
|
||||
Caller: "caller",
|
||||
Filename: "filename",
|
||||
Line: 123,
|
||||
Level: ERROR,
|
||||
Stacktrace: "stacktrace",
|
||||
},
|
||||
"msg format: %v %v", "arg0", NewColoredValue("arg1", FgBlue),
|
||||
)
|
||||
assert.Equal(t, testCase.expected, string(res))
|
||||
}
|
||||
}
|
||||
+11
-19
@@ -24,25 +24,17 @@ func TestLevelMarshalUnmarshalJSON(t *testing.T) {
|
||||
assert.Equal(t, string(makeTestLevelBytes(INFO.String())), string(levelBytes))
|
||||
|
||||
var testLevel testLevel
|
||||
err = json.Unmarshal(levelBytes, &testLevel)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, INFO, testLevel.Level)
|
||||
|
||||
err = json.Unmarshal(makeTestLevelBytes(`FOFOO`), &testLevel)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, INFO, testLevel.Level)
|
||||
|
||||
err = json.Unmarshal(fmt.Appendf(nil, `{"level":%d}`, 2), &testLevel)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, INFO, testLevel.Level)
|
||||
|
||||
err = json.Unmarshal(fmt.Appendf(nil, `{"level":%d}`, 10012), &testLevel)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, INFO, testLevel.Level)
|
||||
|
||||
err = json.Unmarshal([]byte(`{"level":{}}`), &testLevel)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, INFO, testLevel.Level)
|
||||
for _, levelJSON := range [][]byte{
|
||||
levelBytes,
|
||||
makeTestLevelBytes(`FOFOO`),
|
||||
fmt.Appendf(nil, `{"level":%d}`, 2),
|
||||
fmt.Appendf(nil, `{"level":%d}`, 10012),
|
||||
[]byte(`{"level":{}}`),
|
||||
} {
|
||||
err = json.Unmarshal(levelJSON, &testLevel)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, INFO, testLevel.Level)
|
||||
}
|
||||
|
||||
assert.Equal(t, INFO.String(), Level(1001).String())
|
||||
|
||||
|
||||
+12
-21
@@ -21,27 +21,18 @@ func TestCamoHandleLink(t *testing.T) {
|
||||
setting.Camo.ServerURL = "https://image.proxy"
|
||||
setting.Camo.HMACKey = "geheim"
|
||||
dataURL := "data:image/png;base64,i//V"
|
||||
assert.Equal(t, dataURL, camoHandleLink(dataURL))
|
||||
|
||||
assert.Equal(t,
|
||||
"https://gitea.com/img.jpg",
|
||||
camoHandleLink("https://gitea.com/img.jpg"))
|
||||
assert.Equal(t,
|
||||
"https://testimages.org/img.jpg",
|
||||
camoHandleLink("https://testimages.org/img.jpg"))
|
||||
assert.Equal(t,
|
||||
"https://image.proxy/eivin43gJwGVIjR9MiYYtFIk0mw/aHR0cDovL3Rlc3RpbWFnZXMub3JnL2ltZy5qcGc",
|
||||
camoHandleLink("http://testimages.org/img.jpg"))
|
||||
test := func(expectedHTTPS string) {
|
||||
assert.Equal(t, dataURL, camoHandleLink(dataURL))
|
||||
assert.Equal(t,
|
||||
"https://gitea.com/img.jpg",
|
||||
camoHandleLink("https://gitea.com/img.jpg"))
|
||||
assert.Equal(t, expectedHTTPS, camoHandleLink("https://testimages.org/img.jpg"))
|
||||
assert.Equal(t,
|
||||
"https://image.proxy/eivin43gJwGVIjR9MiYYtFIk0mw/aHR0cDovL3Rlc3RpbWFnZXMub3JnL2ltZy5qcGc",
|
||||
camoHandleLink("http://testimages.org/img.jpg"))
|
||||
}
|
||||
|
||||
test("https://testimages.org/img.jpg")
|
||||
setting.Camo.Always = true
|
||||
assert.Equal(t, dataURL, camoHandleLink(dataURL))
|
||||
assert.Equal(t,
|
||||
"https://gitea.com/img.jpg",
|
||||
camoHandleLink("https://gitea.com/img.jpg"))
|
||||
assert.Equal(t,
|
||||
"https://image.proxy/tkdlvmqpbIr7SjONfHNgEU622y0/aHR0cHM6Ly90ZXN0aW1hZ2VzLm9yZy9pbWcuanBn",
|
||||
camoHandleLink("https://testimages.org/img.jpg"))
|
||||
assert.Equal(t,
|
||||
"https://image.proxy/eivin43gJwGVIjR9MiYYtFIk0mw/aHR0cDovL3Rlc3RpbWFnZXMub3JnL2ltZy5qcGc",
|
||||
camoHandleLink("http://testimages.org/img.jpg"))
|
||||
test("https://image.proxy/tkdlvmqpbIr7SjONfHNgEU622y0/aHR0cHM6Ly90ZXN0aW1hZ2VzLm9yZy9pbWcuanBn")
|
||||
}
|
||||
@@ -85,7 +85,6 @@ func TestRender_IssueIndexPattern(t *testing.T) {
|
||||
test("#abcd")
|
||||
test("test#1234")
|
||||
test("#1234test")
|
||||
test("#abcd")
|
||||
test("test!1234")
|
||||
test("!1234test")
|
||||
test(" test !1234test")
|
||||
@@ -257,16 +256,7 @@ func TestRender_IssueIndexPattern_NoShortPattern(t *testing.T) {
|
||||
testRenderIssueIndexPattern(t, "#1", "#1", NewTestRenderContext(metas))
|
||||
testRenderIssueIndexPattern(t, "#1312", "#1312", NewTestRenderContext(metas))
|
||||
testRenderIssueIndexPattern(t, "!1", "!1", NewTestRenderContext(metas))
|
||||
}
|
||||
|
||||
func TestRender_PostProcessIssueTitle(t *testing.T) {
|
||||
setting.AppURL = TestAppURL
|
||||
metas := map[string]string{
|
||||
"format": "https://someurl.com/{user}/{repo}/{index}",
|
||||
"user": "someUser",
|
||||
"repo": "someRepo",
|
||||
"style": IssueNameStyleNumeric,
|
||||
}
|
||||
actual := PostProcessIssueTitle(NewTestRenderContext(metas), "#1")
|
||||
assert.Equal(t, template.HTML("#1"), actual)
|
||||
}
|
||||
|
||||
@@ -37,43 +37,24 @@ func TestRender_IssueList(t *testing.T) {
|
||||
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
t.Run("NormalIssueRef", func(t *testing.T) {
|
||||
test(
|
||||
"#12345",
|
||||
for _, tc := range []struct {
|
||||
name, input, expected string
|
||||
}{
|
||||
{
|
||||
"NormalIssueRef", "#12345",
|
||||
`<p><a href="/test-user/test-repo/issues/12345" class="ref-issue" rel="nofollow">#12345</a></p>`,
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("ListIssueRef", func(t *testing.T) {
|
||||
test(
|
||||
"* #12345",
|
||||
`<ul>
|
||||
},
|
||||
{"ListIssueRef", "* #12345", `<ul>
|
||||
<li><div>issue #12345</div></li>
|
||||
</ul>`,
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("ListIssueRefNormal", func(t *testing.T) {
|
||||
test(
|
||||
"* foo #12345 bar",
|
||||
`<ul>
|
||||
</ul>`},
|
||||
{"ListIssueRefNormal", "* foo #12345 bar", `<ul>
|
||||
<li>foo <a href="/test-user/test-repo/issues/12345" class="ref-issue" rel="nofollow">#12345</a> bar</li>
|
||||
</ul>`,
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("ListTodoIssueRef", func(t *testing.T) {
|
||||
test(
|
||||
"* [ ] #12345",
|
||||
`<ul>
|
||||
</ul>`},
|
||||
{"ListTodoIssueRef", "* [ ] #12345", `<ul>
|
||||
<li class="task-list-item"><input type="checkbox" disabled="" data-source-position="2"/><div>issue #12345</div></li>
|
||||
</ul>`,
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("IssueFootnote", func(t *testing.T) {
|
||||
test(
|
||||
"foo[^1][^2]\n\n[^1]: bar\n[^2]: baz",
|
||||
</ul>`},
|
||||
{
|
||||
"IssueFootnote", "foo[^1][^2]\n\n[^1]: bar\n[^2]: baz",
|
||||
`<p>foo<sup id="fnref:user-content-1-12345"><a href="#fn:user-content-1-12345" rel="nofollow">1 </a></sup><sup id="fnref:user-content-2-12345"><a href="#fn:user-content-2-12345" rel="nofollow">2 </a></sup></p>
|
||||
<div>
|
||||
<hr/>
|
||||
@@ -86,6 +67,10 @@ func TestRender_IssueList(t *testing.T) {
|
||||
</li>
|
||||
</ol>
|
||||
</div>`,
|
||||
)
|
||||
})
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(_t *testing.T) {
|
||||
test(tc.input, tc.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -11,94 +11,79 @@ import (
|
||||
)
|
||||
|
||||
func TestProcessNodeAttrID_HTMLHeadingWithoutID(t *testing.T) {
|
||||
// Test that HTML headings without id get an auto-generated id from their text content
|
||||
// when EnableHeadingIDGeneration is true (for repo files and wiki pages)
|
||||
testCases := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
name string
|
||||
generateHeadingID bool
|
||||
input, expected string
|
||||
}{
|
||||
// Test that HTML headings without id get an auto-generated id from their text content
|
||||
// when EnableHeadingIDGeneration is true (for repo files and wiki pages)
|
||||
{
|
||||
name: "h1 without id",
|
||||
input: `<h1>Heading without ID</h1>`,
|
||||
expected: `<h1 id="user-content-heading-without-id">Heading without ID</h1>`,
|
||||
"h1 without id", true,
|
||||
`<h1>Heading without ID</h1>`,
|
||||
`<h1 id="user-content-heading-without-id">Heading without ID</h1>`,
|
||||
},
|
||||
{
|
||||
name: "h2 without id",
|
||||
input: `<h2>Another Heading</h2>`,
|
||||
expected: `<h2 id="user-content-another-heading">Another Heading</h2>`,
|
||||
"h2 without id", true,
|
||||
`<h2>Another Heading</h2>`,
|
||||
`<h2 id="user-content-another-heading">Another Heading</h2>`,
|
||||
},
|
||||
{
|
||||
name: "h3 without id",
|
||||
input: `<h3>Third Level</h3>`,
|
||||
expected: `<h3 id="user-content-third-level">Third Level</h3>`,
|
||||
"h3 without id", true,
|
||||
`<h3>Third Level</h3>`,
|
||||
`<h3 id="user-content-third-level">Third Level</h3>`,
|
||||
},
|
||||
{
|
||||
name: "h1 with existing id should keep it",
|
||||
input: `<h1 id="my-custom-id">Heading with ID</h1>`,
|
||||
expected: `<h1 id="user-content-my-custom-id">Heading with ID</h1>`,
|
||||
"h1 with existing id should keep it", true,
|
||||
`<h1 id="my-custom-id">Heading with ID</h1>`,
|
||||
`<h1 id="user-content-my-custom-id">Heading with ID</h1>`,
|
||||
},
|
||||
{
|
||||
name: "h1 with user-content prefix should not double prefix",
|
||||
input: `<h1 id="user-content-already-prefixed">Already Prefixed</h1>`,
|
||||
expected: `<h1 id="user-content-already-prefixed">Already Prefixed</h1>`,
|
||||
"h1 with user-content prefix should not double prefix", true,
|
||||
`<h1 id="user-content-already-prefixed">Already Prefixed</h1>`,
|
||||
`<h1 id="user-content-already-prefixed">Already Prefixed</h1>`,
|
||||
},
|
||||
{
|
||||
name: "heading with special characters",
|
||||
input: `<h1>What is Wine Staging?</h1>`,
|
||||
expected: `<h1 id="user-content-what-is-wine-staging">What is Wine Staging?</h1>`,
|
||||
"heading with special characters", true,
|
||||
`<h1>What is Wine Staging?</h1>`,
|
||||
`<h1 id="user-content-what-is-wine-staging">What is Wine Staging?</h1>`,
|
||||
},
|
||||
{
|
||||
name: "heading with nested elements",
|
||||
input: `<h2><strong>Bold</strong> and <em>Italic</em></h2>`,
|
||||
expected: `<h2 id="user-content-bold-and-italic"><strong>Bold</strong> and <em>Italic</em></h2>`,
|
||||
"heading with nested elements", true,
|
||||
`<h2><strong>Bold</strong> and <em>Italic</em></h2>`,
|
||||
`<h2 id="user-content-bold-and-italic"><strong>Bold</strong> and <em>Italic</em></h2>`,
|
||||
},
|
||||
// Test that HTML headings in comment-like contexts (issue comments)
|
||||
// do NOT get auto-generated IDs to avoid duplicate IDs on pages with multiple documents.
|
||||
// This is controlled by EnableHeadingIDGeneration which defaults to false.
|
||||
// Default context without EnableHeadingIDGeneration (simulates comment rendering)
|
||||
{
|
||||
"h1 without id in comment context", false,
|
||||
`<h1>Heading without ID</h1>`,
|
||||
`<h1>Heading without ID</h1>`,
|
||||
},
|
||||
{
|
||||
"h2 without id in comment context", false,
|
||||
`<h2>Another Heading</h2>`,
|
||||
`<h2>Another Heading</h2>`,
|
||||
},
|
||||
{
|
||||
"h1 with existing id should still be prefixed", false,
|
||||
`<h1 id="my-custom-id">Heading with ID</h1>`,
|
||||
`<h1 id="user-content-my-custom-id">Heading with ID</h1>`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var result strings.Builder
|
||||
ctx := NewTestRenderContext().WithEnableHeadingIDGeneration(true)
|
||||
ctx := NewTestRenderContext()
|
||||
if tc.generateHeadingID {
|
||||
ctx.WithEnableHeadingIDGeneration(true)
|
||||
}
|
||||
err := PostProcessDefault(ctx, strings.NewReader(tc.input), &result)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.expected, strings.TrimSpace(result.String()))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessNodeAttrID_SkipHeadingIDForComments(t *testing.T) {
|
||||
// Test that HTML headings in comment-like contexts (issue comments)
|
||||
// do NOT get auto-generated IDs to avoid duplicate IDs on pages with multiple documents.
|
||||
// This is controlled by EnableHeadingIDGeneration which defaults to false.
|
||||
testCases := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "h1 without id in comment context",
|
||||
input: `<h1>Heading without ID</h1>`,
|
||||
expected: `<h1>Heading without ID</h1>`,
|
||||
},
|
||||
{
|
||||
name: "h2 without id in comment context",
|
||||
input: `<h2>Another Heading</h2>`,
|
||||
expected: `<h2>Another Heading</h2>`,
|
||||
},
|
||||
{
|
||||
name: "h1 with existing id should still be prefixed",
|
||||
input: `<h1 id="my-custom-id">Heading with ID</h1>`,
|
||||
expected: `<h1 id="user-content-my-custom-id">Heading with ID</h1>`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var result strings.Builder
|
||||
// Default context without EnableHeadingIDGeneration (simulates comment rendering)
|
||||
err := PostProcessDefault(NewTestRenderContext(), strings.NewReader(tc.input), &result)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.expected, strings.TrimSpace(result.String()))
|
||||
})
|
||||
}
|
||||
}
|
||||
+120
-266
@@ -145,90 +145,42 @@ func TestRender_links(t *testing.T) {
|
||||
setting.Markdown.CustomURLSchemes = []string{"ftp", "magnet"}
|
||||
common.InitLinkURLSchemes(setting.Markdown.CustomURLSchemes)
|
||||
|
||||
// Text that should be turned into URL
|
||||
test(
|
||||
"https://www.example.com",
|
||||
`<p><a href="https://www.example.com" rel="nofollow">https://www.example.com</a></p>`)
|
||||
test(
|
||||
"http://www.example.com",
|
||||
`<p><a href="http://www.example.com" rel="nofollow">http://www.example.com</a></p>`)
|
||||
test(
|
||||
"https://example.com",
|
||||
`<p><a href="https://example.com" rel="nofollow">https://example.com</a></p>`)
|
||||
test(
|
||||
"http://example.com",
|
||||
`<p><a href="http://example.com" rel="nofollow">http://example.com</a></p>`)
|
||||
test(
|
||||
"http://foo.com/blah_blah",
|
||||
`<p><a href="http://foo.com/blah_blah" rel="nofollow">http://foo.com/blah_blah</a></p>`)
|
||||
test(
|
||||
"http://foo.com/blah_blah/",
|
||||
`<p><a href="http://foo.com/blah_blah/" rel="nofollow">http://foo.com/blah_blah/</a></p>`)
|
||||
test(
|
||||
"http://www.example.com/wpstyle/?p=364",
|
||||
`<p><a href="http://www.example.com/wpstyle/?p=364" rel="nofollow">http://www.example.com/wpstyle/?p=364</a></p>`)
|
||||
test(
|
||||
"https://www.example.com/foo/?bar=baz&inga=42&quux",
|
||||
`<p><a href="https://www.example.com/foo/?bar=baz&inga=42&quux" rel="nofollow">https://www.example.com/foo/?bar=baz&inga=42&quux</a></p>`)
|
||||
test(
|
||||
"http://142.42.1.1/",
|
||||
`<p><a href="http://142.42.1.1/" rel="nofollow">http://142.42.1.1/</a></p>`)
|
||||
test(
|
||||
"https://github.com/go-gitea/gitea/?p=aaa/bbb.html#ccc-ddd",
|
||||
`<p><a href="https://github.com/go-gitea/gitea/?p=aaa/bbb.html#ccc-ddd" rel="nofollow">https://github.com/go-gitea/gitea/?p=aaa/bbb.html#ccc-ddd</a></p>`)
|
||||
test(
|
||||
"https://en.wikipedia.org/wiki/URL_(disambiguation)",
|
||||
`<p><a href="https://en.wikipedia.org/wiki/URL_(disambiguation)" rel="nofollow">https://en.wikipedia.org/wiki/URL_(disambiguation)</a></p>`)
|
||||
test(
|
||||
"https://foo_bar.example.com/",
|
||||
`<p><a href="https://foo_bar.example.com/" rel="nofollow">https://foo_bar.example.com/</a></p>`)
|
||||
test(
|
||||
"https://stackoverflow.com/questions/2896191/what-is-go-used-fore",
|
||||
`<p><a href="https://stackoverflow.com/questions/2896191/what-is-go-used-fore" rel="nofollow">https://stackoverflow.com/questions/2896191/what-is-go-used-fore</a></p>`)
|
||||
test(
|
||||
"https://username:password@gitea.com",
|
||||
`<p><a href="https://username:password@gitea.com" rel="nofollow">https://username:password@gitea.com</a></p>`)
|
||||
test(
|
||||
"ftp://gitea.com/file.txt",
|
||||
`<p><a href="ftp://gitea.com/file.txt" rel="nofollow">ftp://gitea.com/file.txt</a></p>`)
|
||||
test(
|
||||
"magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download",
|
||||
`<p><a href="magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download" rel="nofollow">magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download</a></p>`)
|
||||
test(
|
||||
`[link](https://example.com)`,
|
||||
`<p><a href="https://example.com" rel="nofollow">link</a></p>`)
|
||||
test(
|
||||
`[link](mailto:test@example.com)`,
|
||||
`<p><a href="mailto:test@example.com" rel="nofollow">link</a></p>`)
|
||||
test(
|
||||
`[link](javascript:xss)`,
|
||||
`<p>link</p>`)
|
||||
for _, testCase := range []struct {
|
||||
input, expected string
|
||||
}{
|
||||
// Text that should be turned into URL
|
||||
{"https://www.example.com", `<p><a href="https://www.example.com" rel="nofollow">https://www.example.com</a></p>`},
|
||||
{"http://www.example.com", `<p><a href="http://www.example.com" rel="nofollow">http://www.example.com</a></p>`},
|
||||
{"https://example.com", `<p><a href="https://example.com" rel="nofollow">https://example.com</a></p>`},
|
||||
{"http://example.com", `<p><a href="http://example.com" rel="nofollow">http://example.com</a></p>`},
|
||||
{"http://foo.com/blah_blah", `<p><a href="http://foo.com/blah_blah" rel="nofollow">http://foo.com/blah_blah</a></p>`},
|
||||
{"http://foo.com/blah_blah/", `<p><a href="http://foo.com/blah_blah/" rel="nofollow">http://foo.com/blah_blah/</a></p>`},
|
||||
{"http://www.example.com/wpstyle/?p=364", `<p><a href="http://www.example.com/wpstyle/?p=364" rel="nofollow">http://www.example.com/wpstyle/?p=364</a></p>`},
|
||||
{"https://www.example.com/foo/?bar=baz&inga=42&quux", `<p><a href="https://www.example.com/foo/?bar=baz&inga=42&quux" rel="nofollow">https://www.example.com/foo/?bar=baz&inga=42&quux</a></p>`},
|
||||
{"http://142.42.1.1/", `<p><a href="http://142.42.1.1/" rel="nofollow">http://142.42.1.1/</a></p>`},
|
||||
{"https://github.com/go-gitea/gitea/?p=aaa/bbb.html#ccc-ddd", `<p><a href="https://github.com/go-gitea/gitea/?p=aaa/bbb.html#ccc-ddd" rel="nofollow">https://github.com/go-gitea/gitea/?p=aaa/bbb.html#ccc-ddd</a></p>`},
|
||||
{"https://en.wikipedia.org/wiki/URL_(disambiguation)", `<p><a href="https://en.wikipedia.org/wiki/URL_(disambiguation)" rel="nofollow">https://en.wikipedia.org/wiki/URL_(disambiguation)</a></p>`},
|
||||
{"https://foo_bar.example.com/", `<p><a href="https://foo_bar.example.com/" rel="nofollow">https://foo_bar.example.com/</a></p>`},
|
||||
{"https://stackoverflow.com/questions/2896191/what-is-go-used-fore", `<p><a href="https://stackoverflow.com/questions/2896191/what-is-go-used-fore" rel="nofollow">https://stackoverflow.com/questions/2896191/what-is-go-used-fore</a></p>`},
|
||||
{"https://username:password@gitea.com", `<p><a href="https://username:password@gitea.com" rel="nofollow">https://username:password@gitea.com</a></p>`},
|
||||
{"ftp://gitea.com/file.txt", `<p><a href="ftp://gitea.com/file.txt" rel="nofollow">ftp://gitea.com/file.txt</a></p>`},
|
||||
{"magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download", `<p><a href="magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download" rel="nofollow">magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download</a></p>`},
|
||||
{`[link](https://example.com)`, `<p><a href="https://example.com" rel="nofollow">link</a></p>`},
|
||||
{`[link](mailto:test@example.com)`, `<p><a href="mailto:test@example.com" rel="nofollow">link</a></p>`},
|
||||
{`[link](javascript:xss)`, `<p>link</p>`},
|
||||
|
||||
// Test that should *not* be turned into URL
|
||||
test(
|
||||
"www.example.com",
|
||||
`<p>www.example.com</p>`)
|
||||
test(
|
||||
"example.com",
|
||||
`<p>example.com</p>`)
|
||||
test(
|
||||
"test.example.com",
|
||||
`<p>test.example.com</p>`)
|
||||
test(
|
||||
"http://",
|
||||
`<p>http://</p>`)
|
||||
test(
|
||||
"https://",
|
||||
`<p>https://</p>`)
|
||||
test(
|
||||
"://",
|
||||
`<p>://</p>`)
|
||||
test(
|
||||
"www",
|
||||
`<p>www</p>`)
|
||||
test(
|
||||
"ftps://gitea.com",
|
||||
`<p>ftps://gitea.com</p>`)
|
||||
// Test that should *not* be turned into URL
|
||||
{"www.example.com", `<p>www.example.com</p>`},
|
||||
{"example.com", `<p>example.com</p>`},
|
||||
{"test.example.com", `<p>test.example.com</p>`},
|
||||
{"http://", `<p>http://</p>`},
|
||||
{"https://", `<p>https://</p>`},
|
||||
{"://", `<p>://</p>`},
|
||||
{"www", `<p>www</p>`},
|
||||
{"ftps://gitea.com", `<p>ftps://gitea.com</p>`},
|
||||
} {
|
||||
test(testCase.input, testCase.expected)
|
||||
}
|
||||
|
||||
t.Run("LinkEllipsis", func(t *testing.T) {
|
||||
input := util.EllipsisDisplayString("http://10.1.2.3", 12)
|
||||
@@ -244,73 +196,41 @@ func TestRender_links(t *testing.T) {
|
||||
func TestRender_email(t *testing.T) {
|
||||
setting.AppURL = markup.TestAppURL
|
||||
defer testModule.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)()
|
||||
test := func(input, expected string) {
|
||||
res, err := testRenderString(markup.NewTestRenderContext().WithRelativePath("a.md"), input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(res), "input: %s", input)
|
||||
}
|
||||
for _, testCase := range []struct {
|
||||
input, expected string
|
||||
}{
|
||||
// Text that should be turned into email link
|
||||
{"info@gitea.com", `<p><a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a></p>`},
|
||||
{"(info@gitea.com)", `<p>(<a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a>)</p>`},
|
||||
{"[info@gitea.com]", `<p>[<a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a>]</p>`},
|
||||
{"info@gitea.com.", `<p><a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a>.</p>`},
|
||||
{"firstname+lastname@gitea.com", `<p><a href="mailto:firstname+lastname@gitea.com" rel="nofollow">firstname+lastname@gitea.com</a></p>`},
|
||||
{"send email to info@gitea.co.uk.", `<p>send email to <a href="mailto:info@gitea.co.uk" rel="nofollow">info@gitea.co.uk</a>.</p>`},
|
||||
|
||||
// Text that should be turned into email link
|
||||
test(
|
||||
"info@gitea.com",
|
||||
`<p><a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a></p>`)
|
||||
test(
|
||||
"(info@gitea.com)",
|
||||
`<p>(<a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a>)</p>`)
|
||||
test(
|
||||
"[info@gitea.com]",
|
||||
`<p>[<a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a>]</p>`)
|
||||
test(
|
||||
"info@gitea.com.",
|
||||
`<p><a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a>.</p>`)
|
||||
test(
|
||||
"firstname+lastname@gitea.com",
|
||||
`<p><a href="mailto:firstname+lastname@gitea.com" rel="nofollow">firstname+lastname@gitea.com</a></p>`)
|
||||
test(
|
||||
"send email to info@gitea.co.uk.",
|
||||
`<p>send email to <a href="mailto:info@gitea.co.uk" rel="nofollow">info@gitea.co.uk</a>.</p>`)
|
||||
|
||||
test(
|
||||
`j.doe@example.com,
|
||||
{`j.doe@example.com,
|
||||
j.doe@example.com.
|
||||
j.doe@example.com;
|
||||
j.doe@example.com?
|
||||
j.doe@example.com!`,
|
||||
`<p><a href="mailto:j.doe@example.com" rel="nofollow">j.doe@example.com</a>,
|
||||
j.doe@example.com!`, `<p><a href="mailto:j.doe@example.com" rel="nofollow">j.doe@example.com</a>,
|
||||
<a href="mailto:j.doe@example.com" rel="nofollow">j.doe@example.com</a>.
|
||||
<a href="mailto:j.doe@example.com" rel="nofollow">j.doe@example.com</a>;
|
||||
<a href="mailto:j.doe@example.com" rel="nofollow">j.doe@example.com</a>?
|
||||
<a href="mailto:j.doe@example.com" rel="nofollow">j.doe@example.com</a>!</p>`)
|
||||
<a href="mailto:j.doe@example.com" rel="nofollow">j.doe@example.com</a>!</p>`},
|
||||
|
||||
// match GitHub behavior
|
||||
test("email@domain@domain.com", `<p>email@<a href="mailto:domain@domain.com" rel="nofollow">domain@domain.com</a></p>`)
|
||||
// match GitHub behavior
|
||||
{"email@domain@domain.com", `<p>email@<a href="mailto:domain@domain.com" rel="nofollow">domain@domain.com</a></p>`},
|
||||
|
||||
// match GitHub behavior
|
||||
test(`"info@gitea.com"`, `<p>"<a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a>"</p>`)
|
||||
// match GitHub behavior
|
||||
{`"info@gitea.com"`, `<p>"<a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a>"</p>`},
|
||||
|
||||
// Test that should *not* be turned into email links
|
||||
test(
|
||||
"/home/gitea/mailstore/info@gitea/com",
|
||||
`<p>/home/gitea/mailstore/info@gitea/com</p>`)
|
||||
test(
|
||||
"git@try.gitea.io:go-gitea/gitea.git",
|
||||
`<p>git@try.gitea.io:go-gitea/gitea.git</p>`)
|
||||
test(
|
||||
"https://foo:bar@gitea.io",
|
||||
`<p><a href="https://foo:bar@gitea.io" rel="nofollow">https://foo:bar@gitea.io</a></p>`)
|
||||
test(
|
||||
"gitea@3",
|
||||
`<p>gitea@3</p>`)
|
||||
test(
|
||||
"gitea@gmail.c",
|
||||
`<p>gitea@gmail.c</p>`)
|
||||
test(
|
||||
"email@domain..com",
|
||||
`<p>email@domain..com</p>`)
|
||||
// Test that should *not* be turned into email links
|
||||
{"/home/gitea/mailstore/info@gitea/com", `<p>/home/gitea/mailstore/info@gitea/com</p>`},
|
||||
{"git@try.gitea.io:go-gitea/gitea.git", `<p>git@try.gitea.io:go-gitea/gitea.git</p>`},
|
||||
{"https://foo:bar@gitea.io", `<p><a href="https://foo:bar@gitea.io" rel="nofollow">https://foo:bar@gitea.io</a></p>`},
|
||||
{"gitea@3", `<p>gitea@3</p>`},
|
||||
{"gitea@gmail.c", `<p>gitea@gmail.c</p>`},
|
||||
{"email@domain..com", `<p>email@domain..com</p>`},
|
||||
|
||||
cases := []struct {
|
||||
input, expected string
|
||||
}{
|
||||
// match GitHub behavior
|
||||
{"?a@d.zz", `<p>?<a href="mailto:a@d.zz" rel="nofollow">a@d.zz</a></p>`},
|
||||
{"*a@d.zz", `<p>*<a href="mailto:a@d.zz" rel="nofollow">a@d.zz</a></p>`},
|
||||
@@ -320,9 +240,10 @@ func TestRender_email(t *testing.T) {
|
||||
// maybe we should reduce the candidate characters for the "name" part in the future
|
||||
{"a*a@d.zz", `<p><a href="mailto:a*a@d.zz" rel="nofollow">a*a@d.zz</a></p>`},
|
||||
{"a~a@d.zz", `<p><a href="mailto:a~a@d.zz" rel="nofollow">a~a@d.zz</a></p>`},
|
||||
}
|
||||
for _, c := range cases {
|
||||
test(c.input, c.expected)
|
||||
} {
|
||||
res, err := testRenderString(markup.NewTestRenderContext().WithRelativePath("a.md"), testCase.input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(testCase.expected), strings.TrimSpace(res), "input: %s", testCase.input)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,12 +315,6 @@ func TestRender_ShortLinks(t *testing.T) {
|
||||
setting.AppURL = markup.TestAppURL
|
||||
tree := markup.TestRepoURL + "src/master"
|
||||
|
||||
test := func(input, expected string) {
|
||||
buffer, err := markdown.RenderString(markup.NewTestRenderContext(tree), input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
|
||||
}
|
||||
|
||||
url := tree + "/Link"
|
||||
otherURL := tree + "/Other-Link"
|
||||
encodedURL := tree + "/Link%3F"
|
||||
@@ -410,88 +325,36 @@ func TestRender_ShortLinks(t *testing.T) {
|
||||
renderableFileURL := tree + "/markdown_file.md"
|
||||
unrenderableFileURL := tree + "/file.zip"
|
||||
favicon := "http://google.com/favicon.ico"
|
||||
test(
|
||||
"[[Link]]",
|
||||
`<p><a href="`+url+`" rel="nofollow">Link</a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Link.-]]",
|
||||
`<p><a href="http://localhost:3000/test-owner/test-repo/src/master/Link.-" rel="nofollow">Link.-</a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Link.jpg]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Link.jpg" alt="Link.jpg"/></a></p>`,
|
||||
)
|
||||
test(
|
||||
"[["+favicon+"]]",
|
||||
`<p><a href="`+favicon+`" rel="nofollow"><img src="`+favicon+`" title="favicon.ico" alt="`+favicon+`"/></a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Name|Link]]",
|
||||
`<p><a href="`+url+`" rel="nofollow">Name</a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Name|Link.jpg]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Name" alt="Name"/></a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Name|Link.jpg|alt=AltName]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="AltName" alt="AltName"/></a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Name|Link.jpg|title=Title]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Title" alt="Title"/></a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Name|Link.jpg|alt=AltName|title=Title]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Title" alt="AltName"/></a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Name|Link.jpg|alt=\"AltName\"|title='Title']]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Title" alt="AltName"/></a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Name|Link Other.jpg|alt=\"AltName\"|title='Title']]",
|
||||
`<p><a href="`+otherImgurl+`" rel="nofollow"><img src="`+otherImgurl+`" title="Title" alt="AltName"/></a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Link]] [[Other Link]]",
|
||||
`<p><a href="`+url+`" rel="nofollow">Link</a> <a href="`+otherURL+`" rel="nofollow">Other Link</a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Link?]]",
|
||||
`<p><a href="`+encodedURL+`" rel="nofollow">Link?</a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Link]] [[Other Link]] [[Link?]]",
|
||||
`<p><a href="`+url+`" rel="nofollow">Link</a> <a href="`+otherURL+`" rel="nofollow">Other Link</a> <a href="`+encodedURL+`" rel="nofollow">Link?</a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[markdown_file.md]]",
|
||||
`<p><a href="`+renderableFileURL+`" rel="nofollow">markdown_file.md</a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[file.zip]]",
|
||||
`<p><a href="`+unrenderableFileURL+`" rel="nofollow">file.zip</a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Link #.jpg]]",
|
||||
`<p><a href="`+encodedImgurl+`" rel="nofollow"><img src="`+encodedImgurl+`" title="Link #.jpg" alt="Link #.jpg"/></a></p>`,
|
||||
)
|
||||
test(
|
||||
"[[Name|Link #.jpg|alt=\"AltName\"|title='Title']]",
|
||||
`<p><a href="`+encodedImgurl+`" rel="nofollow"><img src="`+encodedImgurl+`" title="Title" alt="AltName"/></a></p>`,
|
||||
)
|
||||
// FIXME: it's unable to resolve: [[link?k=v]]
|
||||
// FIXME: it is a wrong test case, it is not an image, but a link with anchor "#.jpg"
|
||||
test(
|
||||
"[[some/path/Link #.jpg]]",
|
||||
`<p><a href="`+notencodedImgurl+`" rel="nofollow"><img src="`+notencodedImgurl+`" title="Link #.jpg" alt="some/path/Link #.jpg"/></a></p>`,
|
||||
)
|
||||
test(
|
||||
"<p><a href=\"https://example.org\">[[foobar]]</a></p>",
|
||||
`<p><a href="https://example.org" rel="nofollow">[[foobar]]</a></p>`,
|
||||
)
|
||||
for _, testCase := range []struct {
|
||||
input, expected string
|
||||
}{
|
||||
{"[[Link]]", `<p><a href="` + url + `" rel="nofollow">Link</a></p>`},
|
||||
{"[[Link.-]]", `<p><a href="http://localhost:3000/test-owner/test-repo/src/master/Link.-" rel="nofollow">Link.-</a></p>`},
|
||||
{"[[Link.jpg]]", `<p><a href="` + imgurl + `" rel="nofollow"><img src="` + imgurl + `" title="Link.jpg" alt="Link.jpg"/></a></p>`},
|
||||
{"[[" + favicon + "]]", `<p><a href="` + favicon + `" rel="nofollow"><img src="` + favicon + `" title="favicon.ico" alt="` + favicon + `"/></a></p>`},
|
||||
{"[[Name|Link]]", `<p><a href="` + url + `" rel="nofollow">Name</a></p>`},
|
||||
{"[[Name|Link.jpg]]", `<p><a href="` + imgurl + `" rel="nofollow"><img src="` + imgurl + `" title="Name" alt="Name"/></a></p>`},
|
||||
{"[[Name|Link.jpg|alt=AltName]]", `<p><a href="` + imgurl + `" rel="nofollow"><img src="` + imgurl + `" title="AltName" alt="AltName"/></a></p>`},
|
||||
{"[[Name|Link.jpg|title=Title]]", `<p><a href="` + imgurl + `" rel="nofollow"><img src="` + imgurl + `" title="Title" alt="Title"/></a></p>`},
|
||||
{"[[Name|Link.jpg|alt=AltName|title=Title]]", `<p><a href="` + imgurl + `" rel="nofollow"><img src="` + imgurl + `" title="Title" alt="AltName"/></a></p>`},
|
||||
{"[[Name|Link.jpg|alt=\"AltName\"|title='Title']]", `<p><a href="` + imgurl + `" rel="nofollow"><img src="` + imgurl + `" title="Title" alt="AltName"/></a></p>`},
|
||||
{"[[Name|Link Other.jpg|alt=\"AltName\"|title='Title']]", `<p><a href="` + otherImgurl + `" rel="nofollow"><img src="` + otherImgurl + `" title="Title" alt="AltName"/></a></p>`},
|
||||
{"[[Link]] [[Other Link]]", `<p><a href="` + url + `" rel="nofollow">Link</a> <a href="` + otherURL + `" rel="nofollow">Other Link</a></p>`},
|
||||
{"[[Link?]]", `<p><a href="` + encodedURL + `" rel="nofollow">Link?</a></p>`},
|
||||
{"[[Link]] [[Other Link]] [[Link?]]", `<p><a href="` + url + `" rel="nofollow">Link</a> <a href="` + otherURL + `" rel="nofollow">Other Link</a> <a href="` + encodedURL + `" rel="nofollow">Link?</a></p>`},
|
||||
{"[[markdown_file.md]]", `<p><a href="` + renderableFileURL + `" rel="nofollow">markdown_file.md</a></p>`},
|
||||
{"[[file.zip]]", `<p><a href="` + unrenderableFileURL + `" rel="nofollow">file.zip</a></p>`},
|
||||
{"[[Link #.jpg]]", `<p><a href="` + encodedImgurl + `" rel="nofollow"><img src="` + encodedImgurl + `" title="Link #.jpg" alt="Link #.jpg"/></a></p>`},
|
||||
{"[[Name|Link #.jpg|alt=\"AltName\"|title='Title']]", `<p><a href="` + encodedImgurl + `" rel="nofollow"><img src="` + encodedImgurl + `" title="Title" alt="AltName"/></a></p>`},
|
||||
// FIXME: it's unable to resolve: [[link?k=v]]
|
||||
// FIXME: it is a wrong test case, it is not an image, but a link with anchor "#.jpg"
|
||||
{"[[some/path/Link #.jpg]]", `<p><a href="` + notencodedImgurl + `" rel="nofollow"><img src="` + notencodedImgurl + `" title="Link #.jpg" alt="some/path/Link #.jpg"/></a></p>`},
|
||||
{"<p><a href=\"https://example.org\">[[foobar]]</a></p>", `<p><a href="https://example.org" rel="nofollow">[[foobar]]</a></p>`},
|
||||
} {
|
||||
buffer, err := markdown.RenderString(markup.NewTestRenderContext(tree), testCase.input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(testCase.expected), strings.TrimSpace(string(buffer)))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_ParseClusterFuzz(t *testing.T) {
|
||||
@@ -519,45 +382,36 @@ func TestPostProcess(t *testing.T) {
|
||||
setting.StaticURLPrefix = strings.TrimSuffix(markup.TestAppURL, "/") // can't run standalone
|
||||
defer testModule.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)()
|
||||
|
||||
test := func(input, expected string) {
|
||||
for _, testCase := range []struct {
|
||||
input, expected string
|
||||
}{
|
||||
// Issue index shouldn't be post-processing in a document.
|
||||
{"#1", "#1"},
|
||||
|
||||
// But cross-referenced issue index should work.
|
||||
{"go-gitea/gitea#12345", `<a href="/go-gitea/gitea/issues/12345" class="ref-issue">go-gitea/gitea#12345</a>`},
|
||||
|
||||
// Test that other post-processing still works.
|
||||
{":gitea:", `<span class="emoji"><img alt=":gitea:" src="` + setting.StaticURLPrefix + `/assets/img/emoji/gitea.png"/></span>`},
|
||||
{"Some text with 😄 in the middle", `Some text with <span class="emoji" data-alias="smile">😄</span> in the middle`},
|
||||
{"http://localhost:3000/person/repo/issues/4#issuecomment-1234", `<a href="http://localhost:3000/person/repo/issues/4#issuecomment-1234" class="ref-issue">person/repo#4 (comment)</a>`},
|
||||
{"<math><mtext>:gitea: go-gitea/gitea#12345</mtext></math>", "<math><mtext>:gitea: go-gitea/gitea#12345</mtext></math>"},
|
||||
|
||||
// special tags, GitHub's behavior, and for unclosed tags, output as text content as much as possible
|
||||
{"<script>a", `<script>a`},
|
||||
{"<script>a</script>", `<script>a</script>`},
|
||||
{"<STYLE>a", `<STYLE>a`},
|
||||
{"<style>a</STYLE>", `<style>a</STYLE>`},
|
||||
|
||||
// other special tags, our special behavior
|
||||
{"<?php\nfoo", "<?php\nfoo"},
|
||||
{"<%asp\nfoo", "<%asp\nfoo"},
|
||||
} {
|
||||
var res strings.Builder
|
||||
err := markup.PostProcessDefault(markup.NewTestRenderContext(markup.TestAppURL, map[string]string{"user": "go-gitea", "repo": "gitea"}), strings.NewReader(input), &res)
|
||||
err := markup.PostProcessDefault(markup.NewTestRenderContext(markup.TestAppURL, map[string]string{"user": "go-gitea", "repo": "gitea"}), strings.NewReader(testCase.input), &res)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(res.String()))
|
||||
assert.Equal(t, strings.TrimSpace(testCase.expected), strings.TrimSpace(res.String()))
|
||||
}
|
||||
|
||||
// Issue index shouldn't be post-processing in a document.
|
||||
test(
|
||||
"#1",
|
||||
"#1")
|
||||
|
||||
// But cross-referenced issue index should work.
|
||||
test(
|
||||
"go-gitea/gitea#12345",
|
||||
`<a href="/go-gitea/gitea/issues/12345" class="ref-issue">go-gitea/gitea#12345</a>`)
|
||||
|
||||
// Test that other post-processing still works.
|
||||
test(
|
||||
":gitea:",
|
||||
`<span class="emoji"><img alt=":gitea:" src="`+setting.StaticURLPrefix+`/assets/img/emoji/gitea.png"/></span>`)
|
||||
test(
|
||||
"Some text with 😄 in the middle",
|
||||
`Some text with <span class="emoji" data-alias="smile">😄</span> in the middle`)
|
||||
test("http://localhost:3000/person/repo/issues/4#issuecomment-1234",
|
||||
`<a href="http://localhost:3000/person/repo/issues/4#issuecomment-1234" class="ref-issue">person/repo#4 (comment)</a>`)
|
||||
test(
|
||||
"<math><mtext>:gitea: go-gitea/gitea#12345</mtext></math>",
|
||||
"<math><mtext>:gitea: go-gitea/gitea#12345</mtext></math>")
|
||||
|
||||
// special tags, GitHub's behavior, and for unclosed tags, output as text content as much as possible
|
||||
test("<script>a", `<script>a`)
|
||||
test("<script>a</script>", `<script>a</script>`)
|
||||
test("<STYLE>a", `<STYLE>a`)
|
||||
test("<style>a</STYLE>", `<style>a</STYLE>`)
|
||||
|
||||
// other special tags, our special behavior
|
||||
test("<?php\nfoo", "<?php\nfoo")
|
||||
test("<%asp\nfoo", "<%asp\nfoo")
|
||||
}
|
||||
|
||||
func TestIssue16020(t *testing.T) {
|
||||
|
||||
@@ -61,30 +61,20 @@ func TestRenderInternalAttrs(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRenderInternalExtraHead(t *testing.T) {
|
||||
t.Run("HeadExists", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
var r RenderInternal
|
||||
in := r.init("sec", out, `<MY-TAG>`)
|
||||
_, _ = io.WriteString(in, `<head>any</head>`)
|
||||
_ = in.Close()
|
||||
assert.Equal(t, `<head><MY-TAG>any</head>`, out.String())
|
||||
})
|
||||
|
||||
t.Run("HeadNotExists", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
var r RenderInternal
|
||||
in := r.init("sec", out, `<MY-TAG>`)
|
||||
_, _ = io.WriteString(in, `<div></div>`)
|
||||
_ = in.Close()
|
||||
assert.Equal(t, `<MY-TAG><div></div>`, out.String())
|
||||
})
|
||||
|
||||
t.Run("NotHTML", func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
var r RenderInternal
|
||||
in := r.init("sec", out, `<MY-TAG>`)
|
||||
_, _ = io.WriteString(in, `<any>`)
|
||||
_ = in.Close()
|
||||
assert.Equal(t, `<any>`, out.String())
|
||||
})
|
||||
for _, test := range []struct {
|
||||
name, input, expected string
|
||||
}{
|
||||
{"HeadExists", `<head>any</head>`, `<head><MY-TAG>any</head>`},
|
||||
{"HeadNotExists", `<div></div>`, `<MY-TAG><div></div>`},
|
||||
{"NotHTML", `<any>`, `<any>`},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
var r RenderInternal
|
||||
in := r.init("sec", out, `<MY-TAG>`)
|
||||
_, _ = io.WriteString(in, test.input)
|
||||
_ = in.Close()
|
||||
assert.Equal(t, test.expected, out.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,12 @@ import (
|
||||
|
||||
func TestRender(t *testing.T) {
|
||||
r := renderer{}
|
||||
render := func(t *testing.T, ctx *markup.RenderContext, input string) string {
|
||||
var output strings.Builder
|
||||
err := r.Render(ctx, strings.NewReader(input), &output)
|
||||
assert.NoError(t, err)
|
||||
return output.String()
|
||||
}
|
||||
|
||||
t.Run("Basic notebook", func(t *testing.T) {
|
||||
input := `{
|
||||
@@ -37,12 +43,7 @@ func TestRender(t *testing.T) {
|
||||
"nbformat": 4
|
||||
}`
|
||||
|
||||
var output strings.Builder
|
||||
ctx := &markup.RenderContext{}
|
||||
err := r.Render(ctx, strings.NewReader(input), &output)
|
||||
|
||||
assert.NoError(t, err)
|
||||
result := output.String()
|
||||
result := render(t, &markup.RenderContext{}, input)
|
||||
assert.Contains(t, result, `<div class="jupyter-notebook">`)
|
||||
assert.Contains(t, result, `<div class="notebook-cell cell-type-code">`)
|
||||
assert.Contains(t, result, `In [1]:`)
|
||||
@@ -68,12 +69,7 @@ func TestRender(t *testing.T) {
|
||||
"nbformat": 4
|
||||
}`
|
||||
|
||||
var output strings.Builder
|
||||
ctx := markup.NewRenderContext(t.Context())
|
||||
err := r.Render(ctx, strings.NewReader(input), &output)
|
||||
|
||||
assert.NoError(t, err)
|
||||
result := output.String()
|
||||
result := render(t, markup.NewRenderContext(t.Context()), input)
|
||||
|
||||
// Assert normal markup still renders correctly
|
||||
assert.Contains(t, result, `<div class="notebook-cell cell-type-markdown">`)
|
||||
@@ -94,12 +90,7 @@ func TestRender(t *testing.T) {
|
||||
}
|
||||
input := fmt.Sprintf(`{"cells": [%s], "metadata": {}, "nbformat": 4}`, strings.Join(cellBlocks, ","))
|
||||
|
||||
var output strings.Builder
|
||||
ctx := markup.NewRenderContext(t.Context())
|
||||
err := r.Render(ctx, strings.NewReader(input), &output)
|
||||
|
||||
assert.NoError(t, err)
|
||||
result := output.String()
|
||||
result := render(t, markup.NewRenderContext(t.Context()), input)
|
||||
|
||||
// Verify it halts rendering gracefully and shows the truncation warning
|
||||
assert.Contains(t, result, "Output truncated.")
|
||||
@@ -130,12 +121,7 @@ func TestRender(t *testing.T) {
|
||||
"nbformat": 4
|
||||
}`
|
||||
|
||||
var output strings.Builder
|
||||
ctx := markup.NewRenderContext(t.Context())
|
||||
err := r.Render(ctx, strings.NewReader(input), &output)
|
||||
|
||||
assert.NoError(t, err)
|
||||
result := output.String()
|
||||
result := render(t, markup.NewRenderContext(t.Context()), input)
|
||||
assert.Contains(t, result, `<img src="data:image/png;base64,`)
|
||||
assert.Contains(t, result, `iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==`)
|
||||
})
|
||||
@@ -161,12 +147,7 @@ func TestRender(t *testing.T) {
|
||||
"nbformat": 4
|
||||
}`
|
||||
|
||||
var output strings.Builder
|
||||
ctx := markup.NewRenderContext(t.Context())
|
||||
err := r.Render(ctx, strings.NewReader(input), &output)
|
||||
|
||||
assert.NoError(t, err)
|
||||
result := output.String()
|
||||
result := render(t, markup.NewRenderContext(t.Context()), input)
|
||||
assert.NotContains(t, result, `<style scoped>`)
|
||||
assert.Contains(t, result, `<table><tr><td>1</td></tr></table>`)
|
||||
assert.Contains(t, result, `<td>1</td>`)
|
||||
@@ -193,12 +174,7 @@ func TestRender(t *testing.T) {
|
||||
"nbformat": 4
|
||||
}`
|
||||
|
||||
var output strings.Builder
|
||||
ctx := markup.NewRenderContext(t.Context())
|
||||
err := r.Render(ctx, strings.NewReader(input), &output)
|
||||
|
||||
assert.NoError(t, err)
|
||||
result := output.String()
|
||||
result := render(t, markup.NewRenderContext(t.Context()), input)
|
||||
assert.Contains(t, result, `ValueError: test error`)
|
||||
assert.Contains(t, result, `cell-output-error`)
|
||||
})
|
||||
@@ -210,12 +186,8 @@ func TestRender(t *testing.T) {
|
||||
"nbformat": 3
|
||||
}`
|
||||
|
||||
var output strings.Builder
|
||||
ctx := markup.NewRenderContext(t.Context())
|
||||
err := r.Render(ctx, strings.NewReader(input), &output)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Regexp(t, `<div class="file-not-rendered-prompt">This notebook uses an older format.*</div>`, output.String())
|
||||
result := render(t, markup.NewRenderContext(t.Context()), input)
|
||||
assert.Regexp(t, `<div class="file-not-rendered-prompt">This notebook uses an older format.*</div>`, result)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -58,17 +58,6 @@ func TestRender_Images(t *testing.T) {
|
||||
result := baseLink + "/.images/src/02/train.jpg" // resolved link should not go out of the base link
|
||||
// hint: With Markdown v2.5.2, there is a new syntax: [link](URL){:target="_blank"} , but we do not support it now
|
||||
|
||||
render(
|
||||
"",
|
||||
`<p><a href="`+result+`" target="_blank" rel="nofollow noopener"><img src="`+result+`" alt="`+title+`"/></a></p>`)
|
||||
|
||||
render(
|
||||
"[["+title+"|"+url+"]]",
|
||||
`<p><a href="`+result+`" rel="nofollow"><img src="`+result+`" title="`+title+`" alt="`+title+`"/></a></p>`)
|
||||
render(
|
||||
"[]("+href+")",
|
||||
`<p><a href="`+href+`" rel="nofollow"><img src="`+result+`" alt="`+title+`"/></a></p>`)
|
||||
|
||||
render(
|
||||
"",
|
||||
`<p><a href="`+result+`" target="_blank" rel="nofollow noopener"><img src="`+result+`" alt="`+title+`"/></a></p>`)
|
||||
|
||||
@@ -26,67 +26,46 @@ func (it *IssueTemplate) Valid() bool {
|
||||
}
|
||||
|
||||
func TestExtractMetadata(t *testing.T) {
|
||||
t.Run("ValidFrontAndBody", func(t *testing.T) {
|
||||
var meta IssueTemplate
|
||||
body, err := ExtractMetadata(fmt.Sprintf("%s\n%s\n%s\n%s", sepTest, frontTest, sepTest, bodyTest), &meta)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, bodyTest, body)
|
||||
assert.Equal(t, metaTest, meta)
|
||||
assert.True(t, meta.Valid())
|
||||
})
|
||||
for _, mode := range []string{"String", "Bytes"} {
|
||||
t.Run(mode, func(t *testing.T) {
|
||||
extract := func(format string, args ...any) (string, IssueTemplate, error) {
|
||||
var meta IssueTemplate
|
||||
if mode == "String" {
|
||||
body, err := ExtractMetadata(fmt.Sprintf(format, args...), &meta)
|
||||
return body, meta, err
|
||||
} else {
|
||||
body, err := ExtractMetadataBytes(fmt.Appendf(nil, format, args...), &meta)
|
||||
return string(body), meta, err
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("NoFirstSeparator", func(t *testing.T) {
|
||||
var meta IssueTemplate
|
||||
_, err := ExtractMetadata(fmt.Sprintf("%s\n%s\n%s", frontTest, sepTest, bodyTest), &meta)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
t.Run("ValidFrontAndBody", func(t *testing.T) {
|
||||
body, meta, err := extract("%s\n%s\n%s\n%s", sepTest, frontTest, sepTest, bodyTest)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, bodyTest, body)
|
||||
assert.Equal(t, metaTest, meta)
|
||||
assert.True(t, meta.Valid())
|
||||
})
|
||||
|
||||
t.Run("NoLastSeparator", func(t *testing.T) {
|
||||
var meta IssueTemplate
|
||||
_, err := ExtractMetadata(fmt.Sprintf("%s\n%s\n%s", sepTest, frontTest, bodyTest), &meta)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
t.Run("NoFirstSeparator", func(t *testing.T) {
|
||||
_, _, err := extract("%s\n%s\n%s", frontTest, sepTest, bodyTest)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("NoBody", func(t *testing.T) {
|
||||
var meta IssueTemplate
|
||||
body, err := ExtractMetadata(fmt.Sprintf("%s\n%s\n%s", sepTest, frontTest, sepTest), &meta)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, body)
|
||||
assert.Equal(t, metaTest, meta)
|
||||
assert.True(t, meta.Valid())
|
||||
})
|
||||
}
|
||||
t.Run("NoLastSeparator", func(t *testing.T) {
|
||||
_, _, err := extract("%s\n%s\n%s", sepTest, frontTest, bodyTest)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
func TestExtractMetadataBytes(t *testing.T) {
|
||||
t.Run("ValidFrontAndBody", func(t *testing.T) {
|
||||
var meta IssueTemplate
|
||||
body, err := ExtractMetadataBytes(fmt.Appendf(nil, "%s\n%s\n%s\n%s", sepTest, frontTest, sepTest, bodyTest), &meta)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, bodyTest, string(body))
|
||||
assert.Equal(t, metaTest, meta)
|
||||
assert.True(t, meta.Valid())
|
||||
})
|
||||
|
||||
t.Run("NoFirstSeparator", func(t *testing.T) {
|
||||
var meta IssueTemplate
|
||||
_, err := ExtractMetadataBytes(fmt.Appendf(nil, "%s\n%s\n%s", frontTest, sepTest, bodyTest), &meta)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("NoLastSeparator", func(t *testing.T) {
|
||||
var meta IssueTemplate
|
||||
_, err := ExtractMetadataBytes(fmt.Appendf(nil, "%s\n%s\n%s", sepTest, frontTest, bodyTest), &meta)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("NoBody", func(t *testing.T) {
|
||||
var meta IssueTemplate
|
||||
body, err := ExtractMetadataBytes(fmt.Appendf(nil, "%s\n%s\n%s", sepTest, frontTest, sepTest), &meta)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, string(body))
|
||||
assert.Equal(t, metaTest, meta)
|
||||
assert.True(t, meta.Valid())
|
||||
})
|
||||
t.Run("NoBody", func(t *testing.T) {
|
||||
body, meta, err := extract("%s\n%s\n%s", sepTest, frontTest, sepTest)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, body)
|
||||
assert.Equal(t, metaTest, meta)
|
||||
assert.True(t, meta.Valid())
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -12,17 +12,12 @@ import (
|
||||
)
|
||||
|
||||
func TestRenderIFrame(t *testing.T) {
|
||||
render := func(ctx *RenderContext, opts ExternalRendererOptions) string {
|
||||
sb := &strings.Builder{}
|
||||
require.NoError(t, RenderIFrame(ctx, &opts, sb))
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
ctx := NewRenderContext(t.Context()).
|
||||
WithRelativePath("tree-path").
|
||||
WithMetas(map[string]string{"user": "test-owner", "repo": "test-repo", "RefTypeNameSubURL": "src/branch/master"})
|
||||
|
||||
// iframe doesn't need sandbox, the sandbox is set in render's response header
|
||||
ret := render(ctx, ExternalRendererOptions{ContentSandbox: "any"})
|
||||
assert.Equal(t, `<iframe data-src="/test-owner/test-repo/render/src/branch/master/tree-path" data-global-init="initExternalRenderIframe" class="external-render-iframe"></iframe>`, ret)
|
||||
sb := &strings.Builder{}
|
||||
require.NoError(t, RenderIFrame(ctx, &ExternalRendererOptions{ContentSandbox: "any"}, sb))
|
||||
assert.Equal(t, `<iframe data-src="/test-owner/test-repo/render/src/branch/master/tree-path" data-global-init="initExternalRenderIframe" class="external-render-iframe"></iframe>`, sb.String())
|
||||
}
|
||||
@@ -8,74 +8,26 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRedisUsernameOpt(t *testing.T) {
|
||||
uri, _ := url.Parse("redis://redis:password@myredis/0")
|
||||
opts := getRedisOptions(uri)
|
||||
|
||||
if opts.Username != "redis" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedisPasswordOpt(t *testing.T) {
|
||||
uri, _ := url.Parse("redis://redis:password@myredis/0")
|
||||
opts := getRedisOptions(uri)
|
||||
|
||||
if opts.Password != "password" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestSkipVerifyOpt(t *testing.T) {
|
||||
uri, _ := url.Parse("rediss://myredis/0?skipverify=true")
|
||||
tlsConfig := getRedisTLSOptions(uri)
|
||||
|
||||
if !tlsConfig.InsecureSkipVerify {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsecureSkipVerifyOpt(t *testing.T) {
|
||||
uri, _ := url.Parse("rediss://myredis/0?insecureskipverify=true")
|
||||
tlsConfig := getRedisTLSOptions(uri)
|
||||
|
||||
if !tlsConfig.InsecureSkipVerify {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedisSentinelUsernameOpt(t *testing.T) {
|
||||
uri, _ := url.Parse("redis+sentinel://redis:password@myredis/0?sentinelusername=suser&sentinelpassword=spass")
|
||||
opts := getRedisOptions(uri).Failover()
|
||||
|
||||
if opts.SentinelUsername != "suser" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedisSentinelPasswordOpt(t *testing.T) {
|
||||
uri, _ := url.Parse("redis+sentinel://redis:password@myredis/0?sentinelusername=suser&sentinelpassword=spass")
|
||||
opts := getRedisOptions(uri).Failover()
|
||||
|
||||
if opts.SentinelPassword != "spass" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedisDatabaseIndexTcp(t *testing.T) {
|
||||
uri, _ := url.Parse("redis://redis:password@myredis/12")
|
||||
opts := getRedisOptions(uri)
|
||||
|
||||
if opts.DB != 12 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedisDatabaseIndexUnix(t *testing.T) {
|
||||
uri, _ := url.Parse("redis+socket:///var/run/redis.sock?database=12")
|
||||
opts := getRedisOptions(uri)
|
||||
|
||||
if opts.DB != 12 {
|
||||
t.Fail()
|
||||
func TestRedisOptions(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
connection string
|
||||
valid func(*url.URL) bool
|
||||
}{
|
||||
{"username", "redis://redis:password@myredis/0", func(uri *url.URL) bool { return getRedisOptions(uri).Username == "redis" }},
|
||||
{"password", "redis://redis:password@myredis/0", func(uri *url.URL) bool { return getRedisOptions(uri).Password == "password" }},
|
||||
{"skipverify", "rediss://myredis/0?skipverify=true", func(uri *url.URL) bool { return getRedisTLSOptions(uri).InsecureSkipVerify }},
|
||||
{"insecureskipverify", "rediss://myredis/0?insecureskipverify=true", func(uri *url.URL) bool { return getRedisTLSOptions(uri).InsecureSkipVerify }},
|
||||
{"sentinel username", "redis+sentinel://redis:password@myredis/0?sentinelusername=suser&sentinelpassword=spass", func(uri *url.URL) bool { return getRedisOptions(uri).Failover().SentinelUsername == "suser" }},
|
||||
{"sentinel password", "redis+sentinel://redis:password@myredis/0?sentinelusername=suser&sentinelpassword=spass", func(uri *url.URL) bool { return getRedisOptions(uri).Failover().SentinelPassword == "spass" }},
|
||||
{"tcp database", "redis://redis:password@myredis/12", func(uri *url.URL) bool { return getRedisOptions(uri).DB == 12 }},
|
||||
{"unix database", "redis+socket:///var/run/redis.sock?database=12", func(uri *url.URL) bool { return getRedisOptions(uri).DB == 12 }},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
uri, _ := url.Parse(test.connection)
|
||||
if !test.valid(uri) {
|
||||
t.Fail()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -37,16 +37,22 @@ type testSerializationNullPointer struct {
|
||||
OptNull optional.Option[*time.Time] `json:"opt_null,omitempty" yaml:"opt_null,omitempty"`
|
||||
}
|
||||
|
||||
func TestOptionalToJson(t *testing.T) {
|
||||
func TestOptionalToJsonAndYaml(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
obj *testSerializationStruct
|
||||
want string
|
||||
name string
|
||||
obj *testSerializationStruct
|
||||
want string
|
||||
wantYaml string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
obj: new(testSerializationStruct),
|
||||
want: `{"normal_string":"","normal_bool":false,"optional_two_bool":null,"optional_two_string":null}`,
|
||||
wantYaml: `normal_string: ""
|
||||
normal_bool: false
|
||||
optional_two_bool: null
|
||||
optional_two_string: null
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "some",
|
||||
@@ -59,6 +65,13 @@ func TestOptionalToJson(t *testing.T) {
|
||||
OptTwoString: optional.None[string](),
|
||||
},
|
||||
want: `{"normal_string":"a string","normal_bool":true,"optional_bool":false,"optional_string":"","optional_two_bool":null,"optional_two_string":null}`,
|
||||
wantYaml: `normal_string: a string
|
||||
normal_bool: true
|
||||
optional_bool: false
|
||||
optional_string: ""
|
||||
optional_two_bool: null
|
||||
optional_two_string: null
|
||||
`,
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
@@ -70,6 +83,10 @@ func TestOptionalToJson(t *testing.T) {
|
||||
b, err = std_json.Marshal(tc.obj)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.want, string(b), "std json module returned unexpected")
|
||||
|
||||
b, err = yaml.Marshal(tc.obj)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.wantYaml, string(b), "yaml module returned unexpected")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -100,11 +117,12 @@ func TestOptionalToJson(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestOptionalFromJson(t *testing.T) {
|
||||
func TestOptionalFromJsonAndYaml(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
data string
|
||||
want testSerializationStruct
|
||||
name string
|
||||
data string
|
||||
dataYaml string
|
||||
want testSerializationStruct
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
@@ -116,94 +134,7 @@ func TestOptionalFromJson(t *testing.T) {
|
||||
{
|
||||
name: "some",
|
||||
data: `{"normal_string":"a string","normal_bool":true,"optional_bool":false,"optional_string":"","optional_two_bool":null,"optional_two_string":null}`,
|
||||
want: testSerializationStruct{
|
||||
NormalString: "a string",
|
||||
NormalBool: true,
|
||||
OptBool: optional.Some(false),
|
||||
OptString: optional.Some(""),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var obj1 testSerializationStruct
|
||||
err := json.Unmarshal([]byte(tc.data), &obj1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.want, obj1, "gitea json module returned unexpected")
|
||||
|
||||
var obj2 testSerializationStruct
|
||||
err = std_json.Unmarshal([]byte(tc.data), &obj2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.want, obj2, "std json module returned unexpected")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionalToYaml(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
obj *testSerializationStruct
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
obj: new(testSerializationStruct),
|
||||
want: `normal_string: ""
|
||||
normal_bool: false
|
||||
optional_two_bool: null
|
||||
optional_two_string: null
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "some",
|
||||
obj: &testSerializationStruct{
|
||||
NormalString: "a string",
|
||||
NormalBool: true,
|
||||
OptBool: optional.Some(false),
|
||||
OptString: optional.Some(""),
|
||||
},
|
||||
want: `normal_string: a string
|
||||
normal_bool: true
|
||||
optional_bool: false
|
||||
optional_string: ""
|
||||
optional_two_bool: null
|
||||
optional_two_string: null
|
||||
`,
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
b, err := yaml.Marshal(tc.obj)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.want, string(b), "yaml module returned unexpected")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionalFromYaml(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
data string
|
||||
want testSerializationStruct
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
data: ``,
|
||||
want: testSerializationStruct{},
|
||||
},
|
||||
{
|
||||
name: "empty but init",
|
||||
data: `normal_string: ""
|
||||
normal_bool: false
|
||||
optional_bool:
|
||||
optional_two_bool:
|
||||
optional_two_string:
|
||||
`,
|
||||
want: testSerializationStruct{},
|
||||
},
|
||||
{
|
||||
name: "some",
|
||||
data: `
|
||||
dataYaml: `
|
||||
normal_string: a string
|
||||
normal_bool: true
|
||||
optional_bool: false
|
||||
@@ -221,10 +152,31 @@ optional_two_string: null
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var obj testSerializationStruct
|
||||
err := yaml.Unmarshal([]byte(tc.data), &obj)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.want, obj, "yaml module returned unexpected")
|
||||
for _, format := range []struct {
|
||||
data string
|
||||
unmarshal func([]byte, any) error
|
||||
message string
|
||||
}{
|
||||
{tc.data, json.Unmarshal, "gitea json module returned unexpected"},
|
||||
{tc.data, std_json.Unmarshal, "std json module returned unexpected"},
|
||||
{tc.dataYaml, yaml.Unmarshal, "yaml module returned unexpected"},
|
||||
} {
|
||||
var obj testSerializationStruct
|
||||
err := format.unmarshal([]byte(format.data), &obj)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.want, obj, format.message)
|
||||
}
|
||||
})
|
||||
}
|
||||
t.Run("empty but init", func(t *testing.T) {
|
||||
var obj testSerializationStruct
|
||||
err := yaml.Unmarshal([]byte(`normal_string: ""
|
||||
normal_bool: false
|
||||
optional_bool:
|
||||
optional_two_bool:
|
||||
optional_two_string:
|
||||
`), &obj)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, testSerializationStruct{}, obj, "yaml module returned unexpected")
|
||||
})
|
||||
}
|
||||
@@ -22,43 +22,37 @@ const (
|
||||
)
|
||||
|
||||
func TestParsePackage(t *testing.T) {
|
||||
t.Run("MissingMetadataFile", func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
zw := gzip.NewWriter(&buf)
|
||||
tw := tar.NewWriter(zw)
|
||||
tw.Close()
|
||||
zw.Close()
|
||||
for _, name := range []string{"MissingMetadataFile", "Valid"} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
zw := gzip.NewWriter(&buf)
|
||||
tw := tar.NewWriter(zw)
|
||||
if name == "Valid" {
|
||||
content := `{"name":"` + packageName + `","version":"` + packageVersion + `"}`
|
||||
hdr := &tar.Header{
|
||||
Name: packageName + "/metadata.json",
|
||||
Mode: 0o600,
|
||||
Size: int64(len(content)),
|
||||
}
|
||||
tw.WriteHeader(hdr)
|
||||
tw.Write([]byte(content))
|
||||
}
|
||||
tw.Close()
|
||||
zw.Close()
|
||||
|
||||
p, err := ParsePackage(&buf)
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrMissingMetadataFile)
|
||||
})
|
||||
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
zw := gzip.NewWriter(&buf)
|
||||
tw := tar.NewWriter(zw)
|
||||
|
||||
content := `{"name":"` + packageName + `","version":"` + packageVersion + `"}`
|
||||
|
||||
hdr := &tar.Header{
|
||||
Name: packageName + "/metadata.json",
|
||||
Mode: 0o600,
|
||||
Size: int64(len(content)),
|
||||
}
|
||||
tw.WriteHeader(hdr)
|
||||
tw.Write([]byte(content))
|
||||
|
||||
tw.Close()
|
||||
zw.Close()
|
||||
|
||||
p, err := ParsePackage(&buf)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, p)
|
||||
assert.Equal(t, packageName, p.Name)
|
||||
assert.Equal(t, packageVersion, p.Version)
|
||||
assert.NotNil(t, p.Metadata)
|
||||
})
|
||||
p, err := ParsePackage(&buf)
|
||||
if name == "MissingMetadataFile" {
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrMissingMetadataFile)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, p)
|
||||
assert.Equal(t, packageName, p.Name)
|
||||
assert.Equal(t, packageVersion, p.Version)
|
||||
assert.NotNil(t, p.Metadata)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseChefMetadata(t *testing.T) {
|
||||
|
||||
@@ -75,45 +75,28 @@ func TestCommentsUnmarshal(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestParsePackage(t *testing.T) {
|
||||
t.Run("MissingComposerFile", func(t *testing.T) {
|
||||
data := test.WriteZipArchive(map[string]string{"dummy.txt": ""}).Bytes()
|
||||
for _, tc := range []struct {
|
||||
name, filename, content string
|
||||
expectedError error
|
||||
}{
|
||||
{"MissingComposerFile", "dummy.txt", "", ErrMissingComposerFile},
|
||||
{"MissingComposerFileInRoot", "sub/sub/composer.json", "", ErrMissingComposerFile},
|
||||
{"InvalidComposerFile", "composer.json", "", nil},
|
||||
{"InvalidPackageName", "composer.json", "{}", ErrInvalidName},
|
||||
{"InvalidPackageVersion", "composer.json", `{"name": "gitea/composer-package", "version": "1.a.3"}`, ErrInvalidVersion},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
data := test.WriteZipArchive(map[string]string{tc.filename: tc.content}).Bytes()
|
||||
|
||||
cp, err := ParsePackage(bytes.NewReader(data))
|
||||
assert.Nil(t, cp)
|
||||
assert.ErrorIs(t, err, ErrMissingComposerFile)
|
||||
})
|
||||
|
||||
t.Run("MissingComposerFileInRoot", func(t *testing.T) {
|
||||
data := test.WriteZipArchive(map[string]string{"sub/sub/composer.json": ""}).Bytes()
|
||||
|
||||
cp, err := ParsePackage(bytes.NewReader(data))
|
||||
assert.Nil(t, cp)
|
||||
assert.ErrorIs(t, err, ErrMissingComposerFile)
|
||||
})
|
||||
|
||||
t.Run("InvalidComposerFile", func(t *testing.T) {
|
||||
data := test.WriteZipArchive(map[string]string{"composer.json": ""}).Bytes()
|
||||
|
||||
cp, err := ParsePackage(bytes.NewReader(data))
|
||||
assert.Nil(t, cp)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("InvalidPackageName", func(t *testing.T) {
|
||||
data := test.WriteZipArchive(map[string]string{"composer.json": "{}"}).Bytes()
|
||||
|
||||
cp, err := ParsePackage(bytes.NewReader(data))
|
||||
assert.Nil(t, cp)
|
||||
assert.ErrorIs(t, err, ErrInvalidName)
|
||||
})
|
||||
|
||||
t.Run("InvalidPackageVersion", func(t *testing.T) {
|
||||
data := test.WriteZipArchive(map[string]string{"composer.json": `{"name": "gitea/composer-package", "version": "1.a.3"}`}).Bytes()
|
||||
|
||||
cp, err := ParsePackage(bytes.NewReader(data))
|
||||
assert.Nil(t, cp)
|
||||
assert.ErrorIs(t, err, ErrInvalidVersion)
|
||||
})
|
||||
cp, err := ParsePackage(bytes.NewReader(data))
|
||||
assert.Nil(t, cp)
|
||||
if tc.expectedError == nil {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.ErrorIs(t, err, tc.expectedError)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("InvalidReadmePath", func(t *testing.T) {
|
||||
data := test.WriteZipArchive(map[string]string{"composer.json": `{"name": "gitea/composer-package", "readme": "sub/README.md"}`}).Bytes()
|
||||
|
||||
@@ -49,45 +49,25 @@ func TestNewRecipeReference(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRecipeReferenceRevisionOrDefault(t *testing.T) {
|
||||
rref, err := NewRecipeReference("name", "1.0", "", "", "")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, DefaultRevision, rref.RevisionOrDefault())
|
||||
|
||||
rref, err = NewRecipeReference("name", "1.0", "", "", DefaultRevision)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, DefaultRevision, rref.RevisionOrDefault())
|
||||
|
||||
rref, err = NewRecipeReference("name", "1.0", "", "", "Az09")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Az09", rref.RevisionOrDefault())
|
||||
}
|
||||
|
||||
func TestRecipeReferenceString(t *testing.T) {
|
||||
rref, err := NewRecipeReference("name", "1.0", "", "", "")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "name/1.0", rref.String())
|
||||
|
||||
rref, err = NewRecipeReference("name", "1.0", "user", "channel", "")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "name/1.0@user/channel", rref.String())
|
||||
|
||||
rref, err = NewRecipeReference("name", "1.0", "user", "channel", "Az09")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "name/1.0@user/channel#Az09", rref.String())
|
||||
}
|
||||
|
||||
func TestRecipeReferenceLinkName(t *testing.T) {
|
||||
rref, err := NewRecipeReference("name", "1.0", "", "", "")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "name/1.0/_/_/0", rref.LinkName())
|
||||
|
||||
rref, err = NewRecipeReference("name", "1.0", "user", "channel", "")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "name/1.0/user/channel/0", rref.LinkName())
|
||||
|
||||
rref, err = NewRecipeReference("name", "1.0", "user", "channel", "Az09")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "name/1.0/user/channel/Az09", rref.LinkName())
|
||||
for _, test := range []struct {
|
||||
user, channel, revision string
|
||||
method func(*RecipeReference) string
|
||||
expected string
|
||||
}{
|
||||
{"", "", "", (*RecipeReference).RevisionOrDefault, DefaultRevision},
|
||||
{"", "", DefaultRevision, (*RecipeReference).RevisionOrDefault, DefaultRevision},
|
||||
{"", "", "Az09", (*RecipeReference).RevisionOrDefault, "Az09"},
|
||||
{"", "", "", (*RecipeReference).String, "name/1.0"},
|
||||
{"user", "channel", "", (*RecipeReference).String, "name/1.0@user/channel"},
|
||||
{"user", "channel", "Az09", (*RecipeReference).String, "name/1.0@user/channel#Az09"},
|
||||
{"", "", "", (*RecipeReference).LinkName, "name/1.0/_/_/0"},
|
||||
{"user", "channel", "", (*RecipeReference).LinkName, "name/1.0/user/channel/0"},
|
||||
{"user", "channel", "Az09", (*RecipeReference).LinkName, "name/1.0/user/channel/Az09"},
|
||||
} {
|
||||
rref, err := NewRecipeReference("name", "1.0", test.user, test.channel, test.revision)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, test.expected, test.method(rref))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewPackageReference(t *testing.T) {
|
||||
@@ -121,27 +101,19 @@ func TestNewPackageReference(t *testing.T) {
|
||||
func TestPackageReferenceRevisionOrDefault(t *testing.T) {
|
||||
rref, _ := NewRecipeReference("name", "1.0", "", "", "")
|
||||
|
||||
pref, err := NewPackageReference(rref, "ref", "")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, DefaultRevision, pref.RevisionOrDefault())
|
||||
|
||||
pref, err = NewPackageReference(rref, "ref", DefaultRevision)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, DefaultRevision, pref.RevisionOrDefault())
|
||||
|
||||
pref, err = NewPackageReference(rref, "ref", "Az09")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Az09", pref.RevisionOrDefault())
|
||||
}
|
||||
|
||||
func TestPackageReferenceLinkName(t *testing.T) {
|
||||
rref, _ := NewRecipeReference("name", "1.0", "", "", "")
|
||||
|
||||
pref, err := NewPackageReference(rref, "ref", "")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "ref/0", pref.LinkName())
|
||||
|
||||
pref, err = NewPackageReference(rref, "ref", "Az09")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "ref/Az09", pref.LinkName())
|
||||
for _, test := range []struct {
|
||||
revision string
|
||||
method func(*PackageReference) string
|
||||
expected string
|
||||
}{
|
||||
{"", (*PackageReference).RevisionOrDefault, DefaultRevision},
|
||||
{DefaultRevision, (*PackageReference).RevisionOrDefault, DefaultRevision},
|
||||
{"Az09", (*PackageReference).RevisionOrDefault, "Az09"},
|
||||
{"", (*PackageReference).LinkName, "ref/0"},
|
||||
{"Az09", (*PackageReference).LinkName, "ref/Az09"},
|
||||
} {
|
||||
pref, err := NewPackageReference(rref, "ref", test.revision)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, test.expected, test.method(pref))
|
||||
}
|
||||
}
|
||||
@@ -37,8 +37,11 @@ func createDescription(name, version string) *bytes.Buffer {
|
||||
}
|
||||
|
||||
func TestParsePackage(t *testing.T) {
|
||||
t.Run(".tar.gz", func(t *testing.T) {
|
||||
createArchive := func(filename string, content []byte) *bytes.Reader {
|
||||
for _, archive := range []struct {
|
||||
extension string
|
||||
create func(string, []byte) *bytes.Reader
|
||||
}{
|
||||
{".tar.gz", func(filename string, content []byte) *bytes.Reader {
|
||||
var buf bytes.Buffer
|
||||
gw := gzip.NewWriter(&buf)
|
||||
tw := tar.NewWriter(gw)
|
||||
@@ -52,70 +55,43 @@ func TestParsePackage(t *testing.T) {
|
||||
tw.Close()
|
||||
gw.Close()
|
||||
return bytes.NewReader(buf.Bytes())
|
||||
}
|
||||
|
||||
t.Run("MissingDescriptionFile", func(t *testing.T) {
|
||||
buf := createArchive(
|
||||
"dummy.txt",
|
||||
[]byte{},
|
||||
)
|
||||
|
||||
p, err := ParsePackage(buf, buf.Size())
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrMissingDescriptionFile)
|
||||
})
|
||||
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
buf := createArchive(
|
||||
"package/DESCRIPTION",
|
||||
createDescription(packageName, packageVersion).Bytes(),
|
||||
)
|
||||
|
||||
p, err := ParsePackage(buf, buf.Size())
|
||||
|
||||
assert.NotNil(t, p)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, packageName, p.Name)
|
||||
assert.Equal(t, packageVersion, p.Version)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run(".zip", func(t *testing.T) {
|
||||
createArchive := func(filename string, content []byte) *bytes.Reader {
|
||||
}},
|
||||
{".zip", func(filename string, content []byte) *bytes.Reader {
|
||||
var buf bytes.Buffer
|
||||
archive := zip.NewWriter(&buf)
|
||||
w, _ := archive.Create(filename)
|
||||
w.Write(content)
|
||||
archive.Close()
|
||||
return bytes.NewReader(buf.Bytes())
|
||||
}
|
||||
}},
|
||||
} {
|
||||
t.Run(archive.extension, func(t *testing.T) {
|
||||
t.Run("MissingDescriptionFile", func(t *testing.T) {
|
||||
buf := archive.create(
|
||||
"dummy.txt",
|
||||
[]byte{},
|
||||
)
|
||||
|
||||
t.Run("MissingDescriptionFile", func(t *testing.T) {
|
||||
buf := createArchive(
|
||||
"dummy.txt",
|
||||
[]byte{},
|
||||
)
|
||||
p, err := ParsePackage(buf, buf.Size())
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrMissingDescriptionFile)
|
||||
})
|
||||
|
||||
p, err := ParsePackage(buf, buf.Size())
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrMissingDescriptionFile)
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
buf := archive.create(
|
||||
"package/DESCRIPTION",
|
||||
createDescription(packageName, packageVersion).Bytes(),
|
||||
)
|
||||
|
||||
p, err := ParsePackage(buf, buf.Size())
|
||||
assert.NotNil(t, p)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, packageName, p.Name)
|
||||
assert.Equal(t, packageVersion, p.Version)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
buf := createArchive(
|
||||
"package/DESCRIPTION",
|
||||
createDescription(packageName, packageVersion).Bytes(),
|
||||
)
|
||||
|
||||
p, err := ParsePackage(buf, buf.Size())
|
||||
assert.NotNil(t, p)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, packageName, p.Name)
|
||||
assert.Equal(t, packageVersion, p.Version)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseDescription(t *testing.T) {
|
||||
|
||||
@@ -110,21 +110,14 @@ func TestParsePackage(t *testing.T) {
|
||||
w.Write(buf.Bytes())
|
||||
w.Close()
|
||||
|
||||
data := createArchive(map[string][]byte{"control.tar" + c.Extension: cbuf.Bytes()})
|
||||
|
||||
p, err := ParsePackage(data)
|
||||
assert.NotNil(t, p)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "gitea", p.Name)
|
||||
|
||||
t.Run("TrailingSlash", func(t *testing.T) {
|
||||
data := createArchive(map[string][]byte{"control.tar" + c.Extension + "/": cbuf.Bytes()})
|
||||
for _, suffix := range []string{"", "/"} {
|
||||
data := createArchive(map[string][]byte{"control.tar" + c.Extension + suffix: cbuf.Bytes()})
|
||||
|
||||
p, err := ParsePackage(data)
|
||||
assert.NotNil(t, p)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "gitea", p.Name)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -28,58 +28,41 @@ func TestParsePackage(t *testing.T) {
|
||||
return bytes.NewReader(buf.Bytes())
|
||||
}
|
||||
|
||||
t.Run("EmptyPackage", func(t *testing.T) {
|
||||
data := createArchive(nil)
|
||||
|
||||
p, err := ParsePackage(data, int64(data.Len()))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidStructure)
|
||||
})
|
||||
|
||||
t.Run("InvalidNameOrVersionStructure", func(t *testing.T) {
|
||||
data := createArchive(map[string][]byte{
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
files map[string][]byte
|
||||
expectedError error
|
||||
goMod string
|
||||
}{
|
||||
{"EmptyPackage", nil, ErrInvalidStructure, ""},
|
||||
{"InvalidNameOrVersionStructure", map[string][]byte{
|
||||
packageName + "/" + packageVersion + "/go.mod": {},
|
||||
})
|
||||
|
||||
p, err := ParsePackage(data, int64(data.Len()))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidStructure)
|
||||
})
|
||||
|
||||
t.Run("GoModFileInWrongDirectory", func(t *testing.T) {
|
||||
data := createArchive(map[string][]byte{
|
||||
}, ErrInvalidStructure, ""},
|
||||
{"GoModFileInWrongDirectory", map[string][]byte{
|
||||
packageName + "@" + packageVersion + "/subdir/go.mod": {},
|
||||
})
|
||||
|
||||
p, err := ParsePackage(data, int64(data.Len()))
|
||||
assert.NotNil(t, p)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, packageName, p.Name)
|
||||
assert.Equal(t, packageVersion, p.Version)
|
||||
assert.Equal(t, "module gitea.com/go-gitea/gitea", p.GoMod)
|
||||
})
|
||||
|
||||
t.Run("InvalidVersion", func(t *testing.T) {
|
||||
data := createArchive(map[string][]byte{
|
||||
}, nil, "module gitea.com/go-gitea/gitea"},
|
||||
{"InvalidVersion", map[string][]byte{
|
||||
packageName + "@v1.0.0\nv99.0.0/go.mod": []byte("module " + packageName),
|
||||
})
|
||||
|
||||
p, err := ParsePackage(data, int64(data.Len()))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidVersion)
|
||||
})
|
||||
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
data := createArchive(map[string][]byte{
|
||||
}, ErrInvalidVersion, ""},
|
||||
{"Valid", map[string][]byte{
|
||||
packageName + "@" + packageVersion + "/subdir/go.mod": []byte("invalid"),
|
||||
packageName + "@" + packageVersion + "/go.mod": []byte("valid"),
|
||||
})
|
||||
}, nil, "valid"},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
data := createArchive(testCase.files)
|
||||
|
||||
p, err := ParsePackage(data, int64(data.Len()))
|
||||
assert.NotNil(t, p)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, packageName, p.Name)
|
||||
assert.Equal(t, packageVersion, p.Version)
|
||||
assert.Equal(t, "valid", p.GoMod)
|
||||
})
|
||||
p, err := ParsePackage(data, int64(data.Len()))
|
||||
if testCase.expectedError != nil {
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, testCase.expectedError)
|
||||
} else {
|
||||
assert.NotNil(t, p)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, packageName, p.Name)
|
||||
assert.Equal(t, packageVersion, p.Version)
|
||||
assert.Equal(t, testCase.goMod, p.GoMod)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -18,36 +18,28 @@ const (
|
||||
)
|
||||
|
||||
func TestMultiHasherSums(t *testing.T) {
|
||||
t.Run("Sums", func(t *testing.T) {
|
||||
h := NewMultiHasher()
|
||||
h.Write([]byte("gitea"))
|
||||
for _, content := range []string{"gitea", "git"} {
|
||||
t.Run(content, func(t *testing.T) {
|
||||
h := NewMultiHasher()
|
||||
h.Write([]byte(content))
|
||||
|
||||
hashMD5, hashSHA1, hashSHA256, hashSHA512 := h.Sums()
|
||||
if content == "git" {
|
||||
state, err := h.MarshalBinary()
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, expectedMD5, hex.EncodeToString(hashMD5))
|
||||
assert.Equal(t, expectedSHA1, hex.EncodeToString(hashSHA1))
|
||||
assert.Equal(t, expectedSHA256, hex.EncodeToString(hashSHA256))
|
||||
assert.Equal(t, expectedSHA512, hex.EncodeToString(hashSHA512))
|
||||
})
|
||||
h = NewMultiHasher()
|
||||
err = h.UnmarshalBinary(state)
|
||||
assert.NoError(t, err)
|
||||
|
||||
t.Run("State", func(t *testing.T) {
|
||||
h := NewMultiHasher()
|
||||
h.Write([]byte("git"))
|
||||
h.Write([]byte("ea"))
|
||||
}
|
||||
|
||||
state, err := h.MarshalBinary()
|
||||
assert.NoError(t, err)
|
||||
hashMD5, hashSHA1, hashSHA256, hashSHA512 := h.Sums()
|
||||
|
||||
h2 := NewMultiHasher()
|
||||
err = h2.UnmarshalBinary(state)
|
||||
assert.NoError(t, err)
|
||||
|
||||
h2.Write([]byte("ea"))
|
||||
|
||||
hashMD5, hashSHA1, hashSHA256, hashSHA512 := h2.Sums()
|
||||
|
||||
assert.Equal(t, expectedMD5, hex.EncodeToString(hashMD5))
|
||||
assert.Equal(t, expectedSHA1, hex.EncodeToString(hashSHA1))
|
||||
assert.Equal(t, expectedSHA256, hex.EncodeToString(hashSHA256))
|
||||
assert.Equal(t, expectedSHA512, hex.EncodeToString(hashSHA512))
|
||||
})
|
||||
assert.Equal(t, expectedMD5, hex.EncodeToString(hashMD5))
|
||||
assert.Equal(t, expectedSHA1, hex.EncodeToString(hashSHA1))
|
||||
assert.Equal(t, expectedSHA256, hex.EncodeToString(hashSHA256))
|
||||
assert.Equal(t, expectedSHA512, hex.EncodeToString(hashSHA512))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -52,71 +52,38 @@ func TestParsePackage(t *testing.T) {
|
||||
assert.ErrorIs(t, err, ErrInvalidPackage)
|
||||
})
|
||||
|
||||
t.Run("InvalidPackageName", func(t *testing.T) {
|
||||
test := func(t *testing.T, name string) {
|
||||
p, err := parseUploadPackage(&packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: name,
|
||||
Name: name,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: name,
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
names []string
|
||||
expectedError error
|
||||
}{
|
||||
{"InvalidPackageName", []string{
|
||||
" test ", " test", "test ", "te st", "Test", "_test", ".test", "^test", "te^st",
|
||||
"te|st", "te)(st", "te'st", "te!st", "te*st", "te~st", "invalid/scope", "@invalid/_name", "@invalid/.name",
|
||||
}, ErrInvalidPackageName},
|
||||
{"ValidPackageName", []string{
|
||||
"test", "@scope/name", "@scope/q", "q", "@scope/package-name", "@scope/package.name", "@scope/package_name",
|
||||
"123name", "----", packageFullName,
|
||||
}, ErrInvalidPackageVersion},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
for _, name := range testCase.names {
|
||||
p, err := parseUploadPackage(&packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: name,
|
||||
Name: name,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: name,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidPackageName)
|
||||
}
|
||||
|
||||
test(t, " test ")
|
||||
test(t, " test")
|
||||
test(t, "test ")
|
||||
test(t, "te st")
|
||||
test(t, "Test")
|
||||
test(t, "_test")
|
||||
test(t, ".test")
|
||||
test(t, "^test")
|
||||
test(t, "te^st")
|
||||
test(t, "te|st")
|
||||
test(t, "te)(st")
|
||||
test(t, "te'st")
|
||||
test(t, "te!st")
|
||||
test(t, "te*st")
|
||||
test(t, "te~st")
|
||||
test(t, "invalid/scope")
|
||||
test(t, "@invalid/_name")
|
||||
test(t, "@invalid/.name")
|
||||
})
|
||||
|
||||
t.Run("ValidPackageName", func(t *testing.T) {
|
||||
test := func(t *testing.T, name string) {
|
||||
p, err := parseUploadPackage(&packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: name,
|
||||
Name: name,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: name,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidPackageVersion)
|
||||
}
|
||||
|
||||
test(t, "test")
|
||||
test(t, "@scope/name")
|
||||
test(t, "@scope/q")
|
||||
test(t, "q")
|
||||
test(t, "@scope/package-name")
|
||||
test(t, "@scope/package.name")
|
||||
test(t, "@scope/package_name")
|
||||
test(t, "123name")
|
||||
test(t, "----")
|
||||
test(t, packageFullName)
|
||||
})
|
||||
})
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, testCase.expectedError)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("InvalidPackageVersion", func(t *testing.T) {
|
||||
version := "first-version"
|
||||
@@ -136,108 +103,42 @@ func TestParsePackage(t *testing.T) {
|
||||
assert.ErrorIs(t, err, ErrInvalidPackageVersion)
|
||||
})
|
||||
|
||||
t.Run("InvalidAttachment", func(t *testing.T) {
|
||||
b, _ := json.Marshal(packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: packageFullName,
|
||||
Name: packageFullName,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: packageFullName,
|
||||
Version: packageVersion,
|
||||
},
|
||||
},
|
||||
},
|
||||
Attachments: map[string]*PackageAttachment{
|
||||
"dummy.tgz": {},
|
||||
},
|
||||
})
|
||||
|
||||
p, _, err := ParseUpload(bytes.NewReader(b))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidAttachment)
|
||||
})
|
||||
|
||||
t.Run("InvalidData", func(t *testing.T) {
|
||||
filename := fmt.Sprintf("%s-%s.tgz", packageFullName, packageVersion)
|
||||
b, _ := json.Marshal(packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: packageFullName,
|
||||
Name: packageFullName,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: packageFullName,
|
||||
Version: packageVersion,
|
||||
},
|
||||
},
|
||||
},
|
||||
Attachments: map[string]*PackageAttachment{
|
||||
filename: {
|
||||
Data: "/",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
p, _, err := ParseUpload(bytes.NewReader(b))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidAttachment)
|
||||
})
|
||||
|
||||
t.Run("InvalidIntegrity", func(t *testing.T) {
|
||||
filename := fmt.Sprintf("%s-%s.tgz", packageFullName, packageVersion)
|
||||
b, _ := json.Marshal(packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: packageFullName,
|
||||
Name: packageFullName,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: packageFullName,
|
||||
Version: packageVersion,
|
||||
Dist: PackageDistribution{
|
||||
Integrity: "sha512-test==",
|
||||
for _, testCase := range []struct {
|
||||
name, filename, data, integrity string
|
||||
expectedError error
|
||||
}{
|
||||
{"InvalidAttachment", "dummy.tgz", "", "", ErrInvalidAttachment},
|
||||
{"InvalidData", fmt.Sprintf("%s-%s.tgz", packageFullName, packageVersion), "/", "", ErrInvalidAttachment},
|
||||
{"InvalidIntegrity", fmt.Sprintf("%s-%s.tgz", packageFullName, packageVersion), data, "sha512-test==", ErrInvalidIntegrity},
|
||||
{"InvalidIntegrity2", fmt.Sprintf("%s-%s.tgz", packageFullName, packageVersion), base64.StdEncoding.EncodeToString([]byte("data")), integrity, ErrInvalidIntegrity},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
b, _ := json.Marshal(packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: packageFullName,
|
||||
Name: packageFullName,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: packageFullName,
|
||||
Version: packageVersion,
|
||||
Dist: PackageDistribution{
|
||||
Integrity: testCase.integrity,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Attachments: map[string]*PackageAttachment{
|
||||
filename: {
|
||||
Data: data,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
p, _, err := ParseUpload(bytes.NewReader(b))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidIntegrity)
|
||||
})
|
||||
|
||||
t.Run("InvalidIntegrity2", func(t *testing.T) {
|
||||
filename := fmt.Sprintf("%s-%s.tgz", packageFullName, packageVersion)
|
||||
b, _ := json.Marshal(packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: packageFullName,
|
||||
Name: packageFullName,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: packageFullName,
|
||||
Version: packageVersion,
|
||||
Dist: PackageDistribution{
|
||||
Integrity: integrity,
|
||||
},
|
||||
Attachments: map[string]*PackageAttachment{
|
||||
testCase.filename: {
|
||||
Data: testCase.data,
|
||||
},
|
||||
},
|
||||
},
|
||||
Attachments: map[string]*PackageAttachment{
|
||||
filename: {
|
||||
Data: base64.StdEncoding.EncodeToString([]byte("data")),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
p, _, err := ParseUpload(bytes.NewReader(b))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidIntegrity)
|
||||
})
|
||||
p, _, err := ParseUpload(bytes.NewReader(b))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, testCase.expectedError)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
filename := fmt.Sprintf("%s-%s.tgz", packageFullName, packageVersion)
|
||||
|
||||
@@ -92,53 +92,37 @@ func TestParsePackageMetaData(t *testing.T) {
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
t.Run("MissingNuspecFile", func(t *testing.T) {
|
||||
data := createArchive(map[string]string{"dummy.txt": ""})
|
||||
|
||||
np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data)))
|
||||
assert.Nil(t, np)
|
||||
assert.ErrorIs(t, err, ErrMissingNuspecFile)
|
||||
})
|
||||
|
||||
t.Run("MissingNuspecFileInRoot", func(t *testing.T) {
|
||||
data := createArchive(map[string]string{"sub/package.nuspec": ""})
|
||||
|
||||
np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data)))
|
||||
assert.Nil(t, np)
|
||||
assert.ErrorIs(t, err, ErrMissingNuspecFile)
|
||||
})
|
||||
|
||||
t.Run("InvalidNuspecFile", func(t *testing.T) {
|
||||
data := createArchive(map[string]string{"package.nuspec": ""})
|
||||
|
||||
np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data)))
|
||||
assert.Nil(t, np)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("InvalidPackageId", func(t *testing.T) {
|
||||
data := createArchive(map[string]string{"package.nuspec": `<?xml version="1.0" encoding="utf-8"?>
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
files map[string]string
|
||||
expectedError error
|
||||
}{
|
||||
{"MissingNuspecFile", map[string]string{"dummy.txt": ""}, ErrMissingNuspecFile},
|
||||
{"MissingNuspecFileInRoot", map[string]string{"sub/package.nuspec": ""}, ErrMissingNuspecFile},
|
||||
{"InvalidNuspecFile", map[string]string{"package.nuspec": ""}, nil},
|
||||
{"InvalidPackageId", map[string]string{"package.nuspec": `<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
|
||||
<metadata></metadata>
|
||||
</package>`})
|
||||
|
||||
np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data)))
|
||||
assert.Nil(t, np)
|
||||
assert.ErrorIs(t, err, ErrNuspecInvalidID)
|
||||
})
|
||||
|
||||
t.Run("InvalidPackageVersion", func(t *testing.T) {
|
||||
data := createArchive(map[string]string{"package.nuspec": `<?xml version="1.0" encoding="utf-8"?>
|
||||
</package>`}, ErrNuspecInvalidID},
|
||||
{"InvalidPackageVersion", map[string]string{"package.nuspec": `<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>` + id + `</id>
|
||||
</metadata>
|
||||
</package>`})
|
||||
</package>`}, ErrNuspecInvalidVersion},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
data := createArchive(testCase.files)
|
||||
|
||||
np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data)))
|
||||
assert.Nil(t, np)
|
||||
assert.ErrorIs(t, err, ErrNuspecInvalidVersion)
|
||||
})
|
||||
np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data)))
|
||||
assert.Nil(t, np)
|
||||
if testCase.expectedError == nil {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.ErrorIs(t, err, testCase.expectedError)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("MissingReadme", func(t *testing.T) {
|
||||
data := createArchive(map[string]string{"package.nuspec": nuspecContent})
|
||||
|
||||
@@ -110,49 +110,22 @@ OvSXaRmpzyTLHvsXg/M9EcwbAAA=`
|
||||
},
|
||||
p.FileMetadata.Provides,
|
||||
)
|
||||
assert.ElementsMatch(
|
||||
t,
|
||||
[]*Entry{
|
||||
{
|
||||
Name: "/bin/sh",
|
||||
},
|
||||
{
|
||||
Name: "/bin/sh",
|
||||
},
|
||||
{
|
||||
Name: "/bin/sh",
|
||||
},
|
||||
{
|
||||
Name: "rpmlib(CompressedFileNames)",
|
||||
Flags: "LE",
|
||||
Version: "3.0.4",
|
||||
Epoch: "0",
|
||||
Release: "1",
|
||||
},
|
||||
{
|
||||
Name: "rpmlib(FileDigests)",
|
||||
Flags: "LE",
|
||||
Version: "4.6.0",
|
||||
Epoch: "0",
|
||||
Release: "1",
|
||||
},
|
||||
{
|
||||
Name: "rpmlib(PayloadFilesHavePrefix)",
|
||||
Flags: "LE",
|
||||
Version: "4.0",
|
||||
Epoch: "0",
|
||||
Release: "1",
|
||||
},
|
||||
{
|
||||
Name: "rpmlib(PayloadIsXz)",
|
||||
Flags: "LE",
|
||||
Version: "5.2",
|
||||
Epoch: "0",
|
||||
Release: "1",
|
||||
},
|
||||
},
|
||||
p.FileMetadata.Requires,
|
||||
)
|
||||
requires := []*Entry{{Name: "/bin/sh"}, {Name: "/bin/sh"}, {Name: "/bin/sh"}}
|
||||
for _, dependency := range []struct{ name, version string }{
|
||||
{"rpmlib(CompressedFileNames)", "3.0.4"},
|
||||
{"rpmlib(FileDigests)", "4.6.0"},
|
||||
{"rpmlib(PayloadFilesHavePrefix)", "4.0"},
|
||||
{"rpmlib(PayloadIsXz)", "5.2"},
|
||||
} {
|
||||
requires = append(requires, &Entry{
|
||||
Name: dependency.name,
|
||||
Flags: "LE",
|
||||
Version: dependency.version,
|
||||
Epoch: "0",
|
||||
Release: "1",
|
||||
})
|
||||
}
|
||||
assert.ElementsMatch(t, requires, p.FileMetadata.Requires)
|
||||
assert.ElementsMatch(
|
||||
t,
|
||||
[]*File{
|
||||
|
||||
@@ -164,15 +164,15 @@ func TestParsePackage(t *testing.T) {
|
||||
assert.Equal(t, contentA, p.Metadata.Manifests[""].Content)
|
||||
})
|
||||
|
||||
t.Run("WithMetadata", func(t *testing.T) {
|
||||
parseWithMetadata := func(metadata string) (*Package, error) {
|
||||
data := test.WriteZipArchive(map[string]string{
|
||||
"Package.swift": "// swift-tools-version:5.7\n//\n// Package.swift",
|
||||
})
|
||||
return ParsePackage(bytes.NewReader(data.Bytes()), int64(data.Len()), strings.NewReader(metadata))
|
||||
}
|
||||
|
||||
p, err := ParsePackage(
|
||||
bytes.NewReader(data.Bytes()), int64(data.Len()),
|
||||
strings.NewReader(`{"name":"`+packageName+`","version":"`+packageVersion+`","description":"`+packageDescription+`","keywords":["swift","package"],"license":"`+packageLicense+`","licenseURL":"`+packageLicenseURL+`","codeRepository":"`+packageRepositoryURL+`","author":{"givenName":"`+packageAuthor+`"},"repositoryURLs":["`+packageRepositoryURL+`"]}`),
|
||||
)
|
||||
t.Run("WithMetadata", func(t *testing.T) {
|
||||
p, err := parseWithMetadata(`{"name":"` + packageName + `","version":"` + packageVersion + `","description":"` + packageDescription + `","keywords":["swift","package"],"license":"` + packageLicense + `","licenseURL":"` + packageLicenseURL + `","codeRepository":"` + packageRepositoryURL + `","author":{"givenName":"` + packageAuthor + `"},"repositoryURLs":["` + packageRepositoryURL + `"]}`)
|
||||
assert.NotNil(t, p)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -192,15 +192,8 @@ func TestParsePackage(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("WithExplicitNameField", func(t *testing.T) {
|
||||
data := test.WriteZipArchive(map[string]string{
|
||||
"Package.swift": "// swift-tools-version:5.7\n//\n// Package.swift",
|
||||
})
|
||||
|
||||
authorName := "John Doe"
|
||||
p, err := ParsePackage(
|
||||
bytes.NewReader(data.Bytes()), int64(data.Len()),
|
||||
strings.NewReader(`{"name":"`+packageName+`","version":"`+packageVersion+`","description":"`+packageDescription+`","author":{"name":"`+authorName+`","givenName":"John","familyName":"Doe"}}`),
|
||||
)
|
||||
p, err := parseWithMetadata(`{"name":"` + packageName + `","version":"` + packageVersion + `","description":"` + packageDescription + `","author":{"name":"` + authorName + `","givenName":"John","familyName":"Doe"}}`)
|
||||
assert.NotNil(t, p)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -210,14 +203,7 @@ func TestParsePackage(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("WithEmptyJSONMetadata", func(t *testing.T) {
|
||||
data := test.WriteZipArchive(map[string]string{
|
||||
"Package.swift": "// swift-tools-version:5.7\n//\n// Package.swift",
|
||||
})
|
||||
|
||||
p, err := ParsePackage(
|
||||
bytes.NewReader(data.Bytes()), int64(data.Len()),
|
||||
strings.NewReader(`{}`),
|
||||
)
|
||||
p, err := parseWithMetadata(`{}`)
|
||||
assert.NotNil(t, p)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, p.Metadata)
|
||||
@@ -226,15 +212,8 @@ func TestParsePackage(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("NameFieldGeneration", func(t *testing.T) {
|
||||
data := test.WriteZipArchive(map[string]string{
|
||||
"Package.swift": "// swift-tools-version:5.7\n//\n// Package.swift",
|
||||
})
|
||||
|
||||
// Test with only individual name components - Name should be auto-generated
|
||||
p, err := ParsePackage(
|
||||
bytes.NewReader(data.Bytes()), int64(data.Len()),
|
||||
strings.NewReader(`{"author":{"givenName":"John","middleName":"Q","familyName":"Doe"}}`),
|
||||
)
|
||||
p, err := parseWithMetadata(`{"author":{"givenName":"John","middleName":"Q","familyName":"Doe"}}`)
|
||||
assert.NotNil(t, p)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "John Q Doe", p.Metadata.Author.Name)
|
||||
@@ -245,42 +224,16 @@ func TestParsePackage(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTrimmedVersionString(t *testing.T) {
|
||||
cases := []struct {
|
||||
Version *version.Version
|
||||
for _, c := range []struct {
|
||||
Versions []string
|
||||
Expected string
|
||||
}{
|
||||
{
|
||||
Version: version.Must(version.NewVersion("1")),
|
||||
Expected: "1.0",
|
||||
},
|
||||
{
|
||||
Version: version.Must(version.NewVersion("1.0")),
|
||||
Expected: "1.0",
|
||||
},
|
||||
{
|
||||
Version: version.Must(version.NewVersion("1.0.0")),
|
||||
Expected: "1.0",
|
||||
},
|
||||
{
|
||||
Version: version.Must(version.NewVersion("1.0.1")),
|
||||
Expected: "1.0.1",
|
||||
},
|
||||
{
|
||||
Version: version.Must(version.NewVersion("1.0+meta")),
|
||||
Expected: "1.0",
|
||||
},
|
||||
{
|
||||
Version: version.Must(version.NewVersion("1.0.0+meta")),
|
||||
Expected: "1.0",
|
||||
},
|
||||
{
|
||||
Version: version.Must(version.NewVersion("1.0.1+meta")),
|
||||
Expected: "1.0.1",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
assert.Equal(t, c.Expected, TrimmedVersionString(c.Version))
|
||||
{[]string{"1", "1.0", "1.0.0", "1.0+meta", "1.0.0+meta"}, "1.0"},
|
||||
{[]string{"1.0.1", "1.0.1+meta"}, "1.0.1"},
|
||||
} {
|
||||
for _, input := range c.Versions {
|
||||
assert.Equal(t, c.Expected, TrimmedVersionString(version.Must(version.NewVersion(input))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,29 +49,6 @@ func TestParseMetadataFromBox(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
content, err := json.Marshal(map[string]string{
|
||||
"description": description,
|
||||
"author": author,
|
||||
"website": projectURL,
|
||||
"repository": repositoryURL,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
data := createArchive(map[string][]byte{"info.json": content})
|
||||
|
||||
metadata, err := ParseMetadataFromBox(data)
|
||||
assert.NotNil(t, metadata)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, author, metadata.Author)
|
||||
assert.Equal(t, description, metadata.Description)
|
||||
assert.Equal(t, projectURL, metadata.ProjectURL)
|
||||
assert.Equal(t, repositoryURL, metadata.RepositoryURL)
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseInfoFile(t *testing.T) {
|
||||
t.Run("UnknownKeys", func(t *testing.T) {
|
||||
content, err := json.Marshal(map[string]string{
|
||||
"package": "",
|
||||
@@ -89,22 +66,31 @@ func TestParseInfoFile(t *testing.T) {
|
||||
assert.Empty(t, metadata.RepositoryURL)
|
||||
})
|
||||
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
content, err := json.Marshal(map[string]string{
|
||||
"description": description,
|
||||
"author": author,
|
||||
"website": projectURL,
|
||||
"repository": repositoryURL,
|
||||
for name, parse := range map[string]func([]byte) (*Metadata, error){
|
||||
"ValidBox": func(content []byte) (*Metadata, error) {
|
||||
return ParseMetadataFromBox(createArchive(map[string][]byte{"info.json": content}))
|
||||
},
|
||||
"ValidInfoFile": func(content []byte) (*Metadata, error) {
|
||||
return ParseInfoFile(bytes.NewReader(content))
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
content, err := json.Marshal(map[string]string{
|
||||
"description": description,
|
||||
"author": author,
|
||||
"website": projectURL,
|
||||
"repository": repositoryURL,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
metadata, err := parse(content)
|
||||
assert.NotNil(t, metadata)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, author, metadata.Author)
|
||||
assert.Equal(t, description, metadata.Description)
|
||||
assert.Equal(t, projectURL, metadata.ProjectURL)
|
||||
assert.Equal(t, repositoryURL, metadata.RepositoryURL)
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
metadata, err := ParseInfoFile(bytes.NewReader(content))
|
||||
assert.NotNil(t, metadata)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, author, metadata.Author)
|
||||
assert.Equal(t, description, metadata.Description)
|
||||
assert.Equal(t, projectURL, metadata.ProjectURL)
|
||||
assert.Equal(t, repositoryURL, metadata.RepositoryURL)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -85,226 +85,71 @@ func TestPaginator(t *testing.T) {
|
||||
assert.True(t, pages[0].IsCurrent())
|
||||
})
|
||||
|
||||
assertPages := func(t *testing.T, total, current, numPages int, expected ...int) {
|
||||
pages := New(total, 10, current, numPages).Pages()
|
||||
assert.Len(t, pages, len(expected))
|
||||
for i, number := range expected {
|
||||
assert.Equal(t, number, pages[i].Num())
|
||||
if number == current {
|
||||
assert.True(t, pages[i].IsCurrent())
|
||||
} else {
|
||||
assert.False(t, pages[i].IsCurrent())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("Total page number is less or equal", func(t *testing.T) {
|
||||
p := New(1, 10, 1, 2)
|
||||
pages := p.Pages()
|
||||
assert.Len(t, pages, 1)
|
||||
assert.Equal(t, 1, pages[0].Num())
|
||||
assert.True(t, pages[0].IsCurrent())
|
||||
assertPages(t, 1, 1, 2, 1)
|
||||
|
||||
p = New(11, 10, 1, 2)
|
||||
pages = p.Pages()
|
||||
assert.Len(t, pages, 2)
|
||||
assert.Equal(t, 1, pages[0].Num())
|
||||
assert.True(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 2, pages[1].Num())
|
||||
assert.False(t, pages[1].IsCurrent())
|
||||
assertPages(t, 11, 1, 2, 1, 2)
|
||||
|
||||
p = New(11, 10, 2, 2)
|
||||
pages = p.Pages()
|
||||
assert.Len(t, pages, 2)
|
||||
assert.Equal(t, 1, pages[0].Num())
|
||||
assert.False(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 2, pages[1].Num())
|
||||
assert.True(t, pages[1].IsCurrent())
|
||||
assertPages(t, 11, 2, 2, 1, 2)
|
||||
|
||||
p = New(25, 10, 2, 3)
|
||||
pages = p.Pages()
|
||||
assert.Len(t, pages, 3)
|
||||
assert.Equal(t, 1, pages[0].Num())
|
||||
assert.False(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 2, pages[1].Num())
|
||||
assert.True(t, pages[1].IsCurrent())
|
||||
assert.Equal(t, 3, pages[2].Num())
|
||||
assert.False(t, pages[2].IsCurrent())
|
||||
assertPages(t, 25, 2, 3, 1, 2, 3)
|
||||
})
|
||||
|
||||
t.Run("Has more previous pages ", func(t *testing.T) {
|
||||
// ... 2
|
||||
p := New(11, 10, 2, 1)
|
||||
pages := p.Pages()
|
||||
assert.Len(t, pages, 2)
|
||||
assert.Equal(t, -1, pages[0].Num())
|
||||
assert.False(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 2, pages[1].Num())
|
||||
assert.True(t, pages[1].IsCurrent())
|
||||
assertPages(t, 11, 2, 1, -1, 2)
|
||||
|
||||
// ... 2 3
|
||||
p = New(21, 10, 2, 2)
|
||||
pages = p.Pages()
|
||||
assert.Len(t, pages, 3)
|
||||
assert.Equal(t, -1, pages[0].Num())
|
||||
assert.False(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 2, pages[1].Num())
|
||||
assert.True(t, pages[1].IsCurrent())
|
||||
assert.Equal(t, 3, pages[2].Num())
|
||||
assert.False(t, pages[2].IsCurrent())
|
||||
assertPages(t, 21, 2, 2, -1, 2, 3)
|
||||
|
||||
// ... 2 3 4
|
||||
p = New(31, 10, 3, 3)
|
||||
pages = p.Pages()
|
||||
assert.Len(t, pages, 4)
|
||||
assert.Equal(t, -1, pages[0].Num())
|
||||
assert.False(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 2, pages[1].Num())
|
||||
assert.False(t, pages[1].IsCurrent())
|
||||
assert.Equal(t, 3, pages[2].Num())
|
||||
assert.True(t, pages[2].IsCurrent())
|
||||
assert.Equal(t, 4, pages[3].Num())
|
||||
assert.False(t, pages[3].IsCurrent())
|
||||
assertPages(t, 31, 3, 3, -1, 2, 3, 4)
|
||||
|
||||
// ... 3 4 5
|
||||
p = New(41, 10, 4, 3)
|
||||
pages = p.Pages()
|
||||
assert.Len(t, pages, 4)
|
||||
assert.Equal(t, -1, pages[0].Num())
|
||||
assert.False(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 3, pages[1].Num())
|
||||
assert.False(t, pages[1].IsCurrent())
|
||||
assert.Equal(t, 4, pages[2].Num())
|
||||
assert.True(t, pages[2].IsCurrent())
|
||||
assert.Equal(t, 5, pages[3].Num())
|
||||
assert.False(t, pages[3].IsCurrent())
|
||||
assertPages(t, 41, 4, 3, -1, 3, 4, 5)
|
||||
|
||||
// ... 4 5 6 7 8 9 10
|
||||
p = New(100, 10, 9, 7)
|
||||
pages = p.Pages()
|
||||
assert.Len(t, pages, 8)
|
||||
assert.Equal(t, -1, pages[0].Num())
|
||||
assert.False(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 4, pages[1].Num())
|
||||
assert.False(t, pages[1].IsCurrent())
|
||||
assert.Equal(t, 5, pages[2].Num())
|
||||
assert.False(t, pages[2].IsCurrent())
|
||||
assert.Equal(t, 6, pages[3].Num())
|
||||
assert.False(t, pages[3].IsCurrent())
|
||||
assert.Equal(t, 7, pages[4].Num())
|
||||
assert.False(t, pages[4].IsCurrent())
|
||||
assert.Equal(t, 8, pages[5].Num())
|
||||
assert.False(t, pages[5].IsCurrent())
|
||||
assert.Equal(t, 9, pages[6].Num())
|
||||
assert.True(t, pages[6].IsCurrent())
|
||||
assert.Equal(t, 10, pages[7].Num())
|
||||
assert.False(t, pages[7].IsCurrent())
|
||||
assertPages(t, 100, 9, 7, -1, 4, 5, 6, 7, 8, 9, 10)
|
||||
})
|
||||
|
||||
t.Run("Has more next pages", func(t *testing.T) {
|
||||
// 1 ...
|
||||
p := New(21, 10, 1, 1)
|
||||
pages := p.Pages()
|
||||
assert.Len(t, pages, 2)
|
||||
assert.Equal(t, 1, pages[0].Num())
|
||||
assert.True(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, -1, pages[1].Num())
|
||||
assert.False(t, pages[1].IsCurrent())
|
||||
assertPages(t, 21, 1, 1, 1, -1)
|
||||
|
||||
// 1 2 ...
|
||||
p = New(21, 10, 1, 2)
|
||||
pages = p.Pages()
|
||||
assert.Len(t, pages, 3)
|
||||
assert.Equal(t, 1, pages[0].Num())
|
||||
assert.True(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 2, pages[1].Num())
|
||||
assert.False(t, pages[1].IsCurrent())
|
||||
assert.Equal(t, -1, pages[2].Num())
|
||||
assert.False(t, pages[2].IsCurrent())
|
||||
assertPages(t, 21, 1, 2, 1, 2, -1)
|
||||
|
||||
// 1 2 3 ...
|
||||
p = New(31, 10, 2, 3)
|
||||
pages = p.Pages()
|
||||
assert.Len(t, pages, 4)
|
||||
assert.Equal(t, 1, pages[0].Num())
|
||||
assert.False(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 2, pages[1].Num())
|
||||
assert.True(t, pages[1].IsCurrent())
|
||||
assert.Equal(t, 3, pages[2].Num())
|
||||
assert.False(t, pages[2].IsCurrent())
|
||||
assert.Equal(t, -1, pages[3].Num())
|
||||
assert.False(t, pages[3].IsCurrent())
|
||||
assertPages(t, 31, 2, 3, 1, 2, 3, -1)
|
||||
|
||||
// 1 2 3 ...
|
||||
p = New(41, 10, 2, 3)
|
||||
pages = p.Pages()
|
||||
assert.Len(t, pages, 4)
|
||||
assert.Equal(t, 1, pages[0].Num())
|
||||
assert.False(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 2, pages[1].Num())
|
||||
assert.True(t, pages[1].IsCurrent())
|
||||
assert.Equal(t, 3, pages[2].Num())
|
||||
assert.False(t, pages[2].IsCurrent())
|
||||
assert.Equal(t, -1, pages[3].Num())
|
||||
assert.False(t, pages[3].IsCurrent())
|
||||
assertPages(t, 41, 2, 3, 1, 2, 3, -1)
|
||||
|
||||
// 1 2 3 4 5 6 7 ...
|
||||
p = New(100, 10, 1, 7)
|
||||
pages = p.Pages()
|
||||
assert.Len(t, pages, 8)
|
||||
assert.Equal(t, 1, pages[0].Num())
|
||||
assert.True(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 2, pages[1].Num())
|
||||
assert.False(t, pages[1].IsCurrent())
|
||||
assert.Equal(t, 3, pages[2].Num())
|
||||
assert.False(t, pages[2].IsCurrent())
|
||||
assert.Equal(t, 4, pages[3].Num())
|
||||
assert.False(t, pages[3].IsCurrent())
|
||||
assert.Equal(t, 5, pages[4].Num())
|
||||
assert.False(t, pages[4].IsCurrent())
|
||||
assert.Equal(t, 6, pages[5].Num())
|
||||
assert.False(t, pages[5].IsCurrent())
|
||||
assert.Equal(t, 7, pages[6].Num())
|
||||
assert.False(t, pages[6].IsCurrent())
|
||||
assert.Equal(t, -1, pages[7].Num())
|
||||
assert.False(t, pages[7].IsCurrent())
|
||||
assertPages(t, 100, 1, 7, 1, 2, 3, 4, 5, 6, 7, -1)
|
||||
|
||||
// 1 2 3 4 5 6 7 ...
|
||||
p = New(100, 10, 2, 7)
|
||||
pages = p.Pages()
|
||||
assert.Len(t, pages, 8)
|
||||
assert.Equal(t, 1, pages[0].Num())
|
||||
assert.False(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 2, pages[1].Num())
|
||||
assert.True(t, pages[1].IsCurrent())
|
||||
assert.Equal(t, 3, pages[2].Num())
|
||||
assert.False(t, pages[2].IsCurrent())
|
||||
assert.Equal(t, 4, pages[3].Num())
|
||||
assert.False(t, pages[3].IsCurrent())
|
||||
assert.Equal(t, 5, pages[4].Num())
|
||||
assert.False(t, pages[4].IsCurrent())
|
||||
assert.Equal(t, 6, pages[5].Num())
|
||||
assert.False(t, pages[5].IsCurrent())
|
||||
assert.Equal(t, 7, pages[6].Num())
|
||||
assert.False(t, pages[6].IsCurrent())
|
||||
assert.Equal(t, -1, pages[7].Num())
|
||||
assert.False(t, pages[7].IsCurrent())
|
||||
assertPages(t, 100, 2, 7, 1, 2, 3, 4, 5, 6, 7, -1)
|
||||
})
|
||||
|
||||
t.Run("Has both more previous and next pages", func(t *testing.T) {
|
||||
// ... 2 3 ...
|
||||
p := New(35, 10, 2, 2)
|
||||
pages := p.Pages()
|
||||
assert.Len(t, pages, 4)
|
||||
assert.Equal(t, -1, pages[0].Num())
|
||||
assert.False(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 2, pages[1].Num())
|
||||
assert.True(t, pages[1].IsCurrent())
|
||||
assert.Equal(t, 3, pages[2].Num())
|
||||
assert.False(t, pages[2].IsCurrent())
|
||||
assert.Equal(t, -1, pages[3].Num())
|
||||
assert.False(t, pages[3].IsCurrent())
|
||||
assertPages(t, 35, 2, 2, -1, 2, 3, -1)
|
||||
|
||||
// ... 2 3 4 ...
|
||||
p = New(49, 10, 3, 3)
|
||||
pages = p.Pages()
|
||||
assert.Len(t, pages, 5)
|
||||
assert.Equal(t, -1, pages[0].Num())
|
||||
assert.False(t, pages[0].IsCurrent())
|
||||
assert.Equal(t, 2, pages[1].Num())
|
||||
assert.False(t, pages[1].IsCurrent())
|
||||
assert.Equal(t, 3, pages[2].Num())
|
||||
assert.True(t, pages[2].IsCurrent())
|
||||
assert.Equal(t, 4, pages[3].Num())
|
||||
assert.False(t, pages[3].IsCurrent())
|
||||
assert.Equal(t, -1, pages[4].Num())
|
||||
assert.False(t, pages[4].IsCurrent())
|
||||
assertPages(t, 49, 3, 3, -1, 2, 3, 4, -1)
|
||||
})
|
||||
}
|
||||
@@ -41,29 +41,23 @@ func TestManager_AddContext(t *testing.T) {
|
||||
func TestManager_Cancel(t *testing.T) {
|
||||
pm := Manager{processMap: make(map[IDType]*process), next: 1}
|
||||
|
||||
ctx, _, finished := pm.AddContext(t.Context(), "foo")
|
||||
defer finished()
|
||||
for _, managerCancel := range []bool{true, false} {
|
||||
ctx, cancel, finished := pm.AddContext(t.Context(), "foo")
|
||||
defer finished()
|
||||
|
||||
pm.Cancel(GetPID(ctx))
|
||||
if managerCancel {
|
||||
pm.Cancel(GetPID(ctx))
|
||||
} else {
|
||||
cancel()
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
default:
|
||||
assert.FailNow(t, "Cancel should cancel the provided context")
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
default:
|
||||
assert.FailNow(t, "Cancel should cancel the provided context")
|
||||
}
|
||||
finished()
|
||||
}
|
||||
finished()
|
||||
|
||||
ctx, cancel, finished := pm.AddContext(t.Context(), "foo")
|
||||
defer finished()
|
||||
|
||||
cancel()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
default:
|
||||
assert.FailNow(t, "Cancel should cancel the provided context")
|
||||
}
|
||||
finished()
|
||||
}
|
||||
|
||||
func TestManager_Remove(t *testing.T) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package queue
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strconv"
|
||||
"sync"
|
||||
@@ -76,40 +77,32 @@ func TestWorkerPoolQueueUnhandled(t *testing.T) {
|
||||
}
|
||||
|
||||
runCount := 2 // we can run these tests even hundreds times to see its stability
|
||||
t.Run("1/1", func(t *testing.T) {
|
||||
for range runCount {
|
||||
test(t, setting.QueueSettings{BatchLength: 1, MaxWorkers: 1})
|
||||
}
|
||||
})
|
||||
t.Run("3/1", func(t *testing.T) {
|
||||
for range runCount {
|
||||
test(t, setting.QueueSettings{BatchLength: 3, MaxWorkers: 1})
|
||||
}
|
||||
})
|
||||
t.Run("4/5", func(t *testing.T) {
|
||||
for range runCount {
|
||||
test(t, setting.QueueSettings{BatchLength: 4, MaxWorkers: 5})
|
||||
}
|
||||
})
|
||||
for _, queueSetting := range []setting.QueueSettings{
|
||||
{BatchLength: 1, MaxWorkers: 1},
|
||||
{BatchLength: 3, MaxWorkers: 1},
|
||||
{BatchLength: 4, MaxWorkers: 5},
|
||||
} {
|
||||
t.Run(fmt.Sprintf("%d/%d", queueSetting.BatchLength, queueSetting.MaxWorkers), func(t *testing.T) {
|
||||
for range runCount {
|
||||
test(t, queueSetting)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorkerPoolQueuePersistence(t *testing.T) {
|
||||
runCount := 2 // we can run these tests even hundreds times to see its stability
|
||||
t.Run("1/1", func(t *testing.T) {
|
||||
for range runCount {
|
||||
testWorkerPoolQueuePersistence(t, setting.QueueSettings{BatchLength: 1, MaxWorkers: 1, Length: 100})
|
||||
}
|
||||
})
|
||||
t.Run("3/1", func(t *testing.T) {
|
||||
for range runCount {
|
||||
testWorkerPoolQueuePersistence(t, setting.QueueSettings{BatchLength: 3, MaxWorkers: 1, Length: 100})
|
||||
}
|
||||
})
|
||||
t.Run("4/5", func(t *testing.T) {
|
||||
for range runCount {
|
||||
testWorkerPoolQueuePersistence(t, setting.QueueSettings{BatchLength: 4, MaxWorkers: 5, Length: 100})
|
||||
}
|
||||
})
|
||||
for _, queueSetting := range []setting.QueueSettings{
|
||||
{BatchLength: 1, MaxWorkers: 1, Length: 100},
|
||||
{BatchLength: 3, MaxWorkers: 1, Length: 100},
|
||||
{BatchLength: 4, MaxWorkers: 5, Length: 100},
|
||||
} {
|
||||
t.Run(fmt.Sprintf("%d/%d", queueSetting.BatchLength, queueSetting.MaxWorkers), func(t *testing.T) {
|
||||
for range runCount {
|
||||
testWorkerPoolQueuePersistence(t, queueSetting)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testWorkerPoolQueuePersistence(t *testing.T, queueSetting setting.QueueSettings) {
|
||||
@@ -184,37 +177,23 @@ func TestWorkerPoolQueueActiveWorkers(t *testing.T) {
|
||||
return nil
|
||||
}
|
||||
|
||||
q, _ := newWorkerPoolQueueForTest("test-workpoolqueue", setting.QueueSettings{Type: "channel", BatchLength: 1, MaxWorkers: 1, Length: 100}, handler, false)
|
||||
stop := runWorkerPoolQueue(q)
|
||||
for i := range 5 {
|
||||
assert.NoError(t, q.Push(i))
|
||||
for _, workerCount := range []int{1, 3} {
|
||||
q, _ := newWorkerPoolQueueForTest("test-workpoolqueue", setting.QueueSettings{Type: "channel", BatchLength: 1, MaxWorkers: workerCount, Length: 100}, handler, false)
|
||||
stop := runWorkerPoolQueue(q)
|
||||
for i := range workerCount * 5 {
|
||||
assert.NoError(t, q.Push(i))
|
||||
}
|
||||
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
assert.Equal(t, workerCount, q.GetWorkerNumber())
|
||||
assert.Equal(t, workerCount, q.GetWorkerActiveNumber())
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
assert.Equal(t, workerCount, q.GetWorkerNumber())
|
||||
assert.Equal(t, 0, q.GetWorkerActiveNumber())
|
||||
time.Sleep(workerIdleDuration)
|
||||
assert.Equal(t, 1, q.GetWorkerNumber()) // there is at least one worker after the queue begins working
|
||||
stop()
|
||||
}
|
||||
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
assert.Equal(t, 1, q.GetWorkerNumber())
|
||||
assert.Equal(t, 1, q.GetWorkerActiveNumber())
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
assert.Equal(t, 1, q.GetWorkerNumber())
|
||||
assert.Equal(t, 0, q.GetWorkerActiveNumber())
|
||||
time.Sleep(workerIdleDuration)
|
||||
assert.Equal(t, 1, q.GetWorkerNumber()) // there is at least one worker after the queue begins working
|
||||
stop()
|
||||
|
||||
q, _ = newWorkerPoolQueueForTest("test-workpoolqueue", setting.QueueSettings{Type: "channel", BatchLength: 1, MaxWorkers: 3, Length: 100}, handler, false)
|
||||
stop = runWorkerPoolQueue(q)
|
||||
for i := range 15 {
|
||||
assert.NoError(t, q.Push(i))
|
||||
}
|
||||
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
assert.Equal(t, 3, q.GetWorkerNumber())
|
||||
assert.Equal(t, 3, q.GetWorkerActiveNumber())
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
assert.Equal(t, 3, q.GetWorkerNumber())
|
||||
assert.Equal(t, 0, q.GetWorkerActiveNumber())
|
||||
time.Sleep(workerIdleDuration)
|
||||
assert.Equal(t, 1, q.GetWorkerNumber()) // there is at least one worker after the queue begins working
|
||||
stop()
|
||||
}
|
||||
|
||||
func TestWorkerPoolQueueShutdown(t *testing.T) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unittest"
|
||||
"gitea.dev/modules/git"
|
||||
api "gitea.dev/modules/structs"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -52,49 +53,27 @@ func TestPushCommits_ToAPIPayloadCommits(t *testing.T) {
|
||||
assert.Len(t, payloadCommits, 3)
|
||||
assert.NotNil(t, headCommit)
|
||||
|
||||
assert.Equal(t, "69554a6", payloadCommits[0].ID)
|
||||
assert.Equal(t, "not signed commit", payloadCommits[0].Message)
|
||||
assert.Equal(t, "https://try.gitea.io/user2/repo16/commit/69554a6", payloadCommits[0].URL)
|
||||
assert.Equal(t, "User2", payloadCommits[0].Committer.Name)
|
||||
assert.Equal(t, "user2", payloadCommits[0].Committer.UserName)
|
||||
assert.Equal(t, "User2", payloadCommits[0].Author.Name)
|
||||
assert.Equal(t, "user2", payloadCommits[0].Author.UserName)
|
||||
assert.Equal(t, []string{}, payloadCommits[0].Added)
|
||||
assert.Equal(t, []string{}, payloadCommits[0].Removed)
|
||||
assert.Equal(t, []string{"readme.md"}, payloadCommits[0].Modified)
|
||||
|
||||
assert.Equal(t, "27566bd", payloadCommits[1].ID)
|
||||
assert.Equal(t, "good signed commit (with not yet validated email)", payloadCommits[1].Message)
|
||||
assert.Equal(t, "https://try.gitea.io/user2/repo16/commit/27566bd", payloadCommits[1].URL)
|
||||
assert.Equal(t, "User2", payloadCommits[1].Committer.Name)
|
||||
assert.Equal(t, "user2", payloadCommits[1].Committer.UserName)
|
||||
assert.Equal(t, "User2", payloadCommits[1].Author.Name)
|
||||
assert.Equal(t, "user2", payloadCommits[1].Author.UserName)
|
||||
assert.Equal(t, []string{}, payloadCommits[1].Added)
|
||||
assert.Equal(t, []string{}, payloadCommits[1].Removed)
|
||||
assert.Equal(t, []string{"readme.md"}, payloadCommits[1].Modified)
|
||||
|
||||
assert.Equal(t, "5099b81", payloadCommits[2].ID)
|
||||
assert.Equal(t, "good signed commit", payloadCommits[2].Message)
|
||||
assert.Equal(t, "https://try.gitea.io/user2/repo16/commit/5099b81", payloadCommits[2].URL)
|
||||
assert.Equal(t, "User2", payloadCommits[2].Committer.Name)
|
||||
assert.Equal(t, "user2", payloadCommits[2].Committer.UserName)
|
||||
assert.Equal(t, "User2", payloadCommits[2].Author.Name)
|
||||
assert.Equal(t, "user2", payloadCommits[2].Author.UserName)
|
||||
assert.Equal(t, []string{"readme.md"}, payloadCommits[2].Added)
|
||||
assert.Equal(t, []string{}, payloadCommits[2].Removed)
|
||||
assert.Equal(t, []string{}, payloadCommits[2].Modified)
|
||||
|
||||
assert.Equal(t, "69554a6", headCommit.ID)
|
||||
assert.Equal(t, "not signed commit", headCommit.Message)
|
||||
assert.Equal(t, "https://try.gitea.io/user2/repo16/commit/69554a6", headCommit.URL)
|
||||
assert.Equal(t, "User2", headCommit.Committer.Name)
|
||||
assert.Equal(t, "user2", headCommit.Committer.UserName)
|
||||
assert.Equal(t, "User2", headCommit.Author.Name)
|
||||
assert.Equal(t, "user2", headCommit.Author.UserName)
|
||||
assert.Equal(t, []string{}, headCommit.Added)
|
||||
assert.Equal(t, []string{}, headCommit.Removed)
|
||||
assert.Equal(t, []string{"readme.md"}, headCommit.Modified)
|
||||
for _, tt := range []struct {
|
||||
commit *api.PayloadCommit
|
||||
id, message, url string
|
||||
added, modified []string
|
||||
}{
|
||||
{payloadCommits[0], "69554a6", "not signed commit", "https://try.gitea.io/user2/repo16/commit/69554a6", []string{}, []string{"readme.md"}},
|
||||
{payloadCommits[1], "27566bd", "good signed commit (with not yet validated email)", "https://try.gitea.io/user2/repo16/commit/27566bd", []string{}, []string{"readme.md"}},
|
||||
{payloadCommits[2], "5099b81", "good signed commit", "https://try.gitea.io/user2/repo16/commit/5099b81", []string{"readme.md"}, []string{}},
|
||||
{headCommit, "69554a6", "not signed commit", "https://try.gitea.io/user2/repo16/commit/69554a6", []string{}, []string{"readme.md"}},
|
||||
} {
|
||||
assert.Equal(t, tt.id, tt.commit.ID)
|
||||
assert.Equal(t, tt.message, tt.commit.Message)
|
||||
assert.Equal(t, tt.url, tt.commit.URL)
|
||||
assert.Equal(t, "User2", tt.commit.Committer.Name)
|
||||
assert.Equal(t, "user2", tt.commit.Committer.UserName)
|
||||
assert.Equal(t, "User2", tt.commit.Author.Name)
|
||||
assert.Equal(t, "user2", tt.commit.Author.UserName)
|
||||
assert.Equal(t, tt.added, tt.commit.Added)
|
||||
assert.Equal(t, []string{}, tt.commit.Removed)
|
||||
assert.Equal(t, tt.modified, tt.commit.Modified)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitToPushCommit(t *testing.T) {
|
||||
|
||||
@@ -11,22 +11,17 @@ import (
|
||||
)
|
||||
|
||||
func Test_getLicense(t *testing.T) {
|
||||
type args struct {
|
||||
name string
|
||||
values *LicenseValues
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
license string
|
||||
values *LicenseValues
|
||||
want string
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "regular",
|
||||
args: args{
|
||||
name: "MIT",
|
||||
values: &LicenseValues{Owner: "Gitea", Year: "2023"},
|
||||
},
|
||||
name: "regular",
|
||||
license: "MIT",
|
||||
values: &LicenseValues{Owner: "Gitea", Year: "2023"},
|
||||
want: `MIT License
|
||||
|
||||
Copyright (c) 2023 Gitea
|
||||
@@ -35,41 +30,33 @@ Permission is hereby granted`,
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "license not found",
|
||||
args: args{
|
||||
name: "notfound",
|
||||
},
|
||||
name: "license not found",
|
||||
license: "notfound",
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := GetLicense(tt.args.name, tt.args.values)
|
||||
if !tt.wantErr(t, err, fmt.Sprintf("GetLicense(%v, %v)", tt.args.name, tt.args.values)) {
|
||||
got, err := GetLicense(tt.license, tt.values)
|
||||
if !tt.wantErr(t, err, fmt.Sprintf("GetLicense(%v, %v)", tt.license, tt.values)) {
|
||||
return
|
||||
}
|
||||
assert.Contains(t, string(got), tt.want, "GetLicense(%v, %v)", tt.args.name, tt.args.values)
|
||||
assert.Contains(t, string(got), tt.want, "GetLicense(%v, %v)", tt.license, tt.values)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_fillLicensePlaceholder(t *testing.T) {
|
||||
type args struct {
|
||||
name string
|
||||
values *LicenseValues
|
||||
origin string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
name string
|
||||
license string
|
||||
origin string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "owner",
|
||||
args: args{
|
||||
name: "regular",
|
||||
values: &LicenseValues{Year: "2023", Owner: "Gitea", Email: "teabot@gitea.io", Repo: "gitea"},
|
||||
origin: `
|
||||
name: "owner",
|
||||
license: "regular",
|
||||
origin: `
|
||||
<name of author>
|
||||
<owner>
|
||||
[NAME]
|
||||
@@ -81,7 +68,6 @@ func Test_fillLicensePlaceholder(t *testing.T) {
|
||||
<author's name or designee>
|
||||
[one or more legally recognised persons or entities offering the Work under the terms and conditions of this Licence]
|
||||
`,
|
||||
},
|
||||
want: `
|
||||
Gitea
|
||||
Gitea
|
||||
@@ -96,39 +82,31 @@ Gitea
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "email",
|
||||
args: args{
|
||||
name: "regular",
|
||||
values: &LicenseValues{Year: "2023", Owner: "Gitea", Email: "teabot@gitea.io", Repo: "gitea"},
|
||||
origin: `
|
||||
name: "email",
|
||||
license: "regular",
|
||||
origin: `
|
||||
[EMAIL]
|
||||
`,
|
||||
},
|
||||
want: `
|
||||
teabot@gitea.io
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "repo",
|
||||
args: args{
|
||||
name: "regular",
|
||||
values: &LicenseValues{Year: "2023", Owner: "Gitea", Email: "teabot@gitea.io", Repo: "gitea"},
|
||||
origin: `
|
||||
name: "repo",
|
||||
license: "regular",
|
||||
origin: `
|
||||
<program>
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
`,
|
||||
},
|
||||
want: `
|
||||
gitea
|
||||
gitea
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "year",
|
||||
args: args{
|
||||
name: "regular",
|
||||
values: &LicenseValues{Year: "2023", Owner: "Gitea", Email: "teabot@gitea.io", Repo: "gitea"},
|
||||
origin: `
|
||||
name: "year",
|
||||
license: "regular",
|
||||
origin: `
|
||||
<year>
|
||||
[YEAR]
|
||||
{YEAR}
|
||||
@@ -136,7 +114,6 @@ gitea
|
||||
[Year]
|
||||
[year]
|
||||
`,
|
||||
},
|
||||
want: `
|
||||
2023
|
||||
2023
|
||||
@@ -147,18 +124,15 @@ gitea
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "0BSD",
|
||||
args: args{
|
||||
name: "0BSD",
|
||||
values: &LicenseValues{Year: "2023", Owner: "Gitea", Email: "teabot@gitea.io", Repo: "gitea"},
|
||||
origin: `
|
||||
name: "0BSD",
|
||||
license: "0BSD",
|
||||
origin: `
|
||||
Copyright (C) YEAR by AUTHOR EMAIL
|
||||
|
||||
...
|
||||
|
||||
... THE AUTHOR BE LIABLE FOR ...
|
||||
`,
|
||||
},
|
||||
want: `
|
||||
Copyright (C) 2023 by Gitea teabot@gitea.io
|
||||
|
||||
@@ -170,7 +144,8 @@ Copyright (C) 2023 by Gitea teabot@gitea.io
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equalf(t, tt.want, string(fillLicensePlaceholder(tt.args.name, tt.args.values, []byte(tt.args.origin))), "fillLicensePlaceholder(%v, %v, %v)", tt.args.name, tt.args.values, tt.args.origin)
|
||||
values := &LicenseValues{Year: "2023", Owner: "Gitea", Email: "teabot@gitea.io", Repo: "gitea"}
|
||||
assert.Equalf(t, tt.want, string(fillLicensePlaceholder(tt.license, values, []byte(tt.origin))), "fillLicensePlaceholder(%v, %v, %v)", tt.license, values, tt.origin)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -15,89 +15,57 @@ import (
|
||||
)
|
||||
|
||||
func Test_getStorageInheritNameSectionTypeForActions(t *testing.T) {
|
||||
iniStr := `
|
||||
for _, tc := range []struct {
|
||||
iniStr, logType, artifactType string
|
||||
}{
|
||||
{`
|
||||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadActionsFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", Actions.LogStorage.Type)
|
||||
assert.Equal(t, "actions_log/", Actions.LogStorage.MinioConfig.BasePath)
|
||||
assert.EqualValues(t, "minio", Actions.ArtifactStorage.Type)
|
||||
assert.Equal(t, "actions_artifacts/", Actions.ArtifactStorage.MinioConfig.BasePath)
|
||||
|
||||
iniStr = `
|
||||
`, "minio", "minio"},
|
||||
{`
|
||||
[storage.actions_log]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadActionsFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", Actions.LogStorage.Type)
|
||||
assert.Equal(t, "actions_log/", Actions.LogStorage.MinioConfig.BasePath)
|
||||
assert.EqualValues(t, "local", Actions.ArtifactStorage.Type)
|
||||
assert.Equal(t, "actions_artifacts", filepath.Base(Actions.ArtifactStorage.Path))
|
||||
|
||||
iniStr = `
|
||||
`, "minio", "local"},
|
||||
{`
|
||||
[storage.actions_log]
|
||||
STORAGE_TYPE = my_storage
|
||||
|
||||
[storage.my_storage]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadActionsFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", Actions.LogStorage.Type)
|
||||
assert.Equal(t, "actions_log/", Actions.LogStorage.MinioConfig.BasePath)
|
||||
assert.EqualValues(t, "local", Actions.ArtifactStorage.Type)
|
||||
assert.Equal(t, "actions_artifacts", filepath.Base(Actions.ArtifactStorage.Path))
|
||||
|
||||
iniStr = `
|
||||
`, "minio", "local"},
|
||||
{`
|
||||
[storage.actions_artifacts]
|
||||
STORAGE_TYPE = my_storage
|
||||
|
||||
[storage.my_storage]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadActionsFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "local", Actions.LogStorage.Type)
|
||||
assert.Equal(t, "actions_log", filepath.Base(Actions.LogStorage.Path))
|
||||
assert.EqualValues(t, "minio", Actions.ArtifactStorage.Type)
|
||||
assert.Equal(t, "actions_artifacts/", Actions.ArtifactStorage.MinioConfig.BasePath)
|
||||
|
||||
iniStr = `
|
||||
`, "local", "minio"},
|
||||
{`
|
||||
[storage.actions_artifacts]
|
||||
STORAGE_TYPE = my_storage
|
||||
|
||||
[storage.my_storage]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadActionsFrom(cfg))
|
||||
`, "local", "minio"},
|
||||
{``, "local", "local"},
|
||||
} {
|
||||
cfg, err := NewConfigProviderFromData(tc.iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadActionsFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "local", Actions.LogStorage.Type)
|
||||
assert.Equal(t, "actions_log", filepath.Base(Actions.LogStorage.Path))
|
||||
assert.EqualValues(t, "minio", Actions.ArtifactStorage.Type)
|
||||
assert.Equal(t, "actions_artifacts/", Actions.ArtifactStorage.MinioConfig.BasePath)
|
||||
|
||||
iniStr = ``
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadActionsFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "local", Actions.LogStorage.Type)
|
||||
assert.Equal(t, "actions_log", filepath.Base(Actions.LogStorage.Path))
|
||||
assert.EqualValues(t, "local", Actions.ArtifactStorage.Type)
|
||||
assert.Equal(t, "actions_artifacts", filepath.Base(Actions.ArtifactStorage.Path))
|
||||
assert.EqualValues(t, tc.logType, Actions.LogStorage.Type)
|
||||
if tc.logType == "minio" {
|
||||
assert.Equal(t, "actions_log/", Actions.LogStorage.MinioConfig.BasePath)
|
||||
} else {
|
||||
assert.Equal(t, "actions_log", filepath.Base(Actions.LogStorage.Path))
|
||||
}
|
||||
assert.EqualValues(t, tc.artifactType, Actions.ArtifactStorage.Type)
|
||||
if tc.artifactType == "minio" {
|
||||
assert.Equal(t, "actions_artifacts/", Actions.ArtifactStorage.MinioConfig.BasePath)
|
||||
} else {
|
||||
assert.Equal(t, "actions_artifacts", filepath.Base(Actions.ArtifactStorage.Path))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_WorkflowDirs(t *testing.T) {
|
||||
|
||||
@@ -10,7 +10,10 @@ import (
|
||||
)
|
||||
|
||||
func Test_getStorageCustomType(t *testing.T) {
|
||||
iniStr := `
|
||||
for _, tc := range []struct {
|
||||
iniStr, endpoint, bucket string
|
||||
}{
|
||||
{`
|
||||
[attachment]
|
||||
STORAGE_TYPE = my_minio
|
||||
MINIO_BUCKET = gitea-attachment
|
||||
@@ -18,20 +21,8 @@ MINIO_BUCKET = gitea-attachment
|
||||
[storage.my_minio]
|
||||
STORAGE_TYPE = minio
|
||||
MINIO_ENDPOINT = my_minio:9000
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, loadAttachmentFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", Attachment.Storage.Type)
|
||||
assert.Equal(t, "my_minio:9000", Attachment.Storage.MinioConfig.Endpoint)
|
||||
assert.Equal(t, "gitea-attachment", Attachment.Storage.MinioConfig.Bucket)
|
||||
assert.Equal(t, "attachments/", Attachment.Storage.MinioConfig.BasePath)
|
||||
}
|
||||
|
||||
func Test_getStorageTypeSectionOverridesStorageSection(t *testing.T) {
|
||||
iniStr := `
|
||||
`, "my_minio:9000", "gitea-attachment"},
|
||||
{`
|
||||
[attachment]
|
||||
STORAGE_TYPE = minio
|
||||
|
||||
@@ -40,19 +31,8 @@ MINIO_BUCKET = gitea-minio
|
||||
|
||||
[storage]
|
||||
MINIO_BUCKET = gitea
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, loadAttachmentFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", Attachment.Storage.Type)
|
||||
assert.Equal(t, "gitea-minio", Attachment.Storage.MinioConfig.Bucket)
|
||||
assert.Equal(t, "attachments/", Attachment.Storage.MinioConfig.BasePath)
|
||||
}
|
||||
|
||||
func Test_getStorageSpecificOverridesStorage(t *testing.T) {
|
||||
iniStr := `
|
||||
`, "", "gitea-minio"},
|
||||
{`
|
||||
[attachment]
|
||||
STORAGE_TYPE = minio
|
||||
MINIO_BUCKET = gitea-attachment
|
||||
@@ -62,15 +42,19 @@ MINIO_BUCKET = gitea
|
||||
|
||||
[storage]
|
||||
STORAGE_TYPE = local
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
`, "", "gitea-attachment"},
|
||||
} {
|
||||
cfg, err := NewConfigProviderFromData(tc.iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadAttachmentFrom(cfg))
|
||||
|
||||
assert.NoError(t, loadAttachmentFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", Attachment.Storage.Type)
|
||||
assert.Equal(t, "gitea-attachment", Attachment.Storage.MinioConfig.Bucket)
|
||||
assert.Equal(t, "attachments/", Attachment.Storage.MinioConfig.BasePath)
|
||||
assert.EqualValues(t, "minio", Attachment.Storage.Type)
|
||||
if tc.endpoint != "" {
|
||||
assert.Equal(t, tc.endpoint, Attachment.Storage.MinioConfig.Endpoint)
|
||||
}
|
||||
assert.Equal(t, tc.bucket, Attachment.Storage.MinioConfig.Bucket)
|
||||
assert.Equal(t, "attachments/", Attachment.Storage.MinioConfig.BasePath)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getStorageGetDefaults(t *testing.T) {
|
||||
|
||||
@@ -11,22 +11,20 @@ import (
|
||||
)
|
||||
|
||||
func TestDecodeEnvSectionKey(t *testing.T) {
|
||||
ok, section, key := decodeEnvSectionKey("SEC__KEY")
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "sec", section)
|
||||
assert.Equal(t, "KEY", key)
|
||||
for _, tc := range []struct {
|
||||
input, section, key string
|
||||
}{
|
||||
{"SEC__KEY", "sec", "KEY"},
|
||||
{"sec__key", "sec", "key"},
|
||||
{"LOG_0x2E_CONSOLE__STDERR", "log.console", "STDERR"},
|
||||
} {
|
||||
ok, section, key := decodeEnvSectionKey(tc.input)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, tc.section, section)
|
||||
assert.Equal(t, tc.key, key)
|
||||
}
|
||||
|
||||
ok, section, key = decodeEnvSectionKey("sec__key")
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "sec", section)
|
||||
assert.Equal(t, "key", key)
|
||||
|
||||
ok, section, key = decodeEnvSectionKey("LOG_0x2E_CONSOLE__STDERR")
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "log.console", section)
|
||||
assert.Equal(t, "STDERR", key)
|
||||
|
||||
ok, section, key = decodeEnvSectionKey("SEC")
|
||||
ok, section, key := decodeEnvSectionKey("SEC")
|
||||
assert.False(t, ok)
|
||||
assert.Empty(t, section)
|
||||
assert.Empty(t, key)
|
||||
@@ -36,19 +34,15 @@ func TestDecodeEnvironmentKey(t *testing.T) {
|
||||
prefix := "GITEA__"
|
||||
suffix := "__FILE"
|
||||
|
||||
ok, section, key, file := decodeEnvironmentKey(prefix, suffix, "SEC__KEY")
|
||||
assert.False(t, ok)
|
||||
assert.Empty(t, section)
|
||||
assert.Empty(t, key)
|
||||
assert.False(t, file)
|
||||
for _, input := range []string{"SEC__KEY", "GITEA__SEC"} {
|
||||
ok, section, key, file := decodeEnvironmentKey(prefix, suffix, input)
|
||||
assert.False(t, ok)
|
||||
assert.Empty(t, section)
|
||||
assert.Empty(t, key)
|
||||
assert.False(t, file)
|
||||
}
|
||||
|
||||
ok, section, key, file = decodeEnvironmentKey(prefix, suffix, "GITEA__SEC")
|
||||
assert.False(t, ok)
|
||||
assert.Empty(t, section)
|
||||
assert.Empty(t, key)
|
||||
assert.False(t, file)
|
||||
|
||||
ok, section, key, file = decodeEnvironmentKey(prefix, suffix, "GITEA____KEY")
|
||||
ok, section, key, file := decodeEnvironmentKey(prefix, suffix, "GITEA____KEY")
|
||||
assert.True(t, ok)
|
||||
assert.Empty(t, section)
|
||||
assert.Equal(t, "KEY", key)
|
||||
@@ -103,20 +97,18 @@ key = old
|
||||
assert.True(t, changed)
|
||||
assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String())
|
||||
|
||||
cfg, _ = NewConfigProviderFromData("")
|
||||
_ = os.WriteFile(tmpFile, []byte("value-from-file\n"), 0o644)
|
||||
EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile})
|
||||
assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String())
|
||||
|
||||
cfg, _ = NewConfigProviderFromData("")
|
||||
_ = os.WriteFile(tmpFile, []byte("value-from-file\r\n"), 0o644)
|
||||
EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile})
|
||||
assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String())
|
||||
|
||||
cfg, _ = NewConfigProviderFromData("")
|
||||
_ = os.WriteFile(tmpFile, []byte("value-from-file\n\n"), 0o644)
|
||||
EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile})
|
||||
assert.Equal(t, "value-from-file\n", cfg.Section("sec").Key("key").String())
|
||||
for _, tc := range []struct {
|
||||
content, want string
|
||||
}{
|
||||
{"value-from-file\n", "value-from-file"},
|
||||
{"value-from-file\r\n", "value-from-file"},
|
||||
{"value-from-file\n\n", "value-from-file\n"},
|
||||
} {
|
||||
cfg, _ = NewConfigProviderFromData("")
|
||||
_ = os.WriteFile(tmpFile, []byte(tc.content), 0o644)
|
||||
EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile})
|
||||
assert.Equal(t, tc.want, cfg.Section("sec").Key("key").String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvironmentToConfigSubSecKey(t *testing.T) {
|
||||
|
||||
@@ -12,63 +12,39 @@ import (
|
||||
)
|
||||
|
||||
func TestLoadGlobalLockConfig(t *testing.T) {
|
||||
t.Run("DefaultGlobalLockConfig", func(t *testing.T) {
|
||||
defer test.MockVariableValue(&Redis)()
|
||||
iniStr := ``
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
loadRedisFrom(cfg)
|
||||
loadGlobalLockFrom(cfg)
|
||||
assert.Equal(t, "memory", GlobalLock.ServiceType)
|
||||
})
|
||||
|
||||
t.Run("RedisGlobalLockConfig", func(t *testing.T) {
|
||||
defer test.MockVariableValue(&Redis)()
|
||||
iniStr := `
|
||||
for _, tt := range []struct {
|
||||
name, config, serviceType, connStr string
|
||||
}{
|
||||
{"DefaultGlobalLockConfig", ``, "memory", ""},
|
||||
{"RedisGlobalLockConfig", `
|
||||
[global_lock]
|
||||
SERVICE_TYPE = redis
|
||||
SERVICE_CONN_STR = addrs=127.0.0.1:6379 db=0
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
loadRedisFrom(cfg)
|
||||
loadGlobalLockFrom(cfg)
|
||||
assert.Equal(t, "redis", GlobalLock.ServiceType)
|
||||
assert.Equal(t, "addrs=127.0.0.1:6379 db=0", GlobalLock.ServiceConnStr)
|
||||
})
|
||||
|
||||
t.Run("RedisGlobalLockFallsBackToSharedRedis", func(t *testing.T) {
|
||||
defer test.MockVariableValue(&Redis)()
|
||||
iniStr := `
|
||||
`, "redis", "addrs=127.0.0.1:6379 db=0"},
|
||||
{"RedisGlobalLockFallsBackToSharedRedis", `
|
||||
[redis]
|
||||
CONN_STR = redis://127.0.0.1:6379/0
|
||||
[global_lock]
|
||||
SERVICE_TYPE = redis
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
loadRedisFrom(cfg)
|
||||
loadGlobalLockFrom(cfg)
|
||||
assert.Equal(t, "redis", GlobalLock.ServiceType)
|
||||
assert.Equal(t, "redis://127.0.0.1:6379/0", GlobalLock.ServiceConnStr)
|
||||
})
|
||||
|
||||
t.Run("RedisGlobalLockOwnConnWinsOverSharedRedis", func(t *testing.T) {
|
||||
defer test.MockVariableValue(&Redis)()
|
||||
iniStr := `
|
||||
`, "redis", "redis://127.0.0.1:6379/0"},
|
||||
{"RedisGlobalLockOwnConnWinsOverSharedRedis", `
|
||||
[redis]
|
||||
CONN_STR = redis://127.0.0.1:6379/0
|
||||
[global_lock]
|
||||
SERVICE_TYPE = redis
|
||||
SERVICE_CONN_STR = redis://10.0.0.1:6379/1
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
loadRedisFrom(cfg)
|
||||
loadGlobalLockFrom(cfg)
|
||||
assert.Equal(t, "redis", GlobalLock.ServiceType)
|
||||
assert.Equal(t, "redis://10.0.0.1:6379/1", GlobalLock.ServiceConnStr)
|
||||
})
|
||||
`, "redis", "redis://10.0.0.1:6379/1"},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
defer test.MockVariableValue(&Redis)()
|
||||
cfg, err := NewConfigProviderFromData(tt.config)
|
||||
assert.NoError(t, err)
|
||||
loadRedisFrom(cfg)
|
||||
loadGlobalLockFrom(cfg)
|
||||
assert.Equal(t, tt.serviceType, GlobalLock.ServiceType)
|
||||
if tt.serviceType == "redis" {
|
||||
assert.Equal(t, tt.connStr, GlobalLock.ServiceConnStr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
+29
-55
@@ -12,82 +12,56 @@ import (
|
||||
)
|
||||
|
||||
func Test_getStorageInheritNameSectionTypeForLFS(t *testing.T) {
|
||||
iniStr := `
|
||||
for _, tt := range []struct {
|
||||
config, storageType, path string
|
||||
}{
|
||||
{`
|
||||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadLFSFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", LFS.Storage.Type)
|
||||
assert.Equal(t, "lfs/", LFS.Storage.MinioConfig.BasePath)
|
||||
|
||||
iniStr = `
|
||||
`, "minio", "lfs/"},
|
||||
{`
|
||||
[server]
|
||||
LFS_CONTENT_PATH = path_ignored
|
||||
[lfs]
|
||||
PATH = path_used
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
applyDeprecatedKeys(cfg)
|
||||
assert.NoError(t, loadLFSFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "local", LFS.Storage.Type)
|
||||
assert.Contains(t, LFS.Storage.Path, "path_used")
|
||||
|
||||
iniStr = `
|
||||
`, "local", "path_used"},
|
||||
{`
|
||||
[server]
|
||||
LFS_CONTENT_PATH = deprecatedpath
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
applyDeprecatedKeys(cfg)
|
||||
assert.NoError(t, loadLFSFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "local", LFS.Storage.Type)
|
||||
assert.Contains(t, LFS.Storage.Path, "deprecatedpath")
|
||||
|
||||
iniStr = `
|
||||
`, "local", "deprecatedpath"},
|
||||
{`
|
||||
[storage.lfs]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadLFSFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", LFS.Storage.Type)
|
||||
assert.Equal(t, "lfs/", LFS.Storage.MinioConfig.BasePath)
|
||||
|
||||
iniStr = `
|
||||
`, "minio", "lfs/"},
|
||||
{`
|
||||
[lfs]
|
||||
STORAGE_TYPE = my_minio
|
||||
|
||||
[storage.my_minio]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadLFSFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", LFS.Storage.Type)
|
||||
assert.Equal(t, "lfs/", LFS.Storage.MinioConfig.BasePath)
|
||||
|
||||
iniStr = `
|
||||
`, "minio", "lfs/"},
|
||||
{`
|
||||
[lfs]
|
||||
STORAGE_TYPE = my_minio
|
||||
MINIO_BASE_PATH = my_lfs/
|
||||
|
||||
[storage.my_minio]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadLFSFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", LFS.Storage.Type)
|
||||
assert.Equal(t, "my_lfs/", LFS.Storage.MinioConfig.BasePath)
|
||||
`, "minio", "my_lfs/"},
|
||||
} {
|
||||
cfg, err := NewConfigProviderFromData(tt.config)
|
||||
assert.NoError(t, err)
|
||||
if tt.storageType == "local" {
|
||||
applyDeprecatedKeys(cfg)
|
||||
}
|
||||
assert.NoError(t, loadLFSFrom(cfg))
|
||||
assert.EqualValues(t, tt.storageType, LFS.Storage.Type)
|
||||
if tt.storageType == "local" {
|
||||
assert.Contains(t, LFS.Storage.Path, tt.path)
|
||||
} else {
|
||||
assert.Equal(t, tt.path, LFS.Storage.MinioConfig.BasePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_LFSStorage1(t *testing.T) {
|
||||
|
||||
+23
-84
@@ -36,9 +36,6 @@ func toJSON(v any) string {
|
||||
}
|
||||
|
||||
func TestLogConfigDefault(t *testing.T) {
|
||||
manager, managerClose := initLoggersByConfig(t, ``)
|
||||
defer managerClose()
|
||||
|
||||
writerDump := `
|
||||
{
|
||||
"console": {
|
||||
@@ -57,95 +54,37 @@ func TestLogConfigDefault(t *testing.T) {
|
||||
}
|
||||
`
|
||||
|
||||
dump := manager.GetLogger(log.DEFAULT).DumpWriters()
|
||||
require.JSONEq(t, writerDump, toJSON(dump))
|
||||
|
||||
dump = manager.GetLogger("access").DumpWriters()
|
||||
require.JSONEq(t, "{}", toJSON(dump))
|
||||
|
||||
dump = manager.GetLogger("router").DumpWriters()
|
||||
require.JSONEq(t, writerDump, toJSON(dump))
|
||||
|
||||
dump = manager.GetLogger("xorm").DumpWriters()
|
||||
require.JSONEq(t, writerDump, toJSON(dump))
|
||||
}
|
||||
|
||||
func TestLogConfigDisable(t *testing.T) {
|
||||
manager, managerClose := initLoggersByConfig(t, `
|
||||
for _, tt := range []struct {
|
||||
name, config, routerDump string
|
||||
}{
|
||||
{"Default", ``, writerDump},
|
||||
{"Disable", `
|
||||
[log]
|
||||
logger.router.MODE =
|
||||
logger.xorm.MODE =
|
||||
`)
|
||||
defer managerClose()
|
||||
|
||||
writerDump := `
|
||||
{
|
||||
"console": {
|
||||
"BufferLen": 10000,
|
||||
"Colorize": false,
|
||||
"Expression": "",
|
||||
"Flags": "stdflags",
|
||||
"Level": "info",
|
||||
"Prefix": "",
|
||||
"StacktraceLevel": "none",
|
||||
"WriterOption": {
|
||||
"Stderr": false
|
||||
},
|
||||
"WriterType": "console"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
dump := manager.GetLogger(log.DEFAULT).DumpWriters()
|
||||
require.JSONEq(t, writerDump, toJSON(dump))
|
||||
|
||||
dump = manager.GetLogger("access").DumpWriters()
|
||||
require.JSONEq(t, "{}", toJSON(dump))
|
||||
|
||||
dump = manager.GetLogger("router").DumpWriters()
|
||||
require.JSONEq(t, "{}", toJSON(dump))
|
||||
|
||||
dump = manager.GetLogger("xorm").DumpWriters()
|
||||
require.JSONEq(t, "{}", toJSON(dump))
|
||||
}
|
||||
|
||||
func TestLogConfigLegacyDefault(t *testing.T) {
|
||||
manager, managerClose := initLoggersByConfig(t, `
|
||||
`, "{}"},
|
||||
{"LegacyDefault", `
|
||||
[log]
|
||||
MODE = console
|
||||
`)
|
||||
defer managerClose()
|
||||
`, writerDump},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
manager, managerClose := initLoggersByConfig(t, tt.config)
|
||||
defer managerClose()
|
||||
|
||||
writerDump := `
|
||||
{
|
||||
"console": {
|
||||
"BufferLen": 10000,
|
||||
"Colorize": false,
|
||||
"Expression": "",
|
||||
"Flags": "stdflags",
|
||||
"Level": "info",
|
||||
"Prefix": "",
|
||||
"StacktraceLevel": "none",
|
||||
"WriterOption": {
|
||||
"Stderr": false
|
||||
},
|
||||
"WriterType": "console"
|
||||
for _, logger := range []struct {
|
||||
name, expected string
|
||||
}{
|
||||
{log.DEFAULT, writerDump},
|
||||
{"access", "{}"},
|
||||
{"router", tt.routerDump},
|
||||
{"xorm", tt.routerDump},
|
||||
} {
|
||||
require.JSONEq(t, logger.expected, toJSON(manager.GetLogger(logger.name).DumpWriters()))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
dump := manager.GetLogger(log.DEFAULT).DumpWriters()
|
||||
require.JSONEq(t, writerDump, toJSON(dump))
|
||||
|
||||
dump = manager.GetLogger("access").DumpWriters()
|
||||
require.JSONEq(t, "{}", toJSON(dump))
|
||||
|
||||
dump = manager.GetLogger("router").DumpWriters()
|
||||
require.JSONEq(t, writerDump, toJSON(dump))
|
||||
|
||||
dump = manager.GetLogger("xorm").DumpWriters()
|
||||
require.JSONEq(t, writerDump, toJSON(dump))
|
||||
}
|
||||
|
||||
func TestLogConfigLegacyMode(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
|
||||
@@ -31,168 +31,98 @@ func TestMustBytes(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_getStorageInheritNameSectionTypeForPackages(t *testing.T) {
|
||||
// packages storage inherits from storage if nothing configured
|
||||
iniStr := `
|
||||
for _, testcase := range []struct {
|
||||
iniStr, basePath string
|
||||
}{
|
||||
// packages storage inherits from storage if nothing configured
|
||||
{`
|
||||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadPackagesFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", Packages.Storage.Type)
|
||||
assert.Equal(t, "packages/", Packages.Storage.MinioConfig.BasePath)
|
||||
|
||||
// we can also configure packages storage directly
|
||||
iniStr = `
|
||||
`, "packages/"},
|
||||
// we can also configure packages storage directly
|
||||
{`
|
||||
[storage.packages]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadPackagesFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", Packages.Storage.Type)
|
||||
assert.Equal(t, "packages/", Packages.Storage.MinioConfig.BasePath)
|
||||
|
||||
// or we can indicate the storage type in the packages section
|
||||
iniStr = `
|
||||
`, "packages/"},
|
||||
// or we can indicate the storage type in the packages section
|
||||
{`
|
||||
[packages]
|
||||
STORAGE_TYPE = my_minio
|
||||
|
||||
[storage.my_minio]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadPackagesFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", Packages.Storage.Type)
|
||||
assert.Equal(t, "packages/", Packages.Storage.MinioConfig.BasePath)
|
||||
|
||||
// or we can indicate the storage type and minio base path in the packages section
|
||||
iniStr = `
|
||||
`, "packages/"},
|
||||
// or we can indicate the storage type and minio base path in the packages section
|
||||
{`
|
||||
[packages]
|
||||
STORAGE_TYPE = my_minio
|
||||
MINIO_BASE_PATH = my_packages/
|
||||
|
||||
[storage.my_minio]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadPackagesFrom(cfg))
|
||||
`, "my_packages/"},
|
||||
} {
|
||||
cfg, err := NewConfigProviderFromData(testcase.iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadPackagesFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", Packages.Storage.Type)
|
||||
assert.Equal(t, "my_packages/", Packages.Storage.MinioConfig.BasePath)
|
||||
assert.EqualValues(t, "minio", Packages.Storage.Type)
|
||||
assert.Equal(t, testcase.basePath, Packages.Storage.MinioConfig.BasePath)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_PackageStorage1(t *testing.T) {
|
||||
iniStr := `
|
||||
func Test_PackageStorage(t *testing.T) {
|
||||
const storageConfig = `STORAGE_TYPE = minio
|
||||
MINIO_ENDPOINT = s3.my-domain.net
|
||||
MINIO_BUCKET = gitea
|
||||
MINIO_LOCATION = homenet
|
||||
MINIO_USE_SSL = true
|
||||
MINIO_ACCESS_KEY_ID = correct_key
|
||||
MINIO_SECRET_ACCESS_KEY = correct_key
|
||||
`
|
||||
for _, testcase := range []struct {
|
||||
iniStr, basePath string
|
||||
}{
|
||||
{`
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
[packages]
|
||||
MINIO_BASE_PATH = packages/
|
||||
SERVE_DIRECT = true
|
||||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
MINIO_ENDPOINT = s3.my-domain.net
|
||||
MINIO_BUCKET = gitea
|
||||
MINIO_LOCATION = homenet
|
||||
MINIO_USE_SSL = true
|
||||
MINIO_ACCESS_KEY_ID = correct_key
|
||||
MINIO_SECRET_ACCESS_KEY = correct_key
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, loadPackagesFrom(cfg))
|
||||
storage := Packages.Storage
|
||||
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
assert.Equal(t, "gitea", storage.MinioConfig.Bucket)
|
||||
assert.Equal(t, "packages/", storage.MinioConfig.BasePath)
|
||||
assert.True(t, storage.MinioConfig.ServeDirect)
|
||||
}
|
||||
|
||||
func Test_PackageStorage2(t *testing.T) {
|
||||
iniStr := `
|
||||
`, "packages/"},
|
||||
{`
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
[storage.packages]
|
||||
MINIO_BASE_PATH = packages/
|
||||
SERVE_DIRECT = true
|
||||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
MINIO_ENDPOINT = s3.my-domain.net
|
||||
MINIO_BUCKET = gitea
|
||||
MINIO_LOCATION = homenet
|
||||
MINIO_USE_SSL = true
|
||||
MINIO_ACCESS_KEY_ID = correct_key
|
||||
MINIO_SECRET_ACCESS_KEY = correct_key
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, loadPackagesFrom(cfg))
|
||||
storage := Packages.Storage
|
||||
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
assert.Equal(t, "gitea", storage.MinioConfig.Bucket)
|
||||
assert.Equal(t, "packages/", storage.MinioConfig.BasePath)
|
||||
assert.True(t, storage.MinioConfig.ServeDirect)
|
||||
}
|
||||
|
||||
func Test_PackageStorage3(t *testing.T) {
|
||||
iniStr := `
|
||||
`, "packages/"},
|
||||
{`
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
[packages]
|
||||
STORAGE_TYPE = my_cfg
|
||||
MINIO_BASE_PATH = my_packages/
|
||||
SERVE_DIRECT = true
|
||||
[storage.my_cfg]
|
||||
STORAGE_TYPE = minio
|
||||
MINIO_ENDPOINT = s3.my-domain.net
|
||||
MINIO_BUCKET = gitea
|
||||
MINIO_LOCATION = homenet
|
||||
MINIO_USE_SSL = true
|
||||
MINIO_ACCESS_KEY_ID = correct_key
|
||||
MINIO_SECRET_ACCESS_KEY = correct_key
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, loadPackagesFrom(cfg))
|
||||
storage := Packages.Storage
|
||||
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
assert.Equal(t, "gitea", storage.MinioConfig.Bucket)
|
||||
assert.Equal(t, "my_packages/", storage.MinioConfig.BasePath)
|
||||
assert.True(t, storage.MinioConfig.ServeDirect)
|
||||
}
|
||||
|
||||
func Test_PackageStorage4(t *testing.T) {
|
||||
iniStr := `
|
||||
`, "my_packages/"},
|
||||
{`
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
[storage.packages]
|
||||
STORAGE_TYPE = my_cfg
|
||||
MINIO_BASE_PATH = my_packages/
|
||||
SERVE_DIRECT = true
|
||||
[storage.my_cfg]
|
||||
STORAGE_TYPE = minio
|
||||
MINIO_ENDPOINT = s3.my-domain.net
|
||||
MINIO_BUCKET = gitea
|
||||
MINIO_LOCATION = homenet
|
||||
MINIO_USE_SSL = true
|
||||
MINIO_ACCESS_KEY_ID = correct_key
|
||||
MINIO_SECRET_ACCESS_KEY = correct_key
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
`, "my_packages/"},
|
||||
} {
|
||||
cfg, err := NewConfigProviderFromData(testcase.iniStr + storageConfig)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, loadPackagesFrom(cfg))
|
||||
storage := Packages.Storage
|
||||
assert.NoError(t, loadPackagesFrom(cfg))
|
||||
storage := Packages.Storage
|
||||
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
assert.Equal(t, "gitea", storage.MinioConfig.Bucket)
|
||||
assert.Equal(t, "my_packages/", storage.MinioConfig.BasePath)
|
||||
assert.True(t, storage.MinioConfig.ServeDirect)
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
assert.Equal(t, "gitea", storage.MinioConfig.Bucket)
|
||||
assert.Equal(t, testcase.basePath, storage.MinioConfig.BasePath)
|
||||
assert.True(t, storage.MinioConfig.ServeDirect)
|
||||
}
|
||||
}
|
||||
@@ -10,64 +10,49 @@ import (
|
||||
)
|
||||
|
||||
func Test_getStorageInheritNameSectionTypeForRepoArchive(t *testing.T) {
|
||||
// packages storage inherits from storage if nothing configured
|
||||
iniStr := `
|
||||
for _, tc := range []struct {
|
||||
ini, basePath string
|
||||
}{
|
||||
// packages storage inherits from storage if nothing configured
|
||||
{`
|
||||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadRepoArchiveFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", RepoArchive.Storage.Type)
|
||||
assert.Equal(t, "repo-archive/", RepoArchive.Storage.MinioConfig.BasePath)
|
||||
|
||||
// we can also configure packages storage directly
|
||||
iniStr = `
|
||||
`, "repo-archive/"},
|
||||
// we can also configure packages storage directly
|
||||
{`
|
||||
[storage.repo-archive]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadRepoArchiveFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", RepoArchive.Storage.Type)
|
||||
assert.Equal(t, "repo-archive/", RepoArchive.Storage.MinioConfig.BasePath)
|
||||
|
||||
// or we can indicate the storage type in the packages section
|
||||
iniStr = `
|
||||
`, "repo-archive/"},
|
||||
// or we can indicate the storage type in the packages section
|
||||
{`
|
||||
[repo-archive]
|
||||
STORAGE_TYPE = my_minio
|
||||
|
||||
[storage.my_minio]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadRepoArchiveFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", RepoArchive.Storage.Type)
|
||||
assert.Equal(t, "repo-archive/", RepoArchive.Storage.MinioConfig.BasePath)
|
||||
|
||||
// or we can indicate the storage type and minio base path in the packages section
|
||||
iniStr = `
|
||||
`, "repo-archive/"},
|
||||
// or we can indicate the storage type and minio base path in the packages section
|
||||
{`
|
||||
[repo-archive]
|
||||
STORAGE_TYPE = my_minio
|
||||
MINIO_BASE_PATH = my_archive/
|
||||
|
||||
[storage.my_minio]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadRepoArchiveFrom(cfg))
|
||||
`, "my_archive/"},
|
||||
} {
|
||||
cfg, err := NewConfigProviderFromData(tc.ini)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadRepoArchiveFrom(cfg))
|
||||
|
||||
assert.EqualValues(t, "minio", RepoArchive.Storage.Type)
|
||||
assert.Equal(t, "my_archive/", RepoArchive.Storage.MinioConfig.BasePath)
|
||||
assert.EqualValues(t, "minio", RepoArchive.Storage.Type)
|
||||
assert.Equal(t, tc.basePath, RepoArchive.Storage.MinioConfig.BasePath)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_RepoArchiveStorage(t *testing.T) {
|
||||
iniStr := `
|
||||
for _, ini := range []string{
|
||||
`
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
@@ -77,17 +62,8 @@ MINIO_LOCATION = homenet
|
||||
MINIO_USE_SSL = true
|
||||
MINIO_ACCESS_KEY_ID = correct_key
|
||||
MINIO_SECRET_ACCESS_KEY = correct_key
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, loadRepoArchiveFrom(cfg))
|
||||
storage := RepoArchive.Storage
|
||||
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
assert.Equal(t, "gitea", storage.MinioConfig.Bucket)
|
||||
|
||||
iniStr = `
|
||||
`,
|
||||
`
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
[storage.repo-archive]
|
||||
STORAGE_TYPE = s3
|
||||
@@ -99,13 +75,15 @@ MINIO_LOCATION = homenet
|
||||
MINIO_USE_SSL = true
|
||||
MINIO_ACCESS_KEY_ID = correct_key
|
||||
MINIO_SECRET_ACCESS_KEY = correct_key
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
`,
|
||||
} {
|
||||
cfg, err := NewConfigProviderFromData(ini)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, loadRepoArchiveFrom(cfg))
|
||||
storage = RepoArchive.Storage
|
||||
assert.NoError(t, loadRepoArchiveFrom(cfg))
|
||||
storage := RepoArchive.Storage
|
||||
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
assert.Equal(t, "gitea", storage.MinioConfig.Bucket)
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
assert.Equal(t, "gitea", storage.MinioConfig.Bucket)
|
||||
}
|
||||
}
|
||||
@@ -54,77 +54,57 @@ func TestLoadServiceVisibilityModes(t *testing.T) {
|
||||
}
|
||||
return ret
|
||||
}
|
||||
testCases := map[string]func(){
|
||||
testCases := map[string]struct {
|
||||
defaultMode structs.VisibleType
|
||||
allowedModes []structs.VisibilityString
|
||||
}{
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = public
|
||||
ALLOWED_USER_VISIBILITY_MODES = public,limited,private
|
||||
`: func() {
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, visibleTypeSlice("public", "limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`: {structs.VisibleTypePublic, []structs.VisibilityString{"public", "limited", "private"}},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = public
|
||||
`: func() {
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, visibleTypeSlice("public", "limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`: {structs.VisibleTypePublic, []structs.VisibilityString{"public", "limited", "private"}},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = limited
|
||||
`: func() {
|
||||
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, visibleTypeSlice("public", "limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`: {structs.VisibleTypeLimited, []structs.VisibilityString{"public", "limited", "private"}},
|
||||
`
|
||||
[service]
|
||||
ALLOWED_USER_VISIBILITY_MODES = public,limited,private
|
||||
`: func() {
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, visibleTypeSlice("public", "limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`: {structs.VisibleTypePublic, []structs.VisibilityString{"public", "limited", "private"}},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = public
|
||||
ALLOWED_USER_VISIBILITY_MODES = limited,private
|
||||
`: func() {
|
||||
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, visibleTypeSlice("limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`: {structs.VisibleTypeLimited, []structs.VisibilityString{"limited", "private"}},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = my_type
|
||||
ALLOWED_USER_VISIBILITY_MODES = limited,private
|
||||
`: func() {
|
||||
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, visibleTypeSlice("limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`: {structs.VisibleTypeLimited, []structs.VisibilityString{"limited", "private"}},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = my_type
|
||||
`: func() {
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, visibleTypeSlice("public", "limited", "private"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`: {structs.VisibleTypePublic, []structs.VisibilityString{"public", "limited", "private"}},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = public
|
||||
ALLOWED_USER_VISIBILITY_MODES = public, limit, privated
|
||||
`: func() {
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, visibleTypeSlice("public"), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
},
|
||||
`: {structs.VisibleTypePublic, []structs.VisibilityString{"public"}},
|
||||
}
|
||||
|
||||
for tc, fn := range testCases {
|
||||
for tc, expected := range testCases {
|
||||
t.Run(tc, func(t *testing.T) {
|
||||
Service.AllowedUserVisibilityModesSlice = []bool{true, true, true}
|
||||
Service.DefaultUserVisibilityMode = structs.VisibleTypePublic
|
||||
cfg, err := NewConfigProviderFromData(tc)
|
||||
assert.NoError(t, err)
|
||||
loadServiceFrom(cfg)
|
||||
fn()
|
||||
assert.Equal(t, expected.defaultMode, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, visibleTypeSlice(expected.allowedModes...), Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+37
-137
@@ -156,185 +156,85 @@ func testLocalStoragePath(t *testing.T, appDataPath, iniStr string, cases []test
|
||||
}
|
||||
|
||||
func Test_getStorageInheritStorageTypeLocal(t *testing.T) {
|
||||
testLocalStoragePath(t, "/appdata", `
|
||||
for _, tc := range []struct {
|
||||
name, ini, basePath, archivePath string
|
||||
}{
|
||||
{"Default", `
|
||||
[storage]
|
||||
STORAGE_TYPE = local
|
||||
`, []testLocalStoragePathCase{
|
||||
{loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"},
|
||||
{loadLFSFrom, &LFS.Storage, "/appdata/lfs"},
|
||||
{loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"},
|
||||
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
|
||||
{loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/repo-archive"},
|
||||
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
|
||||
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
|
||||
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
|
||||
})
|
||||
}
|
||||
|
||||
func Test_getStorageInheritStorageTypeLocalPath(t *testing.T) {
|
||||
testLocalStoragePath(t, "/appdata", `
|
||||
`, "/appdata", "/appdata/repo-archive"},
|
||||
{"Path", `
|
||||
[storage]
|
||||
STORAGE_TYPE = local
|
||||
PATH = /data/gitea
|
||||
`, []testLocalStoragePathCase{
|
||||
{loadAttachmentFrom, &Attachment.Storage, "/data/gitea/attachments"},
|
||||
{loadLFSFrom, &LFS.Storage, "/data/gitea/lfs"},
|
||||
{loadActionsFrom, &Actions.ArtifactStorage, "/data/gitea/actions_artifacts"},
|
||||
{loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"},
|
||||
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/repo-archive"},
|
||||
{loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"},
|
||||
{loadAvatarsFrom, &Avatar.Storage, "/data/gitea/avatars"},
|
||||
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/data/gitea/repo-avatars"},
|
||||
})
|
||||
}
|
||||
|
||||
func Test_getStorageInheritStorageTypeLocalRelativePath(t *testing.T) {
|
||||
testLocalStoragePath(t, "/appdata", `
|
||||
`, "/data/gitea", "/data/gitea/repo-archive"},
|
||||
{"RelativePath", `
|
||||
[storage]
|
||||
STORAGE_TYPE = local
|
||||
PATH = storages
|
||||
`, []testLocalStoragePathCase{
|
||||
{loadAttachmentFrom, &Attachment.Storage, "/appdata/storages/attachments"},
|
||||
{loadLFSFrom, &LFS.Storage, "/appdata/storages/lfs"},
|
||||
{loadActionsFrom, &Actions.ArtifactStorage, "/appdata/storages/actions_artifacts"},
|
||||
{loadPackagesFrom, &Packages.Storage, "/appdata/storages/packages"},
|
||||
{loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/storages/repo-archive"},
|
||||
{loadActionsFrom, &Actions.LogStorage, "/appdata/storages/actions_log"},
|
||||
{loadAvatarsFrom, &Avatar.Storage, "/appdata/storages/avatars"},
|
||||
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/storages/repo-avatars"},
|
||||
})
|
||||
}
|
||||
|
||||
func Test_getStorageInheritStorageTypeLocalPathOverride(t *testing.T) {
|
||||
testLocalStoragePath(t, "/appdata", `
|
||||
`, "/appdata/storages", "/appdata/storages/repo-archive"},
|
||||
{"PathOverride", `
|
||||
[storage]
|
||||
STORAGE_TYPE = local
|
||||
PATH = /data/gitea
|
||||
|
||||
[repo-archive]
|
||||
PATH = /data/gitea/the-archives-dir
|
||||
`, []testLocalStoragePathCase{
|
||||
{loadAttachmentFrom, &Attachment.Storage, "/data/gitea/attachments"},
|
||||
{loadLFSFrom, &LFS.Storage, "/data/gitea/lfs"},
|
||||
{loadActionsFrom, &Actions.ArtifactStorage, "/data/gitea/actions_artifacts"},
|
||||
{loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"},
|
||||
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/the-archives-dir"},
|
||||
{loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"},
|
||||
{loadAvatarsFrom, &Avatar.Storage, "/data/gitea/avatars"},
|
||||
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/data/gitea/repo-avatars"},
|
||||
})
|
||||
}
|
||||
|
||||
func Test_getStorageInheritStorageTypeLocalPathOverrideEmpty(t *testing.T) {
|
||||
testLocalStoragePath(t, "/appdata", `
|
||||
`, "/data/gitea", "/data/gitea/the-archives-dir"},
|
||||
{"PathOverrideEmpty", `
|
||||
[storage]
|
||||
STORAGE_TYPE = local
|
||||
PATH = /data/gitea
|
||||
|
||||
[repo-archive]
|
||||
`, []testLocalStoragePathCase{
|
||||
{loadAttachmentFrom, &Attachment.Storage, "/data/gitea/attachments"},
|
||||
{loadLFSFrom, &LFS.Storage, "/data/gitea/lfs"},
|
||||
{loadActionsFrom, &Actions.ArtifactStorage, "/data/gitea/actions_artifacts"},
|
||||
{loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"},
|
||||
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/repo-archive"},
|
||||
{loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"},
|
||||
{loadAvatarsFrom, &Avatar.Storage, "/data/gitea/avatars"},
|
||||
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/data/gitea/repo-avatars"},
|
||||
})
|
||||
}
|
||||
|
||||
func Test_getStorageInheritStorageTypeLocalRelativePathOverride(t *testing.T) {
|
||||
testLocalStoragePath(t, "/appdata", `
|
||||
`, "/data/gitea", "/data/gitea/repo-archive"},
|
||||
{"RelativePathOverride", `
|
||||
[storage]
|
||||
STORAGE_TYPE = local
|
||||
PATH = /data/gitea
|
||||
|
||||
[repo-archive]
|
||||
PATH = the-archives-dir
|
||||
`, []testLocalStoragePathCase{
|
||||
{loadAttachmentFrom, &Attachment.Storage, "/data/gitea/attachments"},
|
||||
{loadLFSFrom, &LFS.Storage, "/data/gitea/lfs"},
|
||||
{loadActionsFrom, &Actions.ArtifactStorage, "/data/gitea/actions_artifacts"},
|
||||
{loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"},
|
||||
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/the-archives-dir"},
|
||||
{loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"},
|
||||
{loadAvatarsFrom, &Avatar.Storage, "/data/gitea/avatars"},
|
||||
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/data/gitea/repo-avatars"},
|
||||
})
|
||||
}
|
||||
|
||||
func Test_getStorageInheritStorageTypeLocalPathOverride3(t *testing.T) {
|
||||
testLocalStoragePath(t, "/appdata", `
|
||||
`, "/data/gitea", "/data/gitea/the-archives-dir"},
|
||||
{"PathOverride3", `
|
||||
[storage.repo-archive]
|
||||
STORAGE_TYPE = local
|
||||
PATH = /data/gitea/archives
|
||||
`, []testLocalStoragePathCase{
|
||||
{loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"},
|
||||
{loadLFSFrom, &LFS.Storage, "/appdata/lfs"},
|
||||
{loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"},
|
||||
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
|
||||
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/archives"},
|
||||
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
|
||||
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
|
||||
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
|
||||
})
|
||||
}
|
||||
|
||||
func Test_getStorageInheritStorageTypeLocalPathOverride3_5(t *testing.T) {
|
||||
testLocalStoragePath(t, "/appdata", `
|
||||
`, "/appdata", "/data/gitea/archives"},
|
||||
{"PathOverride3_5", `
|
||||
[storage.repo-archive]
|
||||
STORAGE_TYPE = local
|
||||
PATH = a-relative-path
|
||||
`, []testLocalStoragePathCase{
|
||||
{loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"},
|
||||
{loadLFSFrom, &LFS.Storage, "/appdata/lfs"},
|
||||
{loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"},
|
||||
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
|
||||
{loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/a-relative-path"},
|
||||
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
|
||||
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
|
||||
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
|
||||
})
|
||||
}
|
||||
|
||||
func Test_getStorageInheritStorageTypeLocalPathOverride4(t *testing.T) {
|
||||
testLocalStoragePath(t, "/appdata", `
|
||||
`, "/appdata", "/appdata/a-relative-path"},
|
||||
{"PathOverride4", `
|
||||
[storage.repo-archive]
|
||||
STORAGE_TYPE = local
|
||||
PATH = /data/gitea/archives
|
||||
|
||||
[repo-archive]
|
||||
PATH = /tmp/gitea/archives
|
||||
`, []testLocalStoragePathCase{
|
||||
{loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"},
|
||||
{loadLFSFrom, &LFS.Storage, "/appdata/lfs"},
|
||||
{loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"},
|
||||
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
|
||||
{loadRepoArchiveFrom, &RepoArchive.Storage, "/tmp/gitea/archives"},
|
||||
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
|
||||
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
|
||||
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
|
||||
})
|
||||
}
|
||||
|
||||
func Test_getStorageInheritStorageTypeLocalPathOverride5(t *testing.T) {
|
||||
testLocalStoragePath(t, "/appdata", `
|
||||
`, "/appdata", "/tmp/gitea/archives"},
|
||||
{"PathOverride5", `
|
||||
[storage.repo-archive]
|
||||
STORAGE_TYPE = local
|
||||
PATH = /data/gitea/archives
|
||||
|
||||
[repo-archive]
|
||||
`, []testLocalStoragePathCase{
|
||||
{loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"},
|
||||
{loadLFSFrom, &LFS.Storage, "/appdata/lfs"},
|
||||
{loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"},
|
||||
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
|
||||
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/archives"},
|
||||
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
|
||||
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
|
||||
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
|
||||
})
|
||||
`, "/appdata", "/data/gitea/archives"},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
testLocalStoragePath(t, "/appdata", tc.ini, []testLocalStoragePathCase{
|
||||
{loadAttachmentFrom, &Attachment.Storage, tc.basePath + "/attachments"},
|
||||
{loadLFSFrom, &LFS.Storage, tc.basePath + "/lfs"},
|
||||
{loadActionsFrom, &Actions.ArtifactStorage, tc.basePath + "/actions_artifacts"},
|
||||
{loadPackagesFrom, &Packages.Storage, tc.basePath + "/packages"},
|
||||
{loadRepoArchiveFrom, &RepoArchive.Storage, tc.archivePath},
|
||||
{loadActionsFrom, &Actions.LogStorage, tc.basePath + "/actions_log"},
|
||||
{loadAvatarsFrom, &Avatar.Storage, tc.basePath + "/avatars"},
|
||||
{loadRepoAvatarFrom, &RepoAvatar.Storage, tc.basePath + "/repo-avatars"},
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getStorageInheritStorageTypeLocalPathOverride72(t *testing.T) {
|
||||
|
||||
+78
-139
@@ -15,151 +15,90 @@ import (
|
||||
|
||||
func TestNewSitemap(t *testing.T) {
|
||||
ts := time.Unix(1651322008, 0).UTC()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
urls []URL
|
||||
want string
|
||||
wantErr string
|
||||
for _, sitemap := range []struct {
|
||||
name string
|
||||
newSitemap func() *Sitemap
|
||||
root, entry string
|
||||
wantManyErr string
|
||||
wantSizeErr string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
urls: []URL{},
|
||||
want: xml.Header + `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">` +
|
||||
"" +
|
||||
"</urlset>\n",
|
||||
"NewSitemap", NewSitemap, "urlset", "url",
|
||||
"sitemap contains 50001 URLs, but only 50000 are allowed",
|
||||
"sitemap has 52428932 bytes, but only 52428800 are allowed",
|
||||
},
|
||||
{
|
||||
name: "regular",
|
||||
urls: []URL{
|
||||
{URL: "https://gitea.io/test1", LastMod: &ts},
|
||||
},
|
||||
want: xml.Header + `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">` +
|
||||
"<url><loc>https://gitea.io/test1</loc><lastmod>2022-04-30T12:33:28Z</lastmod></url>" +
|
||||
"</urlset>\n",
|
||||
"NewSitemapIndex", NewSitemapIndex, "sitemapindex", "sitemap",
|
||||
"sitemap contains 50001 sub-sitemaps, but only 50000 are allowed",
|
||||
"sitemap has 52428952 bytes, but only 52428800 are allowed",
|
||||
},
|
||||
{
|
||||
name: "without lastmod",
|
||||
urls: []URL{
|
||||
{URL: "https://gitea.io/test1"},
|
||||
},
|
||||
want: xml.Header + `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">` +
|
||||
"<url><loc>https://gitea.io/test1</loc></url>" +
|
||||
"</urlset>\n",
|
||||
},
|
||||
{
|
||||
name: "multiple",
|
||||
urls: []URL{
|
||||
{URL: "https://gitea.io/test1", LastMod: &ts},
|
||||
{URL: "https://gitea.io/test2", LastMod: nil},
|
||||
},
|
||||
want: xml.Header + `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">` +
|
||||
"<url><loc>https://gitea.io/test1</loc><lastmod>2022-04-30T12:33:28Z</lastmod></url>" +
|
||||
"<url><loc>https://gitea.io/test2</loc></url>" +
|
||||
"</urlset>\n",
|
||||
},
|
||||
{
|
||||
name: "too many urls",
|
||||
urls: make([]URL, 50001),
|
||||
wantErr: "sitemap contains 50001 URLs, but only 50000 are allowed",
|
||||
},
|
||||
{
|
||||
name: "too big file",
|
||||
urls: []URL{
|
||||
{URL: strings.Repeat("b", 50*1024*1024+1)},
|
||||
},
|
||||
wantErr: "sitemap has 52428932 bytes, but only 52428800 are allowed",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := NewSitemap()
|
||||
for _, url := range tt.urls {
|
||||
s.Add(url)
|
||||
} {
|
||||
t.Run(sitemap.name, func(t *testing.T) {
|
||||
entryStart, entryEnd := "<"+sitemap.entry+">", "</"+sitemap.entry+">"
|
||||
tests := []struct {
|
||||
name string
|
||||
urls []URL
|
||||
want string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
urls: []URL{},
|
||||
},
|
||||
{
|
||||
name: "regular",
|
||||
urls: []URL{
|
||||
{URL: "https://gitea.io/test1", LastMod: &ts},
|
||||
},
|
||||
want: entryStart + "<loc>https://gitea.io/test1</loc><lastmod>2022-04-30T12:33:28Z</lastmod>" + entryEnd,
|
||||
},
|
||||
{
|
||||
name: "without lastmod",
|
||||
urls: []URL{
|
||||
{URL: "https://gitea.io/test1"},
|
||||
},
|
||||
want: entryStart + "<loc>https://gitea.io/test1</loc>" + entryEnd,
|
||||
},
|
||||
{
|
||||
name: "multiple",
|
||||
urls: []URL{
|
||||
{URL: "https://gitea.io/test1", LastMod: &ts},
|
||||
{URL: "https://gitea.io/test2", LastMod: nil},
|
||||
},
|
||||
want: entryStart + "<loc>https://gitea.io/test1</loc><lastmod>2022-04-30T12:33:28Z</lastmod>" + entryEnd +
|
||||
entryStart + "<loc>https://gitea.io/test2</loc>" + entryEnd,
|
||||
},
|
||||
{
|
||||
name: "too many " + sitemap.entry + "s",
|
||||
urls: make([]URL, 50001),
|
||||
wantErr: sitemap.wantManyErr,
|
||||
},
|
||||
{
|
||||
name: "too big file",
|
||||
urls: []URL{
|
||||
{URL: strings.Repeat("b", 50*1024*1024+1)},
|
||||
},
|
||||
wantErr: sitemap.wantSizeErr,
|
||||
},
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
_, err := s.WriteTo(buf)
|
||||
if tt.wantErr != "" {
|
||||
assert.EqualError(t, err, tt.wantErr)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, tt.want, buf.String(), "NewSitemap()")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewSitemapIndex(t *testing.T) {
|
||||
ts := time.Unix(1651322008, 0).UTC()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
urls []URL
|
||||
want string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
urls: []URL{},
|
||||
want: xml.Header + `<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">` +
|
||||
"" +
|
||||
"</sitemapindex>\n",
|
||||
},
|
||||
{
|
||||
name: "regular",
|
||||
urls: []URL{
|
||||
{URL: "https://gitea.io/test1", LastMod: &ts},
|
||||
},
|
||||
want: xml.Header + `<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">` +
|
||||
"<sitemap><loc>https://gitea.io/test1</loc><lastmod>2022-04-30T12:33:28Z</lastmod></sitemap>" +
|
||||
"</sitemapindex>\n",
|
||||
},
|
||||
{
|
||||
name: "without lastmod",
|
||||
urls: []URL{
|
||||
{URL: "https://gitea.io/test1"},
|
||||
},
|
||||
want: xml.Header + `<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">` +
|
||||
"<sitemap><loc>https://gitea.io/test1</loc></sitemap>" +
|
||||
"</sitemapindex>\n",
|
||||
},
|
||||
{
|
||||
name: "multiple",
|
||||
urls: []URL{
|
||||
{URL: "https://gitea.io/test1", LastMod: &ts},
|
||||
{URL: "https://gitea.io/test2", LastMod: nil},
|
||||
},
|
||||
want: xml.Header + `<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">` +
|
||||
"<sitemap><loc>https://gitea.io/test1</loc><lastmod>2022-04-30T12:33:28Z</lastmod></sitemap>" +
|
||||
"<sitemap><loc>https://gitea.io/test2</loc></sitemap>" +
|
||||
"</sitemapindex>\n",
|
||||
},
|
||||
{
|
||||
name: "too many sitemaps",
|
||||
urls: make([]URL, 50001),
|
||||
wantErr: "sitemap contains 50001 sub-sitemaps, but only 50000 are allowed",
|
||||
},
|
||||
{
|
||||
name: "too big file",
|
||||
urls: []URL{
|
||||
{URL: strings.Repeat("b", 50*1024*1024+1)},
|
||||
},
|
||||
wantErr: "sitemap has 52428952 bytes, but only 52428800 are allowed",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := NewSitemapIndex()
|
||||
for _, url := range tt.urls {
|
||||
s.Add(url)
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
_, err := s.WriteTo(buf)
|
||||
if tt.wantErr != "" {
|
||||
assert.EqualError(t, err, tt.wantErr)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t, tt.want, buf.String(), "NewSitemapIndex()")
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := sitemap.newSitemap()
|
||||
for _, url := range tt.urls {
|
||||
s.Add(url)
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
_, err := s.WriteTo(buf)
|
||||
if tt.wantErr != "" {
|
||||
assert.EqualError(t, err, tt.wantErr)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equalf(t,
|
||||
xml.Header+"<"+sitemap.root+` xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">`+tt.want+"</"+sitemap.root+">\n",
|
||||
buf.String(), sitemap.name+"()",
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -52,18 +52,21 @@ func TestMinioCredentials(t *testing.T) {
|
||||
FakeEndpoint = "http://localhost"
|
||||
)
|
||||
|
||||
t.Run("Static Credentials", func(t *testing.T) {
|
||||
cfg := setting.MinioStorageConfig{
|
||||
AccessKeyID: ExpectedAccessKey,
|
||||
SecretAccessKey: ExpectedSecretAccessKey,
|
||||
IamEndpoint: FakeEndpoint,
|
||||
}
|
||||
checkCredentials := func(t *testing.T, cfg setting.MinioStorageConfig, suffix string) {
|
||||
creds := buildMinioCredentials(cfg)
|
||||
v, err := creds.Get()
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ExpectedAccessKey, v.AccessKeyID)
|
||||
assert.Equal(t, ExpectedSecretAccessKey, v.SecretAccessKey)
|
||||
assert.Equal(t, ExpectedAccessKey+suffix, v.AccessKeyID)
|
||||
assert.Equal(t, ExpectedSecretAccessKey+suffix, v.SecretAccessKey)
|
||||
}
|
||||
|
||||
t.Run("Static Credentials", func(t *testing.T) {
|
||||
checkCredentials(t, setting.MinioStorageConfig{
|
||||
AccessKeyID: ExpectedAccessKey,
|
||||
SecretAccessKey: ExpectedSecretAccessKey,
|
||||
IamEndpoint: FakeEndpoint,
|
||||
}, "")
|
||||
})
|
||||
|
||||
t.Run("Chain", func(t *testing.T) {
|
||||
@@ -75,24 +78,14 @@ func TestMinioCredentials(t *testing.T) {
|
||||
t.Setenv("MINIO_ACCESS_KEY", ExpectedAccessKey+"Minio")
|
||||
t.Setenv("MINIO_SECRET_KEY", ExpectedSecretAccessKey+"Minio")
|
||||
|
||||
creds := buildMinioCredentials(cfg)
|
||||
v, err := creds.Get()
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ExpectedAccessKey+"Minio", v.AccessKeyID)
|
||||
assert.Equal(t, ExpectedSecretAccessKey+"Minio", v.SecretAccessKey)
|
||||
checkCredentials(t, cfg, "Minio")
|
||||
})
|
||||
|
||||
t.Run("EnvAWS", func(t *testing.T) {
|
||||
t.Setenv("AWS_ACCESS_KEY", ExpectedAccessKey+"AWS")
|
||||
t.Setenv("AWS_SECRET_KEY", ExpectedSecretAccessKey+"AWS")
|
||||
|
||||
creds := buildMinioCredentials(cfg)
|
||||
v, err := creds.Get()
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ExpectedAccessKey+"AWS", v.AccessKeyID)
|
||||
assert.Equal(t, ExpectedSecretAccessKey+"AWS", v.SecretAccessKey)
|
||||
checkCredentials(t, cfg, "AWS")
|
||||
})
|
||||
|
||||
t.Run("FileMinio", func(t *testing.T) {
|
||||
@@ -100,12 +93,7 @@ func TestMinioCredentials(t *testing.T) {
|
||||
t.Setenv("MINIO_SHARED_CREDENTIALS_FILE", "testdata/minio.json")
|
||||
t.Setenv("AWS_SHARED_CREDENTIALS_FILE", "testdata/fake")
|
||||
|
||||
creds := buildMinioCredentials(cfg)
|
||||
v, err := creds.Get()
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ExpectedAccessKey+"MinioFile", v.AccessKeyID)
|
||||
assert.Equal(t, ExpectedSecretAccessKey+"MinioFile", v.SecretAccessKey)
|
||||
checkCredentials(t, cfg, "MinioFile")
|
||||
})
|
||||
|
||||
t.Run("FileAWS", func(t *testing.T) {
|
||||
@@ -113,12 +101,7 @@ func TestMinioCredentials(t *testing.T) {
|
||||
t.Setenv("MINIO_SHARED_CREDENTIALS_FILE", "testdata/fake.json")
|
||||
t.Setenv("AWS_SHARED_CREDENTIALS_FILE", "testdata/aws_credentials")
|
||||
|
||||
creds := buildMinioCredentials(cfg)
|
||||
v, err := creds.Get()
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ExpectedAccessKey+"AWSFile", v.AccessKeyID)
|
||||
assert.Equal(t, ExpectedSecretAccessKey+"AWSFile", v.SecretAccessKey)
|
||||
checkCredentials(t, cfg, "AWSFile")
|
||||
})
|
||||
|
||||
t.Run("IAM", func(t *testing.T) {
|
||||
@@ -139,14 +122,9 @@ func TestMinioCredentials(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
// Use the provided EC2 Instance Metadata server
|
||||
creds := buildMinioCredentials(setting.MinioStorageConfig{
|
||||
checkCredentials(t, setting.MinioStorageConfig{
|
||||
IamEndpoint: server.URL,
|
||||
})
|
||||
v, err := creds.Get()
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ExpectedAccessKey+"IAM", v.AccessKeyID)
|
||||
assert.Equal(t, ExpectedSecretAccessKey+"IAM", v.SecretAccessKey)
|
||||
}, "IAM")
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -15,37 +15,22 @@ import (
|
||||
)
|
||||
|
||||
func TestObjectStoragePath(t *testing.T) {
|
||||
base := ""
|
||||
assert.Empty(t, buildObjectStorePath(base, "/"))
|
||||
assert.Empty(t, buildObjectStorePath(base, "."))
|
||||
assert.Equal(t, "a", buildObjectStorePath(base, "/a"))
|
||||
assert.Equal(t, "a/b", buildObjectStorePath(base, "/a/b/"))
|
||||
assert.Empty(t, buildObjectStorePathPrefix(base, ""))
|
||||
assert.Equal(t, "a/", buildObjectStorePathPrefix(base, "/a/"))
|
||||
|
||||
base = "/"
|
||||
assert.Empty(t, buildObjectStorePath(base, "/"))
|
||||
assert.Empty(t, buildObjectStorePath(base, "."))
|
||||
assert.Equal(t, "a", buildObjectStorePath(base, "/a"))
|
||||
assert.Equal(t, "a/b", buildObjectStorePath(base, "/a/b/"))
|
||||
assert.Empty(t, buildObjectStorePathPrefix(base, ""))
|
||||
assert.Equal(t, "a/", buildObjectStorePathPrefix(base, "/a/"))
|
||||
|
||||
base = "/base"
|
||||
assert.Equal(t, "base", buildObjectStorePath(base, "/"))
|
||||
assert.Equal(t, "base", buildObjectStorePath(base, "."))
|
||||
assert.Equal(t, "base/a", buildObjectStorePath(base, "/a"))
|
||||
assert.Equal(t, "base/a/b", buildObjectStorePath(base, "/a/b/"))
|
||||
assert.Equal(t, "base/", buildObjectStorePathPrefix(base, ""))
|
||||
assert.Equal(t, "base/a/", buildObjectStorePathPrefix(base, "/a/"))
|
||||
|
||||
base = "/base/"
|
||||
assert.Equal(t, "base", buildObjectStorePath(base, "/"))
|
||||
assert.Equal(t, "base", buildObjectStorePath(base, "."))
|
||||
assert.Equal(t, "base/a", buildObjectStorePath(base, "/a"))
|
||||
assert.Equal(t, "base/a/b", buildObjectStorePath(base, "/a/b/"))
|
||||
assert.Equal(t, "base/", buildObjectStorePathPrefix(base, ""))
|
||||
assert.Equal(t, "base/a/", buildObjectStorePathPrefix(base, "/a/"))
|
||||
for _, base := range []string{"", "/"} {
|
||||
assert.Empty(t, buildObjectStorePath(base, "/"))
|
||||
assert.Empty(t, buildObjectStorePath(base, "."))
|
||||
assert.Equal(t, "a", buildObjectStorePath(base, "/a"))
|
||||
assert.Equal(t, "a/b", buildObjectStorePath(base, "/a/b/"))
|
||||
assert.Empty(t, buildObjectStorePathPrefix(base, ""))
|
||||
assert.Equal(t, "a/", buildObjectStorePathPrefix(base, "/a/"))
|
||||
}
|
||||
for _, base := range []string{"/base", "/base/"} {
|
||||
assert.Equal(t, "base", buildObjectStorePath(base, "/"))
|
||||
assert.Equal(t, "base", buildObjectStorePath(base, "."))
|
||||
assert.Equal(t, "base/a", buildObjectStorePath(base, "/a"))
|
||||
assert.Equal(t, "base/a/b", buildObjectStorePath(base, "/a/b/"))
|
||||
assert.Equal(t, "base/", buildObjectStorePathPrefix(base, ""))
|
||||
assert.Equal(t, "base/a/", buildObjectStorePathPrefix(base, "/a/"))
|
||||
}
|
||||
}
|
||||
|
||||
func testStorageAccess(t *testing.T, objStore ObjectStorage) {
|
||||
|
||||
@@ -12,21 +12,33 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPullRequestPayloadSynchronizeBeforeAfter(t *testing.T) {
|
||||
payload := &PullRequestPayload{
|
||||
Action: HookIssueSynchronized,
|
||||
Before: "1111111111111111111111111111111111111111",
|
||||
After: "2222222222222222222222222222222222222222",
|
||||
Index: 12,
|
||||
}
|
||||
|
||||
data, err := json.Marshal(payload)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.JSONEq(t, `{
|
||||
func TestPullRequestPayload(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
payload PullRequestPayload
|
||||
want string
|
||||
}{
|
||||
{
|
||||
payload: PullRequestPayload{
|
||||
Action: HookIssueSynchronized,
|
||||
Before: "1111111111111111111111111111111111111111",
|
||||
After: "2222222222222222222222222222222222222222",
|
||||
Index: 12,
|
||||
},
|
||||
want: `
|
||||
"action": "synchronized",
|
||||
"before": "1111111111111111111111111111111111111111",
|
||||
"after": "2222222222222222222222222222222222222222",
|
||||
"after": "2222222222222222222222222222222222222222",`,
|
||||
},
|
||||
{
|
||||
payload: PullRequestPayload{Action: HookIssueOpened, Index: 12},
|
||||
want: `
|
||||
"action": "opened",`,
|
||||
},
|
||||
} {
|
||||
t.Run(string(tt.payload.Action), func(t *testing.T) {
|
||||
data, err := json.Marshal(&tt.payload)
|
||||
require.NoError(t, err)
|
||||
assert.JSONEq(t, `{`+tt.want+`
|
||||
"number": 12,
|
||||
"commit_id": "",
|
||||
"pull_request": null,
|
||||
@@ -35,25 +47,6 @@ func TestPullRequestPayloadSynchronizeBeforeAfter(t *testing.T) {
|
||||
"review": null,
|
||||
"sender": null
|
||||
}`, string(data))
|
||||
}
|
||||
|
||||
func TestPullRequestPayloadNonSynchronizeOmitsBeforeAfter(t *testing.T) {
|
||||
payload := &PullRequestPayload{
|
||||
Action: HookIssueOpened,
|
||||
Index: 12,
|
||||
})
|
||||
}
|
||||
|
||||
data, err := json.Marshal(payload)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.JSONEq(t, `{
|
||||
"action": "opened",
|
||||
"number": 12,
|
||||
"commit_id": "",
|
||||
"pull_request": null,
|
||||
"repository": null,
|
||||
"requested_reviewer": null,
|
||||
"review": null,
|
||||
"sender": null
|
||||
}`, string(data))
|
||||
}
|
||||
@@ -46,39 +46,22 @@ func TestIssueTemplateStringSlice_UnmarshalYAML(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
content string
|
||||
tmpl *IssueTemplate
|
||||
want *IssueTemplate
|
||||
labels []string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "array",
|
||||
content: `labels: ["a", "b", "c"]`,
|
||||
tmpl: &IssueTemplate{
|
||||
Labels: []string{"should_be_overwrote"},
|
||||
},
|
||||
want: &IssueTemplate{
|
||||
Labels: []string{"a", "b", "c"},
|
||||
},
|
||||
labels: []string{"a", "b", "c"},
|
||||
},
|
||||
{
|
||||
name: "string",
|
||||
content: `labels: "a,b,c"`,
|
||||
tmpl: &IssueTemplate{
|
||||
Labels: []string{"should_be_overwrote"},
|
||||
},
|
||||
want: &IssueTemplate{
|
||||
Labels: []string{"a", "b", "c"},
|
||||
},
|
||||
labels: []string{"a", "b", "c"},
|
||||
},
|
||||
{
|
||||
name: "empty",
|
||||
content: `labels:`,
|
||||
tmpl: &IssueTemplate{
|
||||
Labels: []string{"should_be_overwrote"},
|
||||
},
|
||||
want: &IssueTemplate{
|
||||
Labels: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "error",
|
||||
@@ -87,18 +70,21 @@ labels:
|
||||
a: aa
|
||||
b: bb
|
||||
`,
|
||||
tmpl: &IssueTemplate{},
|
||||
wantErr: "yaml: construct errors: line 3: cannot unmarshal !!map into IssueTemplateStringSlice",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := yaml.Unmarshal([]byte(tt.content), tt.tmpl)
|
||||
tmpl := &IssueTemplate{}
|
||||
if tt.wantErr == "" {
|
||||
tmpl.Labels = []string{"should_be_overwrote"}
|
||||
}
|
||||
err := yaml.Unmarshal([]byte(tt.content), tmpl)
|
||||
if tt.wantErr != "" {
|
||||
assert.EqualError(t, err, tt.wantErr)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, tt.tmpl)
|
||||
assert.Equal(t, &IssueTemplate{Labels: tt.labels}, tmpl)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -15,47 +15,29 @@ import (
|
||||
)
|
||||
|
||||
func TestSubjectBodySeparator(t *testing.T) {
|
||||
test := func(input, subject, body string) {
|
||||
loc := mailSubjectSplit.FindStringIndex(input)
|
||||
for _, testCase := range []struct {
|
||||
input, subject, body string
|
||||
}{
|
||||
{"Simple\n---------------\nCase", "Simple\n", "\nCase"},
|
||||
{"Only\nBody", "", "Only\nBody"},
|
||||
{"Minimal\n---\nseparator", "Minimal\n", "\nseparator"},
|
||||
{"False --- separator", "", "False --- separator"},
|
||||
{"False\n--- separator", "", "False\n--- separator"},
|
||||
{"False ---\nseparator", "", "False ---\nseparator"},
|
||||
{"With extra spaces\n----- \t \nBody", "With extra spaces\n", "\nBody"},
|
||||
{"With leading spaces\n -------\nOnly body", "", "With leading spaces\n -------\nOnly body"},
|
||||
{"Multiple\n---\n-------\n---\nSeparators", "Multiple\n", "\n-------\n---\nSeparators"},
|
||||
{"Insufficient\n--\nSeparators", "", "Insufficient\n--\nSeparators"},
|
||||
} {
|
||||
loc := mailSubjectSplit.FindStringIndex(testCase.input)
|
||||
if loc == nil {
|
||||
assert.Empty(t, subject, "no subject found, but one expected")
|
||||
assert.Equal(t, body, input)
|
||||
assert.Empty(t, testCase.subject, "no subject found, but one expected")
|
||||
assert.Equal(t, testCase.body, testCase.input)
|
||||
} else {
|
||||
assert.Equal(t, subject, input[0:loc[0]])
|
||||
assert.Equal(t, body, input[loc[1]:])
|
||||
assert.Equal(t, testCase.subject, testCase.input[0:loc[0]])
|
||||
assert.Equal(t, testCase.body, testCase.input[loc[1]:])
|
||||
}
|
||||
}
|
||||
|
||||
test("Simple\n---------------\nCase",
|
||||
"Simple\n",
|
||||
"\nCase")
|
||||
test("Only\nBody",
|
||||
"",
|
||||
"Only\nBody")
|
||||
test("Minimal\n---\nseparator",
|
||||
"Minimal\n",
|
||||
"\nseparator")
|
||||
test("False --- separator",
|
||||
"",
|
||||
"False --- separator")
|
||||
test("False\n--- separator",
|
||||
"",
|
||||
"False\n--- separator")
|
||||
test("False ---\nseparator",
|
||||
"",
|
||||
"False ---\nseparator")
|
||||
test("With extra spaces\n----- \t \nBody",
|
||||
"With extra spaces\n",
|
||||
"\nBody")
|
||||
test("With leading spaces\n -------\nOnly body",
|
||||
"",
|
||||
"With leading spaces\n -------\nOnly body")
|
||||
test("Multiple\n---\n-------\n---\nSeparators",
|
||||
"Multiple\n",
|
||||
"\n-------\n---\nSeparators")
|
||||
test("Insufficient\n--\nSeparators",
|
||||
"",
|
||||
"Insufficient\n--\nSeparators")
|
||||
}
|
||||
|
||||
func TestSanitizeHTML(t *testing.T) {
|
||||
@@ -148,33 +130,20 @@ func TestQueryBuild(t *testing.T) {
|
||||
assert.Equal(t, "a=1&b=2&", string(QueryBuild("a=1&", "b", 2)))
|
||||
})
|
||||
|
||||
t.Run("replace", func(t *testing.T) {
|
||||
assert.Equal(t, "a=1&c=d&e=f", string(QueryBuild("a=b&c=d&e=f", "a", 1)))
|
||||
assert.Equal(t, "a=b&c=1&e=f", string(QueryBuild("a=b&c=d&e=f", "c", 1)))
|
||||
assert.Equal(t, "a=b&c=d&e=1", string(QueryBuild("a=b&c=d&e=f", "e", 1)))
|
||||
assert.Equal(t, "a=b&c=d&e=f&k=1", string(QueryBuild("a=b&c=d&e=f", "k", 1)))
|
||||
})
|
||||
|
||||
t.Run("replace-&", func(t *testing.T) {
|
||||
assert.Equal(t, "&a=1&c=d&e=f", string(QueryBuild("&a=b&c=d&e=f", "a", 1)))
|
||||
assert.Equal(t, "&a=b&c=1&e=f", string(QueryBuild("&a=b&c=d&e=f", "c", 1)))
|
||||
assert.Equal(t, "&a=b&c=d&e=1", string(QueryBuild("&a=b&c=d&e=f", "e", 1)))
|
||||
assert.Equal(t, "&a=b&c=d&e=f&k=1", string(QueryBuild("&a=b&c=d&e=f", "k", 1)))
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
assert.Equal(t, "c=d&e=f", string(QueryBuild("a=b&c=d&e=f", "a", "")))
|
||||
assert.Equal(t, "a=b&e=f", string(QueryBuild("a=b&c=d&e=f", "c", "")))
|
||||
assert.Equal(t, "a=b&c=d", string(QueryBuild("a=b&c=d&e=f", "e", "")))
|
||||
assert.Equal(t, "a=b&c=d&e=f", string(QueryBuild("a=b&c=d&e=f", "k", "")))
|
||||
})
|
||||
|
||||
t.Run("delete-&", func(t *testing.T) {
|
||||
assert.Equal(t, "&c=d&e=f", string(QueryBuild("&a=b&c=d&e=f", "a", "")))
|
||||
assert.Equal(t, "&a=b&e=f", string(QueryBuild("&a=b&c=d&e=f", "c", "")))
|
||||
assert.Equal(t, "&a=b&c=d", string(QueryBuild("&a=b&c=d&e=f", "e", "")))
|
||||
assert.Equal(t, "&a=b&c=d&e=f", string(QueryBuild("&a=b&c=d&e=f", "k", "")))
|
||||
})
|
||||
for _, prefix := range []string{"", "&"} {
|
||||
t.Run("replace"+prefix, func(t *testing.T) {
|
||||
assert.Equal(t, prefix+"a=1&c=d&e=f", string(QueryBuild(prefix+"a=b&c=d&e=f", "a", 1)))
|
||||
assert.Equal(t, prefix+"a=b&c=1&e=f", string(QueryBuild(prefix+"a=b&c=d&e=f", "c", 1)))
|
||||
assert.Equal(t, prefix+"a=b&c=d&e=1", string(QueryBuild(prefix+"a=b&c=d&e=f", "e", 1)))
|
||||
assert.Equal(t, prefix+"a=b&c=d&e=f&k=1", string(QueryBuild(prefix+"a=b&c=d&e=f", "k", 1)))
|
||||
})
|
||||
t.Run("delete"+prefix, func(t *testing.T) {
|
||||
assert.Equal(t, prefix+"c=d&e=f", string(QueryBuild(prefix+"a=b&c=d&e=f", "a", "")))
|
||||
assert.Equal(t, prefix+"a=b&e=f", string(QueryBuild(prefix+"a=b&c=d&e=f", "c", "")))
|
||||
assert.Equal(t, prefix+"a=b&c=d", string(QueryBuild(prefix+"a=b&c=d&e=f", "e", "")))
|
||||
assert.Equal(t, prefix+"a=b&c=d&e=f", string(QueryBuild(prefix+"a=b&c=d&e=f", "k", "")))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const queryNonASCII = " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" // all non-letter & non-number chars
|
||||
|
||||
@@ -39,21 +39,10 @@ func TestDateTime(t *testing.T) {
|
||||
|
||||
actual = du.FullTime(refTimeStamp)
|
||||
assert.EqualValues(t, `<relative-time weekday="" year="numeric" format="datetime" month="short" day="numeric" hour="numeric" minute="numeric" second="numeric" data-tooltip-content data-tooltip-interactive="true" datetime="2017-12-31T19:00:00-05:00">2017-12-31 19:00:00 -05:00</relative-time>`, actual)
|
||||
}
|
||||
|
||||
func TestTimeSince(t *testing.T) {
|
||||
testTz, _ := time.LoadLocation("America/New_York")
|
||||
defer test.MockVariableValue(&setting.DefaultUILocation, testTz)()
|
||||
defer test.MockVariableValue(&setting.IsProd, true)()
|
||||
defer test.MockVariableValue(&setting.IsInTesting, false)()
|
||||
|
||||
du := NewDateUtils()
|
||||
assert.EqualValues(t, "-", du.TimeSince(nil))
|
||||
|
||||
refTimeStr := "2018-01-01T00:00:00Z"
|
||||
refTime, _ := time.Parse(time.RFC3339, refTimeStr)
|
||||
|
||||
actual := du.TimeSince(refTime)
|
||||
actual = du.TimeSince(refTime)
|
||||
assert.EqualValues(t, `<relative-time prefix="" tense="past" datetime="2018-01-01T00:00:00Z" data-tooltip-content data-tooltip-interactive="true">2018-01-01 00:00:00 +00:00</relative-time>`, actual)
|
||||
|
||||
actual = timeSinceTo(&refTime, time.Time{})
|
||||
|
||||
@@ -77,40 +77,18 @@ func TestRenderRepoComment(t *testing.T) {
|
||||
}
|
||||
t.Run("RenderCommitBody", func(t *testing.T) {
|
||||
defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)()
|
||||
type args struct {
|
||||
msg string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want template.HTML
|
||||
msg string
|
||||
}{
|
||||
{
|
||||
name: "multiple lines",
|
||||
args: args{
|
||||
msg: "first line\nsecond line",
|
||||
},
|
||||
want: "second line",
|
||||
},
|
||||
{
|
||||
name: "multiple lines with leading newlines",
|
||||
args: args{
|
||||
msg: "\n\n\n\nfirst line\nsecond line",
|
||||
},
|
||||
want: "second line",
|
||||
},
|
||||
{
|
||||
name: "multiple lines with trailing newlines",
|
||||
args: args{
|
||||
msg: "first line\nsecond line\n\n\n",
|
||||
},
|
||||
want: "second line",
|
||||
},
|
||||
{"multiple lines", "first line\nsecond line"},
|
||||
{"multiple lines with leading newlines", "\n\n\n\nfirst line\nsecond line"},
|
||||
{"multiple lines with trailing newlines", "first line\nsecond line\n\n\n"},
|
||||
}
|
||||
ut := newTestRenderUtils(t)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equalf(t, tt.want, ut.RenderCommitBody(tt.args.msg, mockRepo), "RenderCommitBody(%v, %v)", tt.args.msg, nil)
|
||||
assert.Equalf(t, template.HTML("second line"), ut.RenderCommitBody(tt.msg, mockRepo), "RenderCommitBody(%v, %v)", tt.msg, nil)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -10,65 +10,36 @@ import (
|
||||
)
|
||||
|
||||
func TestDiffSliceBasic(t *testing.T) {
|
||||
// Typical integer cases
|
||||
t.Run("additions", func(t *testing.T) {
|
||||
added, removed := DiffSlice([]int{1, 2}, []int{1, 2, 3})
|
||||
assert.Equal(t, []int{3}, added)
|
||||
assert.Empty(t, removed)
|
||||
})
|
||||
|
||||
t.Run("removals", func(t *testing.T) {
|
||||
added, removed := DiffSlice([]int{1, 2, 3}, []int{1, 2})
|
||||
assert.Empty(t, added)
|
||||
assert.Equal(t, []int{3}, removed)
|
||||
})
|
||||
|
||||
t.Run("no changes", func(t *testing.T) {
|
||||
added, removed := DiffSlice([]int{1, 2}, []int{1, 2})
|
||||
assert.Empty(t, added)
|
||||
assert.Empty(t, removed)
|
||||
})
|
||||
|
||||
t.Run("empty slices", func(t *testing.T) {
|
||||
added, removed := DiffSlice([]int{}, []int{})
|
||||
assert.Empty(t, added)
|
||||
assert.Empty(t, removed)
|
||||
})
|
||||
|
||||
t.Run("overlapping elements", func(t *testing.T) {
|
||||
added, removed := DiffSlice([]int{1, 2, 4}, []int{2, 3, 4})
|
||||
assert.Equal(t, []int{3}, added)
|
||||
assert.Equal(t, []int{1}, removed)
|
||||
})
|
||||
}
|
||||
|
||||
func TestDiffSliceOrderAndDuplicates(t *testing.T) {
|
||||
oldSlice := []int{1, 2, 2, 3}
|
||||
newSlice := []int{2, 4, 2, 5}
|
||||
|
||||
added, removed := DiffSlice(oldSlice, newSlice)
|
||||
assert.Equal(t, []int{4, 5}, added)
|
||||
assert.Equal(t, []int{1, 3}, removed)
|
||||
}
|
||||
|
||||
func TestDiffSliceDeduplicatesOutput(t *testing.T) {
|
||||
// Test case from issue: newSlice contains [4, 4, 5] and oldSlice is [1]
|
||||
// added should return [4, 5], not [4, 4, 5]
|
||||
t.Run("deduplicates added", func(t *testing.T) {
|
||||
added, removed := DiffSlice([]int{1}, []int{4, 4, 5})
|
||||
assert.Equal(t, []int{4, 5}, added)
|
||||
assert.Equal(t, []int{1}, removed)
|
||||
})
|
||||
|
||||
t.Run("deduplicates removed", func(t *testing.T) {
|
||||
added, removed := DiffSlice([]int{1, 1, 2}, []int{3})
|
||||
assert.Equal(t, []int{3}, added)
|
||||
assert.Equal(t, []int{1, 2}, removed)
|
||||
})
|
||||
|
||||
t.Run("deduplicates both", func(t *testing.T) {
|
||||
added, removed := DiffSlice([]int{1, 1, 2, 2}, []int{3, 3, 4, 4})
|
||||
assert.Equal(t, []int{3, 4}, added)
|
||||
assert.Equal(t, []int{1, 2}, removed)
|
||||
})
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
oldSlice, newSlice []int
|
||||
expectedAdded, expectedRemoved []int
|
||||
}{
|
||||
// Typical integer cases
|
||||
{"additions", []int{1, 2}, []int{1, 2, 3}, []int{3}, nil},
|
||||
{"removals", []int{1, 2, 3}, []int{1, 2}, nil, []int{3}},
|
||||
{"no changes", []int{1, 2}, []int{1, 2}, nil, nil},
|
||||
{"empty slices", []int{}, []int{}, nil, nil},
|
||||
{"overlapping elements", []int{1, 2, 4}, []int{2, 3, 4}, []int{3}, []int{1}},
|
||||
{"order and duplicates", []int{1, 2, 2, 3}, []int{2, 4, 2, 5}, []int{4, 5}, []int{1, 3}},
|
||||
// Test case from issue: newSlice contains [4, 4, 5] and oldSlice is [1]
|
||||
// added should return [4, 5], not [4, 4, 5]
|
||||
{"deduplicates added", []int{1}, []int{4, 4, 5}, []int{4, 5}, []int{1}},
|
||||
{"deduplicates removed", []int{1, 1, 2}, []int{3}, []int{3}, []int{1, 2}},
|
||||
{"deduplicates both", []int{1, 1, 2, 2}, []int{3, 3, 4, 4}, []int{3, 4}, []int{1, 2}},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
added, removed := DiffSlice(testCase.oldSlice, testCase.newSlice)
|
||||
if testCase.expectedAdded == nil {
|
||||
assert.Empty(t, added)
|
||||
} else {
|
||||
assert.Equal(t, testCase.expectedAdded, added)
|
||||
}
|
||||
if testCase.expectedRemoved == nil {
|
||||
assert.Empty(t, removed)
|
||||
} else {
|
||||
assert.Equal(t, testCase.expectedRemoved, removed)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -12,24 +12,16 @@ import (
|
||||
)
|
||||
|
||||
func TestFileBackedBuffer(t *testing.T) {
|
||||
cases := []struct {
|
||||
MaxMemorySize int
|
||||
Data string
|
||||
}{
|
||||
{5, "test"},
|
||||
{5, "testtest"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
buf := New(c.MaxMemorySize, t.TempDir())
|
||||
_, err := io.Copy(buf, strings.NewReader(c.Data))
|
||||
for _, content := range []string{"test", "testtest"} {
|
||||
buf := New(5, t.TempDir())
|
||||
_, err := io.Copy(buf, strings.NewReader(content))
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, len(c.Data), buf.Size())
|
||||
assert.EqualValues(t, len(content), buf.Size())
|
||||
|
||||
data, err := io.ReadAll(buf)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, c.Data, string(data))
|
||||
assert.Equal(t, content, string(data))
|
||||
|
||||
assert.NoError(t, buf.Close())
|
||||
}
|
||||
|
||||
+15
-20
@@ -26,28 +26,23 @@ func TestReadWithLimit(t *testing.T) {
|
||||
bs := []byte("0123456789abcdef")
|
||||
|
||||
// normal test
|
||||
buf, err := readWithLimit(bytes.NewBuffer(bs), 5, 2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("01"), buf)
|
||||
|
||||
buf, err = readWithLimit(bytes.NewBuffer(bs), 5, 5)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("01234"), buf)
|
||||
|
||||
buf, err = readWithLimit(bytes.NewBuffer(bs), 5, 6)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("012345"), buf)
|
||||
|
||||
buf, err = readWithLimit(bytes.NewBuffer(bs), 5, len(bs))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("0123456789abcdef"), buf)
|
||||
|
||||
buf, err = readWithLimit(bytes.NewBuffer(bs), 5, 100)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("0123456789abcdef"), buf)
|
||||
for _, testCase := range []struct {
|
||||
limit int
|
||||
expected string
|
||||
}{
|
||||
{2, "01"},
|
||||
{5, "01234"},
|
||||
{6, "012345"},
|
||||
{len(bs), "0123456789abcdef"},
|
||||
{100, "0123456789abcdef"},
|
||||
} {
|
||||
buf, err := readWithLimit(bytes.NewBuffer(bs), 5, testCase.limit)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte(testCase.expected), buf)
|
||||
}
|
||||
|
||||
// test with error
|
||||
buf, err = readWithLimit(&readerWithError{bytes.NewBuffer(bs)}, 5, 10)
|
||||
buf, err := readWithLimit(&readerWithError{bytes.NewBuffer(bs)}, 5, 10)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("0123456789"), buf)
|
||||
|
||||
|
||||
@@ -25,11 +25,6 @@ func TestKeygen(t *testing.T) {
|
||||
|
||||
assert.Regexp(t, "^-----BEGIN RSA PRIVATE KEY-----.*", priv)
|
||||
assert.Regexp(t, "^-----BEGIN PUBLIC KEY-----.*", pub)
|
||||
}
|
||||
|
||||
func TestSignUsingKeys(t *testing.T) {
|
||||
priv, pub, err := GenerateKeyPair(2048)
|
||||
assert.NoError(t, err)
|
||||
|
||||
privPem, _ := pem.Decode([]byte(priv))
|
||||
if privPem == nil || privPem.Type != "RSA PRIVATE KEY" {
|
||||
|
||||
@@ -159,34 +159,19 @@ func TestCleanPath(t *testing.T) {
|
||||
{[]string{`a`}, `a`},
|
||||
{[]string{`/a/`}, `a`},
|
||||
{[]string{`../a/`, `../b`, `c/..`, `d`}, `a/b/d`},
|
||||
{[]string{`a\..\b`}, `a\..\b`},
|
||||
{[]string{`a`, ``, `b`}, `a/b`},
|
||||
{[]string{`a`, `..`, `b`}, `a/b`},
|
||||
{[]string{`lfs`, `repo/..`, `user/../path`}, `lfs/path`},
|
||||
}
|
||||
for _, c := range cases {
|
||||
assert.Equal(t, c.expected, PathJoinRel(c.elems...), "case: %v", c.elems)
|
||||
}
|
||||
|
||||
cases = []struct {
|
||||
elems []string
|
||||
expected string
|
||||
}{
|
||||
{[]string{}, ``},
|
||||
{[]string{``}, ``},
|
||||
{[]string{`..`}, `.`},
|
||||
{[]string{`a`}, `a`},
|
||||
{[]string{`/a/`}, `a`},
|
||||
{[]string{`../a/`, `../b`, `c/..`, `d`}, `a/b/d`},
|
||||
{[]string{`a\..\b`}, `b`},
|
||||
{[]string{`a`, ``, `b`}, `a/b`},
|
||||
{[]string{`a`, `..`, `b`}, `a/b`},
|
||||
{[]string{`lfs`, `repo/..`, `user/../path`}, `lfs/path`},
|
||||
}
|
||||
for _, c := range cases {
|
||||
assert.Equal(t, c.expected, PathJoinRelX(c.elems...), "case: %v", c.elems)
|
||||
}
|
||||
|
||||
backslashPath := []string{`a\..\b`}
|
||||
assert.Equal(t, `a\..\b`, PathJoinRel(backslashPath...), "case: %v", backslashPath)
|
||||
assert.Equal(t, `b`, PathJoinRelX(backslashPath...), "case: %v", backslashPath)
|
||||
|
||||
// for POSIX only, but the result is similar on Windows, because the first element must be an absolute path
|
||||
if consts.IsWindows {
|
||||
cases = []struct {
|
||||
|
||||
@@ -27,7 +27,6 @@ func TestSliceSortedEqual(t *testing.T) {
|
||||
assert.True(t, SliceSortedEqual([]int{}, []int{}))
|
||||
assert.True(t, SliceSortedEqual([]int(nil), nil))
|
||||
assert.True(t, SliceSortedEqual([]int(nil), []int{}))
|
||||
assert.True(t, SliceSortedEqual([]int{}, []int{}))
|
||||
|
||||
assert.True(t, SliceSortedEqual([]string{"2", "0", "2", "3"}, []string{"2", "0", "2", "3"}))
|
||||
assert.True(t, SliceSortedEqual([]float64{2, 0, 2, 3}, []float64{2, 0, 2, 3}))
|
||||
@@ -47,7 +46,6 @@ func TestSliceRemoveAll(t *testing.T) {
|
||||
assert.ElementsMatch(t, []int{2, 0, 2, 3}, SliceRemoveAll([]int{2, 0, 2, 3}, 4))
|
||||
assert.Empty(t, SliceRemoveAll([]int{}, 0))
|
||||
assert.ElementsMatch(t, []int(nil), SliceRemoveAll([]int(nil), 0))
|
||||
assert.Empty(t, SliceRemoveAll([]int{}, 0))
|
||||
|
||||
assert.ElementsMatch(t, []string{"2", "2", "3"}, SliceRemoveAll([]string{"2", "0", "2", "3"}, "0"))
|
||||
assert.ElementsMatch(t, []float64{2, 2, 3}, SliceRemoveAll([]float64{2, 0, 2, 3}, 0))
|
||||
|
||||
+25
-34
@@ -10,40 +10,31 @@ import (
|
||||
)
|
||||
|
||||
func TestOnceValue(t *testing.T) {
|
||||
t.Run("RepeatCall", func(t *testing.T) {
|
||||
callCount := 0
|
||||
o := OnceValue[int]{Func: func() int {
|
||||
callCount++
|
||||
return 42
|
||||
}}
|
||||
assert.Equal(t, 42, o.Value())
|
||||
assert.Equal(t, 42, o.Value())
|
||||
assert.Equal(t, 1, callCount)
|
||||
o.Reset()
|
||||
assert.Equal(t, 42, o.Value())
|
||||
assert.Equal(t, 2, callCount)
|
||||
assert.Equal(t, 42, o.Value())
|
||||
assert.Equal(t, 2, callCount)
|
||||
})
|
||||
|
||||
t.Run("Panic", func(t *testing.T) {
|
||||
callCount := 0
|
||||
doPanic := true
|
||||
o := OnceValue[int]{Func: func() int {
|
||||
callCount++
|
||||
for _, name := range []string{"RepeatCall", "Panic"} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
callCount := 0
|
||||
doPanic := name == "Panic"
|
||||
o := OnceValue[int]{Func: func() int {
|
||||
callCount++
|
||||
if doPanic {
|
||||
panic("some error")
|
||||
}
|
||||
return 42
|
||||
}}
|
||||
if doPanic {
|
||||
panic("some error")
|
||||
assert.PanicsWithValue(t, "some error", func() { o.Value() })
|
||||
assert.PanicsWithValue(t, "some error", func() { o.Value() })
|
||||
} else {
|
||||
assert.Equal(t, 42, o.Value())
|
||||
assert.Equal(t, 42, o.Value())
|
||||
}
|
||||
return 42
|
||||
}}
|
||||
assert.PanicsWithValue(t, "some error", func() { o.Value() })
|
||||
assert.PanicsWithValue(t, "some error", func() { o.Value() })
|
||||
assert.Equal(t, 1, callCount)
|
||||
doPanic = false
|
||||
o.Reset()
|
||||
assert.Equal(t, 42, o.Value())
|
||||
assert.Equal(t, 2, callCount)
|
||||
assert.Equal(t, 42, o.Value())
|
||||
assert.Equal(t, 2, callCount)
|
||||
})
|
||||
assert.Equal(t, 1, callCount)
|
||||
doPanic = false
|
||||
o.Reset()
|
||||
assert.Equal(t, 42, o.Value())
|
||||
assert.Equal(t, 2, callCount)
|
||||
assert.Equal(t, 42, o.Value())
|
||||
assert.Equal(t, 2, callCount)
|
||||
})
|
||||
}
|
||||
}
|
||||
+10
-29
@@ -40,26 +40,13 @@ func Test_NormalizeEOL(t *testing.T) {
|
||||
"Ends without EOLtoo.",
|
||||
}
|
||||
|
||||
buildEOLData := func(data []string, eol string) []byte {
|
||||
return []byte(strings.Join(data, eol))
|
||||
for _, data := range [][]string{data1, data2} {
|
||||
unix := []byte(strings.Join(data, "\n"))
|
||||
for _, input := range [][]byte{[]byte(strings.Join(data, "\r\n")), []byte(strings.Join(data, "\r")), unix} {
|
||||
assert.Equal(t, unix, NormalizeEOL(input))
|
||||
}
|
||||
}
|
||||
|
||||
dos := buildEOLData(data1, "\r\n")
|
||||
unix := buildEOLData(data1, "\n")
|
||||
mac := buildEOLData(data1, "\r")
|
||||
|
||||
assert.Equal(t, unix, NormalizeEOL(dos))
|
||||
assert.Equal(t, unix, NormalizeEOL(mac))
|
||||
assert.Equal(t, unix, NormalizeEOL(unix))
|
||||
|
||||
dos = buildEOLData(data2, "\r\n")
|
||||
unix = buildEOLData(data2, "\n")
|
||||
mac = buildEOLData(data2, "\r")
|
||||
|
||||
assert.Equal(t, unix, NormalizeEOL(dos))
|
||||
assert.Equal(t, unix, NormalizeEOL(mac))
|
||||
assert.Equal(t, unix, NormalizeEOL(unix))
|
||||
|
||||
assert.Equal(t, []byte("one liner"), NormalizeEOL([]byte("one liner")))
|
||||
assert.Equal(t, []byte("\n"), NormalizeEOL([]byte("\n")))
|
||||
assert.Equal(t, []byte("\ntwo liner"), NormalizeEOL([]byte("\ntwo liner")))
|
||||
@@ -103,17 +90,11 @@ func Test_RandomString(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_RandomBytes(t *testing.T) {
|
||||
bytes1 := CryptoRandomBytes(32)
|
||||
|
||||
bytes2 := CryptoRandomBytes(32)
|
||||
|
||||
assert.NotEqual(t, bytes1, bytes2)
|
||||
|
||||
bytes3 := CryptoRandomBytes(256)
|
||||
|
||||
bytes4 := CryptoRandomBytes(256)
|
||||
|
||||
assert.NotEqual(t, bytes3, bytes4)
|
||||
for _, length := range []int64{32, 256} {
|
||||
bytes1 := CryptoRandomBytes(length)
|
||||
bytes2 := CryptoRandomBytes(length)
|
||||
assert.NotEqual(t, bytes1, bytes2)
|
||||
}
|
||||
}
|
||||
|
||||
// Test case for any function which accepts and returns a single string.
|
||||
|
||||
@@ -8,249 +8,33 @@ import (
|
||||
)
|
||||
|
||||
func Test_GitRefNameValidation(t *testing.T) {
|
||||
gitRefNameValidationTestCases := []validationTestCase{
|
||||
{
|
||||
description: "Reference name contains only characters",
|
||||
data: &TestForm{
|
||||
BranchName: "test",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name contains single slash",
|
||||
data: &TestForm{
|
||||
BranchName: "feature/test",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name has allowed special characters",
|
||||
data: &TestForm{
|
||||
BranchName: "debian/1%1.6.0-2",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name contains backslash",
|
||||
data: &TestForm{
|
||||
BranchName: "feature\\test",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name starts with dot",
|
||||
data: &TestForm{
|
||||
BranchName: ".test",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name ends with dot",
|
||||
data: &TestForm{
|
||||
BranchName: "test.",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name starts with slash",
|
||||
data: &TestForm{
|
||||
BranchName: "/test",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name ends with slash",
|
||||
data: &TestForm{
|
||||
BranchName: "test/",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name ends with .lock",
|
||||
data: &TestForm{
|
||||
BranchName: "test.lock",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name contains multiple consecutive dots",
|
||||
data: &TestForm{
|
||||
BranchName: "te..st",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name contains multiple consecutive slashes",
|
||||
data: &TestForm{
|
||||
BranchName: "te//st",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name is single @",
|
||||
data: &TestForm{
|
||||
BranchName: "@",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name has @{",
|
||||
data: &TestForm{
|
||||
BranchName: "branch@{",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character ~",
|
||||
data: &TestForm{
|
||||
BranchName: "~debian/1%1.6.0-2",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character *",
|
||||
data: &TestForm{
|
||||
BranchName: "*debian/1%1.6.0-2",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character ?",
|
||||
data: &TestForm{
|
||||
BranchName: "?debian/1%1.6.0-2",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character ^",
|
||||
data: &TestForm{
|
||||
BranchName: "^debian/1%1.6.0-2",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character :",
|
||||
data: &TestForm{
|
||||
BranchName: "debian:jessie",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character (whitespace)",
|
||||
data: &TestForm{
|
||||
BranchName: "debian jessie",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character [",
|
||||
data: &TestForm{
|
||||
BranchName: "debian[jessie",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range gitRefNameValidationTestCases {
|
||||
expectedErrors := BindingErrors{{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
}}
|
||||
for _, testCase := range []validationTestCase{
|
||||
{"Reference name contains only characters", &TestForm{BranchName: "test"}, nil},
|
||||
{"Reference name contains single slash", &TestForm{BranchName: "feature/test"}, nil},
|
||||
{"Reference name has allowed special characters", &TestForm{BranchName: "debian/1%1.6.0-2"}, nil},
|
||||
{"Reference name contains backslash", &TestForm{BranchName: "feature\\test"}, expectedErrors},
|
||||
{"Reference name starts with dot", &TestForm{BranchName: ".test"}, expectedErrors},
|
||||
{"Reference name ends with dot", &TestForm{BranchName: "test."}, expectedErrors},
|
||||
{"Reference name starts with slash", &TestForm{BranchName: "/test"}, expectedErrors},
|
||||
{"Reference name ends with slash", &TestForm{BranchName: "test/"}, expectedErrors},
|
||||
{"Reference name ends with .lock", &TestForm{BranchName: "test.lock"}, expectedErrors},
|
||||
{"Reference name contains multiple consecutive dots", &TestForm{BranchName: "te..st"}, expectedErrors},
|
||||
{"Reference name contains multiple consecutive slashes", &TestForm{BranchName: "te//st"}, expectedErrors},
|
||||
{"Reference name is single @", &TestForm{BranchName: "@"}, expectedErrors},
|
||||
{"Reference name has @{", &TestForm{BranchName: "branch@{"}, expectedErrors},
|
||||
{"Reference name has unallowed special character ~", &TestForm{BranchName: "~debian/1%1.6.0-2"}, expectedErrors},
|
||||
{"Reference name has unallowed special character *", &TestForm{BranchName: "*debian/1%1.6.0-2"}, expectedErrors},
|
||||
{"Reference name has unallowed special character ?", &TestForm{BranchName: "?debian/1%1.6.0-2"}, expectedErrors},
|
||||
{"Reference name has unallowed special character ^", &TestForm{BranchName: "^debian/1%1.6.0-2"}, expectedErrors},
|
||||
{"Reference name has unallowed special character :", &TestForm{BranchName: "debian:jessie"}, expectedErrors},
|
||||
{"Reference name has unallowed special character (whitespace)", &TestForm{BranchName: "debian jessie"}, expectedErrors},
|
||||
{"Reference name has unallowed special character [", &TestForm{BranchName: "debian[jessie"}, expectedErrors},
|
||||
} {
|
||||
t.Run(testCase.description, func(t *testing.T) {
|
||||
performValidationTest(t, testCase)
|
||||
})
|
||||
|
||||
@@ -8,92 +8,22 @@ import (
|
||||
)
|
||||
|
||||
func Test_ValidURLValidation(t *testing.T) {
|
||||
urlValidationTestCases := []validationTestCase{
|
||||
{
|
||||
description: "Empty URL",
|
||||
data: &TestForm{
|
||||
URL: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "URL without port",
|
||||
data: &TestForm{
|
||||
URL: "http://test.lan/",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "URL with port",
|
||||
data: &TestForm{
|
||||
URL: "http://test.lan:3000/",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "URL with IPv6 address without port",
|
||||
data: &TestForm{
|
||||
URL: "http://[::1]/",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "URL with IPv6 address with port",
|
||||
data: &TestForm{
|
||||
URL: "http://[::1]:3000/",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Invalid URL",
|
||||
data: &TestForm{
|
||||
URL: "http//test.lan/",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"URL"},
|
||||
Classification: "UrlError",
|
||||
Message: "Url",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Invalid schema",
|
||||
data: &TestForm{
|
||||
URL: "ftp://test.lan/",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"URL"},
|
||||
Classification: "UrlError",
|
||||
Message: "Url",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Invalid port",
|
||||
data: &TestForm{
|
||||
URL: "http://test.lan:3x4/",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"URL"},
|
||||
Classification: "UrlError",
|
||||
Message: "Url",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Invalid port with IPv6 address",
|
||||
data: &TestForm{
|
||||
URL: "http://[::1]:3x4/",
|
||||
},
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"URL"},
|
||||
Classification: "UrlError",
|
||||
Message: "Url",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range urlValidationTestCases {
|
||||
expectedErrors := BindingErrors{{
|
||||
FieldNames: []string{"URL"},
|
||||
Classification: "UrlError",
|
||||
Message: "Url",
|
||||
}}
|
||||
for _, testCase := range []validationTestCase{
|
||||
{"Empty URL", &TestForm{URL: ""}, nil},
|
||||
{"URL without port", &TestForm{URL: "http://test.lan/"}, nil},
|
||||
{"URL with port", &TestForm{URL: "http://test.lan:3000/"}, nil},
|
||||
{"URL with IPv6 address without port", &TestForm{URL: "http://[::1]/"}, nil},
|
||||
{"URL with IPv6 address with port", &TestForm{URL: "http://[::1]:3000/"}, nil},
|
||||
{"Invalid URL", &TestForm{URL: "http//test.lan/"}, expectedErrors},
|
||||
{"Invalid schema", &TestForm{URL: "ftp://test.lan/"}, expectedErrors},
|
||||
{"Invalid port", &TestForm{URL: "http://test.lan:3x4/"}, expectedErrors},
|
||||
{"Invalid port with IPv6 address", &TestForm{URL: "http://[::1]:3x4/"}, expectedErrors},
|
||||
} {
|
||||
t.Run(testCase.description, func(t *testing.T) {
|
||||
performValidationTest(t, testCase)
|
||||
})
|
||||
|
||||
@@ -28,43 +28,31 @@ func TestRouteMock(t *testing.T) {
|
||||
}
|
||||
r.Get("/foo", middleware1, RouterMockPoint("mock-point"), middleware2, handler)
|
||||
|
||||
// normal request
|
||||
recorder := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, "http://localhost:8000/foo", nil)
|
||||
assert.NoError(t, err)
|
||||
r.ServeHTTP(recorder, req)
|
||||
assert.Len(t, recorder.Header(), 3)
|
||||
assert.Equal(t, "m1", recorder.Header().Get("X-Test-Middleware1"))
|
||||
assert.Equal(t, "m2", recorder.Header().Get("X-Test-Middleware2"))
|
||||
assert.Equal(t, "h", recorder.Header().Get("X-Test-Handler"))
|
||||
RouteMockReset()
|
||||
|
||||
// mock at "mock-point"
|
||||
RouteMock("mock-point", func(resp http.ResponseWriter, req *http.Request) {
|
||||
resp.Header().Set("X-Test-MockPoint", "a")
|
||||
resp.WriteHeader(http.StatusOK)
|
||||
})
|
||||
recorder = httptest.NewRecorder()
|
||||
req, err = http.NewRequest(http.MethodGet, "http://localhost:8000/foo", nil)
|
||||
assert.NoError(t, err)
|
||||
r.ServeHTTP(recorder, req)
|
||||
assert.Len(t, recorder.Header(), 2)
|
||||
assert.Equal(t, "m1", recorder.Header().Get("X-Test-Middleware1"))
|
||||
assert.Equal(t, "a", recorder.Header().Get("X-Test-MockPoint"))
|
||||
RouteMockReset()
|
||||
|
||||
// mock at MockAfterMiddlewares
|
||||
RouteMock(MockAfterMiddlewares, func(resp http.ResponseWriter, req *http.Request) {
|
||||
resp.Header().Set("X-Test-MockPoint", "b")
|
||||
resp.WriteHeader(http.StatusOK)
|
||||
})
|
||||
recorder = httptest.NewRecorder()
|
||||
req, err = http.NewRequest(http.MethodGet, "http://localhost:8000/foo", nil)
|
||||
assert.NoError(t, err)
|
||||
r.ServeHTTP(recorder, req)
|
||||
assert.Len(t, recorder.Header(), 3)
|
||||
assert.Equal(t, "m1", recorder.Header().Get("X-Test-Middleware1"))
|
||||
assert.Equal(t, "m2", recorder.Header().Get("X-Test-Middleware2"))
|
||||
assert.Equal(t, "b", recorder.Header().Get("X-Test-MockPoint"))
|
||||
RouteMockReset()
|
||||
for _, tc := range []struct {
|
||||
mockPoint, mockValue string
|
||||
headers [][2]string
|
||||
}{
|
||||
// normal request
|
||||
{headers: [][2]string{{"X-Test-Middleware1", "m1"}, {"X-Test-Middleware2", "m2"}, {"X-Test-Handler", "h"}}},
|
||||
// mock at "mock-point"
|
||||
{mockPoint: "mock-point", mockValue: "a", headers: [][2]string{{"X-Test-Middleware1", "m1"}, {"X-Test-MockPoint", "a"}}},
|
||||
// mock at MockAfterMiddlewares
|
||||
{mockPoint: MockAfterMiddlewares, mockValue: "b", headers: [][2]string{{"X-Test-Middleware1", "m1"}, {"X-Test-Middleware2", "m2"}, {"X-Test-MockPoint", "b"}}},
|
||||
} {
|
||||
if tc.mockPoint != "" {
|
||||
RouteMock(tc.mockPoint, func(resp http.ResponseWriter, req *http.Request) {
|
||||
resp.Header().Set("X-Test-MockPoint", tc.mockValue)
|
||||
resp.WriteHeader(http.StatusOK)
|
||||
})
|
||||
}
|
||||
recorder := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, "http://localhost:8000/foo", nil)
|
||||
assert.NoError(t, err)
|
||||
r.ServeHTTP(recorder, req)
|
||||
assert.Len(t, recorder.Header(), len(tc.headers))
|
||||
for _, header := range tc.headers {
|
||||
assert.Equal(t, header[1], recorder.Header().Get(header[0]))
|
||||
}
|
||||
RouteMockReset()
|
||||
}
|
||||
}
|
||||
+12
-24
@@ -208,30 +208,18 @@ func TestRouter(t *testing.T) {
|
||||
method: "GET",
|
||||
handlerMarks: []string{"not-found:/api/v1"},
|
||||
})
|
||||
testRoute(t, "GET /api/v1/repos/the-user/the-repo/branches", resultStruct{
|
||||
method: "GET",
|
||||
pathParams: map[string]string{"username": "the-user", "reponame": "the-repo"},
|
||||
})
|
||||
|
||||
testRoute(t, "POST /api/v1/repos/the-user/the-repo/branches", resultStruct{
|
||||
method: "POST",
|
||||
pathParams: map[string]string{"username": "the-user", "reponame": "the-repo"},
|
||||
})
|
||||
|
||||
testRoute(t, "GET /api/v1/repos/the-user/the-repo/branches/master", resultStruct{
|
||||
method: "GET",
|
||||
pathParams: map[string]string{"username": "the-user", "reponame": "the-repo", "name": "master"},
|
||||
})
|
||||
|
||||
testRoute(t, "PATCH /api/v1/repos/the-user/the-repo/branches/master", resultStruct{
|
||||
method: "PATCH",
|
||||
pathParams: map[string]string{"username": "the-user", "reponame": "the-repo", "name": "master"},
|
||||
})
|
||||
|
||||
testRoute(t, "DELETE /api/v1/repos/the-user/the-repo/branches/master", resultStruct{
|
||||
method: "DELETE",
|
||||
pathParams: map[string]string{"username": "the-user", "reponame": "the-repo", "name": "master"},
|
||||
})
|
||||
for _, method := range []string{"GET", "POST"} {
|
||||
testRoute(t, method+" /api/v1/repos/the-user/the-repo/branches", resultStruct{
|
||||
method: method,
|
||||
pathParams: map[string]string{"username": "the-user", "reponame": "the-repo"},
|
||||
})
|
||||
}
|
||||
for _, method := range []string{"GET", "PATCH", "DELETE"} {
|
||||
testRoute(t, method+" /api/v1/repos/the-user/the-repo/branches/master", resultStruct{
|
||||
method: method,
|
||||
pathParams: map[string]string{"username": "the-user", "reponame": "the-repo", "name": "master"},
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("MatchPath", func(t *testing.T) {
|
||||
|
||||
+33
-83
@@ -21,47 +21,35 @@ func TestWriterReader(t *testing.T) {
|
||||
|
||||
result := bytes.NewBuffer(nil)
|
||||
|
||||
t.Run("regular", func(t *testing.T) {
|
||||
result.Reset()
|
||||
writer, err := NewWriter(result)
|
||||
require.NoError(t, err)
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
writerOptions []WriterOption
|
||||
readerOptions []ReaderOption
|
||||
}{
|
||||
{"regular", nil, nil},
|
||||
{"with options", []WriterOption{WithEncoderLevel(SpeedBestCompression)}, []ReaderOption{WithDecoderLowmem(true)}},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
result.Reset()
|
||||
writer, err := NewWriter(result, testCase.writerOptions...)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = io.Copy(writer, bytes.NewReader(testData))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, writer.Close())
|
||||
_, err = io.Copy(writer, bytes.NewReader(testData))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, writer.Close())
|
||||
|
||||
t.Logf("original size: %d, compressed size: %d, rate: %.2f%%", len(testData), result.Len(), float64(result.Len())/float64(len(testData))*100)
|
||||
t.Logf("original size: %d, compressed size: %d, rate: %.2f%%", len(testData), result.Len(), float64(result.Len())/float64(len(testData))*100)
|
||||
|
||||
reader, err := NewReader(result)
|
||||
require.NoError(t, err)
|
||||
reader, err := NewReader(result, testCase.readerOptions...)
|
||||
require.NoError(t, err)
|
||||
|
||||
data, err := io.ReadAll(reader)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, reader.Close())
|
||||
data, err := io.ReadAll(reader)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, reader.Close())
|
||||
|
||||
assert.Equal(t, testData, data)
|
||||
})
|
||||
|
||||
t.Run("with options", func(t *testing.T) {
|
||||
result.Reset()
|
||||
writer, err := NewWriter(result, WithEncoderLevel(SpeedBestCompression))
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = io.Copy(writer, bytes.NewReader(testData))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, writer.Close())
|
||||
|
||||
t.Logf("original size: %d, compressed size: %d, rate: %.2f%%", len(testData), result.Len(), float64(result.Len())/float64(len(testData))*100)
|
||||
|
||||
reader, err := NewReader(result, WithDecoderLowmem(true))
|
||||
require.NoError(t, err)
|
||||
|
||||
data, err := io.ReadAll(reader)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, reader.Close())
|
||||
|
||||
assert.Equal(t, testData, data)
|
||||
})
|
||||
assert.Equal(t, testData, data)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("rejects window above 128 MiB", func(t *testing.T) {
|
||||
frameWith256MiBWindow := []byte{0x28, 0xb5, 0x2f, 0xfd, 0x00, 0x90, 0x01, 0x00, 0x00}
|
||||
@@ -77,10 +65,8 @@ func TestSeekableWriterReader(t *testing.T) {
|
||||
|
||||
result := bytes.NewBuffer(nil)
|
||||
|
||||
t.Run("regular", func(t *testing.T) {
|
||||
write := func(t *testing.T, testData []byte, blockSize int) {
|
||||
result.Reset()
|
||||
blockSize := 10000
|
||||
|
||||
writer, err := NewSeekableWriter(result, blockSize)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -89,6 +75,10 @@ func TestSeekableWriterReader(t *testing.T) {
|
||||
require.NoError(t, writer.Close())
|
||||
|
||||
t.Logf("original size: %d, compressed size: %d, rate: %.2f%%", len(testData), result.Len(), float64(result.Len())/float64(len(testData))*100)
|
||||
}
|
||||
|
||||
t.Run("regular", func(t *testing.T) {
|
||||
write(t, testData, 10000)
|
||||
|
||||
reader, err := NewSeekableReader(bytes.NewReader(result.Bytes()))
|
||||
require.NoError(t, err)
|
||||
@@ -101,17 +91,8 @@ func TestSeekableWriterReader(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("seek read", func(t *testing.T) {
|
||||
result.Reset()
|
||||
blockSize := 10000
|
||||
|
||||
writer, err := NewSeekableWriter(result, blockSize)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = io.Copy(writer, bytes.NewReader(testData))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, writer.Close())
|
||||
|
||||
t.Logf("original size: %d, compressed size: %d, rate: %.2f%%", len(testData), result.Len(), float64(result.Len())/float64(len(testData))*100)
|
||||
write(t, testData, blockSize)
|
||||
|
||||
assertReader := &assertReadSeeker{r: bytes.NewReader(result.Bytes())}
|
||||
|
||||
@@ -141,18 +122,7 @@ func TestSeekableWriterReader(t *testing.T) {
|
||||
|
||||
t.Run("tidy data", func(t *testing.T) {
|
||||
testData := prepareTestData(t, 1000) // data size is less than a block
|
||||
|
||||
result.Reset()
|
||||
blockSize := 10000
|
||||
|
||||
writer, err := NewSeekableWriter(result, blockSize)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = io.Copy(writer, bytes.NewReader(testData))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, writer.Close())
|
||||
|
||||
t.Logf("original size: %d, compressed size: %d, rate: %.2f%%", len(testData), result.Len(), float64(result.Len())/float64(len(testData))*100)
|
||||
write(t, testData, 10000)
|
||||
|
||||
reader, err := NewSeekableReader(bytes.NewReader(result.Bytes()))
|
||||
require.NoError(t, err)
|
||||
@@ -165,17 +135,7 @@ func TestSeekableWriterReader(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("tidy block", func(t *testing.T) {
|
||||
result.Reset()
|
||||
blockSize := 100
|
||||
|
||||
writer, err := NewSeekableWriter(result, blockSize)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = io.Copy(writer, bytes.NewReader(testData))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, writer.Close())
|
||||
|
||||
t.Logf("original size: %d, compressed size: %d, rate: %.2f%%", len(testData), result.Len(), float64(result.Len())/float64(len(testData))*100)
|
||||
write(t, testData, 100)
|
||||
// A too small block size will cause a bad compression rate,
|
||||
// even the compressed data is larger than the original data.
|
||||
assert.Greater(t, result.Len(), len(testData))
|
||||
@@ -191,17 +151,7 @@ func TestSeekableWriterReader(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("compatible reader", func(t *testing.T) {
|
||||
result.Reset()
|
||||
blockSize := 10000
|
||||
|
||||
writer, err := NewSeekableWriter(result, blockSize)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = io.Copy(writer, bytes.NewReader(testData))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, writer.Close())
|
||||
|
||||
t.Logf("original size: %d, compressed size: %d, rate: %.2f%%", len(testData), result.Len(), float64(result.Len())/float64(len(testData))*100)
|
||||
write(t, testData, 10000)
|
||||
|
||||
// It should be able to read the data with a regular reader.
|
||||
reader, err := NewReader(bytes.NewReader(result.Bytes()))
|
||||
|
||||
Reference in new issue
Block a user