From dd136858f1ea40ad3c94191d647487fa4f31926c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 18 Oct 2024 20:33:49 +0200 Subject: Adding upstream version 9.0.0. Signed-off-by: Daniel Baumann --- modules/util/util_test.go | 277 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 modules/util/util_test.go (limited to 'modules/util/util_test.go') diff --git a/modules/util/util_test.go b/modules/util/util_test.go new file mode 100644 index 0000000..549b53f --- /dev/null +++ b/modules/util/util_test.go @@ -0,0 +1,277 @@ +// Copyright 2018 The Gitea Authors. All rights reserved. +// Copyright 2024 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package util_test + +import ( + "bytes" + "crypto/rand" + "regexp" + "strings" + "testing" + + "code.gitea.io/gitea/modules/optional" + "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/modules/util" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestURLJoin(t *testing.T) { + type test struct { + Expected string + Base string + Elements []string + } + newTest := func(expected, base string, elements ...string) test { + return test{Expected: expected, Base: base, Elements: elements} + } + for _, test := range []test{ + newTest("https://try.gitea.io/a/b/c", + "https://try.gitea.io", "a/b", "c"), + newTest("https://try.gitea.io/a/b/c", + "https://try.gitea.io/", "/a/b/", "/c/"), + newTest("https://try.gitea.io/a/c", + "https://try.gitea.io/", "/a/./b/", "../c/"), + newTest("a/b/c", + "a", "b/c/"), + newTest("a/b/d", + "a/", "b/c/", "/../d/"), + newTest("https://try.gitea.io/a/b/c#d", + "https://try.gitea.io", "a/b", "c#d"), + newTest("/a/b/d", + "/a/", "b/c/", "/../d/"), + newTest("/a/b/c", + "/a", "b/c/"), + newTest("/a/b/c#hash", + "/a", "b/c#hash"), + } { + assert.Equal(t, test.Expected, util.URLJoin(test.Base, test.Elements...)) + } +} + +func TestIsEmptyString(t *testing.T) { + cases := []struct { + s string + expected bool + }{ + {"", true}, + {" ", true}, + {" ", true}, + {" a", false}, + } + + for _, v := range cases { + assert.Equal(t, v.expected, util.IsEmptyString(v.s)) + } +} + +func Test_NormalizeEOL(t *testing.T) { + data1 := []string{ + "", + "This text starts with empty lines", + "another", + "", + "", + "", + "Some other empty lines in the middle", + "more.", + "And more.", + "Ends with empty lines too.", + "", + "", + "", + } + + data2 := []string{ + "This text does not start with empty lines", + "another", + "", + "", + "", + "Some other empty lines in the middle", + "more.", + "And more.", + "Ends without EOLtoo.", + } + + buildEOLData := func(data []string, eol string) []byte { + return []byte(strings.Join(data, eol)) + } + + dos := buildEOLData(data1, "\r\n") + unix := buildEOLData(data1, "\n") + mac := buildEOLData(data1, "\r") + + assert.Equal(t, unix, util.NormalizeEOL(dos)) + assert.Equal(t, unix, util.NormalizeEOL(mac)) + assert.Equal(t, unix, util.NormalizeEOL(unix)) + + dos = buildEOLData(data2, "\r\n") + unix = buildEOLData(data2, "\n") + mac = buildEOLData(data2, "\r") + + assert.Equal(t, unix, util.NormalizeEOL(dos)) + assert.Equal(t, unix, util.NormalizeEOL(mac)) + assert.Equal(t, unix, util.NormalizeEOL(unix)) + + assert.Equal(t, []byte("one liner"), util.NormalizeEOL([]byte("one liner"))) + assert.Equal(t, []byte("\n"), util.NormalizeEOL([]byte("\n"))) + assert.Equal(t, []byte("\ntwo liner"), util.NormalizeEOL([]byte("\ntwo liner"))) + assert.Equal(t, []byte("two liner\n"), util.NormalizeEOL([]byte("two liner\n"))) + assert.Equal(t, []byte{}, util.NormalizeEOL([]byte{})) + + assert.Equal(t, []byte("mix\nand\nmatch\n."), util.NormalizeEOL([]byte("mix\r\nand\rmatch\n."))) +} + +func Test_RandomInt(t *testing.T) { + randInt, err := util.CryptoRandomInt(255) + assert.GreaterOrEqual(t, randInt, int64(0)) + assert.LessOrEqual(t, randInt, int64(255)) + require.NoError(t, err) +} + +func Test_RandomString(t *testing.T) { + str1, err := util.CryptoRandomString(32) + require.NoError(t, err) + matches, err := regexp.MatchString(`^[a-zA-Z0-9]{32}$`, str1) + require.NoError(t, err) + assert.True(t, matches) + + str2, err := util.CryptoRandomString(32) + require.NoError(t, err) + matches, err = regexp.MatchString(`^[a-zA-Z0-9]{32}$`, str1) + require.NoError(t, err) + assert.True(t, matches) + + assert.NotEqual(t, str1, str2) + + str3, err := util.CryptoRandomString(256) + require.NoError(t, err) + matches, err = regexp.MatchString(`^[a-zA-Z0-9]{256}$`, str3) + require.NoError(t, err) + assert.True(t, matches) + + str4, err := util.CryptoRandomString(256) + require.NoError(t, err) + matches, err = regexp.MatchString(`^[a-zA-Z0-9]{256}$`, str4) + require.NoError(t, err) + assert.True(t, matches) + + assert.NotEqual(t, str3, str4) +} + +func Test_RandomBytes(t *testing.T) { + bytes1, err := util.CryptoRandomBytes(32) + require.NoError(t, err) + + bytes2, err := util.CryptoRandomBytes(32) + require.NoError(t, err) + + assert.NotEqual(t, bytes1, bytes2) + + bytes3, err := util.CryptoRandomBytes(256) + require.NoError(t, err) + + bytes4, err := util.CryptoRandomBytes(256) + require.NoError(t, err) + + assert.NotEqual(t, bytes3, bytes4) +} + +func TestOptionalBoolParse(t *testing.T) { + assert.Equal(t, optional.None[bool](), util.OptionalBoolParse("")) + assert.Equal(t, optional.None[bool](), util.OptionalBoolParse("x")) + + assert.Equal(t, optional.Some(false), util.OptionalBoolParse("0")) + assert.Equal(t, optional.Some(false), util.OptionalBoolParse("f")) + assert.Equal(t, optional.Some(false), util.OptionalBoolParse("False")) + + assert.Equal(t, optional.Some(true), util.OptionalBoolParse("1")) + assert.Equal(t, optional.Some(true), util.OptionalBoolParse("t")) + assert.Equal(t, optional.Some(true), util.OptionalBoolParse("True")) +} + +// Test case for any function which accepts and returns a single string. +type StringTest struct { + in, out string +} + +var upperTests = []StringTest{ + {"", ""}, + {"ONLYUPPER", "ONLYUPPER"}, + {"abc", "ABC"}, + {"AbC123", "ABC123"}, + {"azAZ09_", "AZAZ09_"}, + {"longStrinGwitHmixofsmaLLandcAps", "LONGSTRINGWITHMIXOFSMALLANDCAPS"}, + {"long\u0250string\u0250with\u0250nonascii\u2C6Fchars", "LONG\u0250STRING\u0250WITH\u0250NONASCII\u2C6FCHARS"}, + {"\u0250\u0250\u0250\u0250\u0250", "\u0250\u0250\u0250\u0250\u0250"}, + {"a\u0080\U0010FFFF", "A\u0080\U0010FFFF"}, + {"lél", "LéL"}, +} + +func TestToUpperASCII(t *testing.T) { + for _, tc := range upperTests { + assert.Equal(t, util.ToUpperASCII(tc.in), tc.out) + } +} + +func BenchmarkToUpper(b *testing.B) { + for _, tc := range upperTests { + b.Run(tc.in, func(b *testing.B) { + for i := 0; i < b.N; i++ { + util.ToUpperASCII(tc.in) + } + }) + } +} + +func TestToTitleCase(t *testing.T) { + assert.Equal(t, `Foo Bar Baz`, util.ToTitleCase(`foo bar baz`)) + assert.Equal(t, `Foo Bar Baz`, util.ToTitleCase(`FOO BAR BAZ`)) +} + +func TestToPointer(t *testing.T) { + assert.Equal(t, "abc", *util.ToPointer("abc")) + assert.Equal(t, 123, *util.ToPointer(123)) + abc := "abc" + assert.NotSame(t, &abc, util.ToPointer(abc)) + val123 := 123 + assert.NotSame(t, &val123, util.ToPointer(val123)) +} + +func TestReserveLineBreakForTextarea(t *testing.T) { + assert.Equal(t, "test\ndata", util.ReserveLineBreakForTextarea("test\r\ndata")) + assert.Equal(t, "test\ndata\n", util.ReserveLineBreakForTextarea("test\r\ndata\r\n")) +} + +const ( + testPublicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAOhB7/zzhC+HXDdGOdLwJln5NYwm6UNXx3chmQSVTG4\n" + testPrivateKey = `-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtz +c2gtZWQyNTUxOQAAACADoQe/884Qvh1w3RjnS8CZZ+TWMJulDV8d3IZkElUxuAAA +AIggISIjICEiIwAAAAtzc2gtZWQyNTUxOQAAACADoQe/884Qvh1w3RjnS8CZZ+TW +MJulDV8d3IZkElUxuAAAAEAAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0e +HwOhB7/zzhC+HXDdGOdLwJln5NYwm6UNXx3chmQSVTG4AAAAAAECAwQF +-----END OPENSSH PRIVATE KEY-----` + "\n" +) + +func TestGeneratingEd25519Keypair(t *testing.T) { + defer test.MockProtect(&rand.Reader)() + + // Only 32 bytes needs to be provided to generate a ed25519 keypair. + // And another 32 bytes are required, which is included as random value + // in the OpenSSH format. + b := make([]byte, 64) + for i := 0; i < 64; i++ { + b[i] = byte(i) + } + rand.Reader = bytes.NewReader(b) + + publicKey, privateKey, err := util.GenerateSSHKeypair() + require.NoError(t, err) + assert.EqualValues(t, testPublicKey, string(publicKey)) + assert.EqualValues(t, testPrivateKey, string(privateKey)) +} -- cgit v1.2.3