loading up the forgejo repo on tangled to test page performance
at forgejo 7.4 kB view raw
1// Copyright 2018 The Gitea Authors. All rights reserved. 2// Copyright 2024 The Forgejo Authors. All rights reserved. 3// SPDX-License-Identifier: MIT 4 5package util_test 6 7import ( 8 "bytes" 9 "crypto/rand" 10 "regexp" 11 "strings" 12 "testing" 13 14 "forgejo.org/modules/test" 15 "forgejo.org/modules/util" 16 17 "github.com/stretchr/testify/assert" 18 "github.com/stretchr/testify/require" 19) 20 21func TestURLJoin(t *testing.T) { 22 type test struct { 23 Expected string 24 Base string 25 Elements []string 26 } 27 newTest := func(expected, base string, elements ...string) test { 28 return test{Expected: expected, Base: base, Elements: elements} 29 } 30 for _, test := range []test{ 31 newTest("https://try.gitea.io/a/b/c", 32 "https://try.gitea.io", "a/b", "c"), 33 newTest("https://try.gitea.io/a/b/c", 34 "https://try.gitea.io/", "/a/b/", "/c/"), 35 newTest("https://try.gitea.io/a/c", 36 "https://try.gitea.io/", "/a/./b/", "../c/"), 37 newTest("a/b/c", 38 "a", "b/c/"), 39 newTest("a/b/d", 40 "a/", "b/c/", "/../d/"), 41 newTest("https://try.gitea.io/a/b/c#d", 42 "https://try.gitea.io", "a/b", "c#d"), 43 newTest("/a/b/d", 44 "/a/", "b/c/", "/../d/"), 45 newTest("/a/b/c", 46 "/a", "b/c/"), 47 newTest("/a/b/c#hash", 48 "/a", "b/c#hash"), 49 } { 50 assert.Equal(t, test.Expected, util.URLJoin(test.Base, test.Elements...)) 51 } 52} 53 54func TestIsEmptyString(t *testing.T) { 55 cases := []struct { 56 s string 57 expected bool 58 }{ 59 {"", true}, 60 {" ", true}, 61 {" ", true}, 62 {" a", false}, 63 } 64 65 for _, v := range cases { 66 assert.Equal(t, v.expected, util.IsEmptyString(v.s)) 67 } 68} 69 70func Test_NormalizeEOL(t *testing.T) { 71 data1 := []string{ 72 "", 73 "This text starts with empty lines", 74 "another", 75 "", 76 "", 77 "", 78 "Some other empty lines in the middle", 79 "more.", 80 "And more.", 81 "Ends with empty lines too.", 82 "", 83 "", 84 "", 85 } 86 87 data2 := []string{ 88 "This text does not start with empty lines", 89 "another", 90 "", 91 "", 92 "", 93 "Some other empty lines in the middle", 94 "more.", 95 "And more.", 96 "Ends without EOLtoo.", 97 } 98 99 buildEOLData := func(data []string, eol string) []byte { 100 return []byte(strings.Join(data, eol)) 101 } 102 103 dos := buildEOLData(data1, "\r\n") 104 unix := buildEOLData(data1, "\n") 105 mac := buildEOLData(data1, "\r") 106 107 assert.Equal(t, unix, util.NormalizeEOL(dos)) 108 assert.Equal(t, unix, util.NormalizeEOL(mac)) 109 assert.Equal(t, unix, util.NormalizeEOL(unix)) 110 111 dos = buildEOLData(data2, "\r\n") 112 unix = buildEOLData(data2, "\n") 113 mac = buildEOLData(data2, "\r") 114 115 assert.Equal(t, unix, util.NormalizeEOL(dos)) 116 assert.Equal(t, unix, util.NormalizeEOL(mac)) 117 assert.Equal(t, unix, util.NormalizeEOL(unix)) 118 119 assert.Equal(t, []byte("one liner"), util.NormalizeEOL([]byte("one liner"))) 120 assert.Equal(t, []byte("\n"), util.NormalizeEOL([]byte("\n"))) 121 assert.Equal(t, []byte("\ntwo liner"), util.NormalizeEOL([]byte("\ntwo liner"))) 122 assert.Equal(t, []byte("two liner\n"), util.NormalizeEOL([]byte("two liner\n"))) 123 assert.Equal(t, []byte{}, util.NormalizeEOL([]byte{})) 124 125 assert.Equal(t, []byte("mix\nand\nmatch\n."), util.NormalizeEOL([]byte("mix\r\nand\rmatch\n."))) 126} 127 128func Test_RandomInt(t *testing.T) { 129 randInt, err := util.CryptoRandomInt(255) 130 assert.GreaterOrEqual(t, randInt, int64(0)) 131 assert.LessOrEqual(t, randInt, int64(255)) 132 require.NoError(t, err) 133} 134 135func Test_RandomString(t *testing.T) { 136 str1, err := util.CryptoRandomString(32) 137 require.NoError(t, err) 138 matches, err := regexp.MatchString(`^[a-zA-Z0-9]{32}$`, str1) 139 require.NoError(t, err) 140 assert.True(t, matches) 141 142 str2, err := util.CryptoRandomString(32) 143 require.NoError(t, err) 144 matches, err = regexp.MatchString(`^[a-zA-Z0-9]{32}$`, str1) 145 require.NoError(t, err) 146 assert.True(t, matches) 147 148 assert.NotEqual(t, str1, str2) 149 150 str3, err := util.CryptoRandomString(256) 151 require.NoError(t, err) 152 matches, err = regexp.MatchString(`^[a-zA-Z0-9]{256}$`, str3) 153 require.NoError(t, err) 154 assert.True(t, matches) 155 156 str4, err := util.CryptoRandomString(256) 157 require.NoError(t, err) 158 matches, err = regexp.MatchString(`^[a-zA-Z0-9]{256}$`, str4) 159 require.NoError(t, err) 160 assert.True(t, matches) 161 162 assert.NotEqual(t, str3, str4) 163} 164 165func Test_RandomBytes(t *testing.T) { 166 bytes1 := util.CryptoRandomBytes(32) 167 bytes2 := util.CryptoRandomBytes(32) 168 169 assert.Len(t, bytes1, 32) 170 assert.Len(t, bytes2, 32) 171 assert.NotEqual(t, bytes1, bytes2) 172 173 bytes3 := util.CryptoRandomBytes(256) 174 bytes4 := util.CryptoRandomBytes(256) 175 176 assert.Len(t, bytes3, 256) 177 assert.Len(t, bytes4, 256) 178 assert.NotEqual(t, bytes3, bytes4) 179} 180 181// Test case for any function which accepts and returns a single string. 182type StringTest struct { 183 in, out string 184} 185 186var upperTests = []StringTest{ 187 {"", ""}, 188 {"ONLYUPPER", "ONLYUPPER"}, 189 {"abc", "ABC"}, 190 {"AbC123", "ABC123"}, 191 {"azAZ09_", "AZAZ09_"}, 192 {"longStrinGwitHmixofsmaLLandcAps", "LONGSTRINGWITHMIXOFSMALLANDCAPS"}, 193 {"long\u0250string\u0250with\u0250nonascii\u2C6Fchars", "LONG\u0250STRING\u0250WITH\u0250NONASCII\u2C6FCHARS"}, 194 {"\u0250\u0250\u0250\u0250\u0250", "\u0250\u0250\u0250\u0250\u0250"}, 195 {"a\u0080\U0010FFFF", "A\u0080\U0010FFFF"}, 196 {"lél", "LéL"}, 197} 198 199func TestToUpperASCII(t *testing.T) { 200 for _, tc := range upperTests { 201 assert.Equal(t, util.ToUpperASCII(tc.in), tc.out) 202 } 203} 204 205func BenchmarkToUpper(b *testing.B) { 206 for _, tc := range upperTests { 207 b.Run(tc.in, func(b *testing.B) { 208 for i := 0; i < b.N; i++ { 209 util.ToUpperASCII(tc.in) 210 } 211 }) 212 } 213} 214 215func TestToTitleCase(t *testing.T) { 216 assert.Equal(t, `Foo Bar Baz`, util.ToTitleCase(`foo bar baz`)) 217 assert.Equal(t, `Foo Bar Baz`, util.ToTitleCase(`FOO BAR BAZ`)) 218} 219 220func TestToPointer(t *testing.T) { 221 assert.Equal(t, "abc", *util.ToPointer("abc")) 222 assert.Equal(t, 123, *util.ToPointer(123)) 223 abc := "abc" 224 assert.NotSame(t, &abc, util.ToPointer(abc)) 225 val123 := 123 226 assert.NotSame(t, &val123, util.ToPointer(val123)) 227} 228 229func TestReserveLineBreakForTextarea(t *testing.T) { 230 assert.Equal(t, "test\ndata", util.ReserveLineBreakForTextarea("test\r\ndata")) 231 assert.Equal(t, "test\ndata\n", util.ReserveLineBreakForTextarea("test\r\ndata\r\n")) 232} 233 234const ( 235 testPublicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAOhB7/zzhC+HXDdGOdLwJln5NYwm6UNXx3chmQSVTG4\n" 236 testPrivateKey = `-----BEGIN OPENSSH PRIVATE KEY----- 237b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtz 238c2gtZWQyNTUxOQAAACADoQe/884Qvh1w3RjnS8CZZ+TWMJulDV8d3IZkElUxuAAA 239AIggISIjICEiIwAAAAtzc2gtZWQyNTUxOQAAACADoQe/884Qvh1w3RjnS8CZZ+TW 240MJulDV8d3IZkElUxuAAAAEAAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0e 241HwOhB7/zzhC+HXDdGOdLwJln5NYwm6UNXx3chmQSVTG4AAAAAAECAwQF 242-----END OPENSSH PRIVATE KEY-----` + "\n" 243) 244 245func TestGeneratingEd25519Keypair(t *testing.T) { 246 defer test.MockProtect(&rand.Reader)() 247 248 // Only 32 bytes needs to be provided to generate a ed25519 keypair. 249 // And another 32 bytes are required, which is included as random value 250 // in the OpenSSH format. 251 b := make([]byte, 64) 252 for i := 0; i < 64; i++ { 253 b[i] = byte(i) 254 } 255 rand.Reader = bytes.NewReader(b) 256 257 publicKey, privateKey, err := util.GenerateSSHKeypair() 258 require.NoError(t, err) 259 assert.Equal(t, testPublicKey, string(publicKey)) 260 assert.Equal(t, testPrivateKey, string(privateKey)) 261} 262 263func TestOptionalArg(t *testing.T) { 264 foo := func(other any, optArg ...int) int { 265 return util.OptionalArg(optArg) 266 } 267 bar := func(other any, optArg ...int) int { 268 return util.OptionalArg(optArg, 42) 269 } 270 assert.Equal(t, 0, foo(nil)) 271 assert.Equal(t, 100, foo(nil, 100)) 272 assert.Equal(t, 42, bar(nil)) 273 assert.Equal(t, 100, bar(nil, 100)) 274}