loading up the forgejo repo on tangled to test page performance
at forgejo 6.0 kB view raw
1// Copyright 2021 The Gitea Authors. All rights reserved. 2// SPDX-License-Identifier: MIT 3 4package cmd 5 6import ( 7 "bufio" 8 "bytes" 9 "io" 10 "net/http" 11 "net/http/httptest" 12 "os" 13 "strings" 14 "testing" 15 "time" 16 17 "forgejo.org/modules/setting" 18 "forgejo.org/modules/test" 19 20 "github.com/stretchr/testify/assert" 21 "github.com/stretchr/testify/require" 22 "github.com/urfave/cli/v2" 23) 24 25// Capture what's being written into a standard file descriptor. 26func captureOutput(t *testing.T, stdFD *os.File) (finish func() (output string)) { 27 t.Helper() 28 29 r, w, err := os.Pipe() 30 require.NoError(t, err) 31 resetStdout := test.MockVariableValue(stdFD, *w) 32 33 return func() (output string) { 34 w.Close() 35 resetStdout() 36 37 out, err := io.ReadAll(r) 38 require.NoError(t, err) 39 return string(out) 40 } 41} 42 43func TestPktLine(t *testing.T) { 44 ctx := t.Context() 45 46 t.Run("Read", func(t *testing.T) { 47 s := strings.NewReader("0000") 48 r := bufio.NewReader(s) 49 result, err := readPktLine(ctx, r, pktLineTypeFlush) 50 require.NoError(t, err) 51 assert.Equal(t, pktLineTypeFlush, result.Type) 52 53 s = strings.NewReader("0006a\n") 54 r = bufio.NewReader(s) 55 result, err = readPktLine(ctx, r, pktLineTypeData) 56 require.NoError(t, err) 57 assert.Equal(t, pktLineTypeData, result.Type) 58 assert.Equal(t, []byte("a\n"), result.Data) 59 60 s = strings.NewReader("0004") 61 r = bufio.NewReader(s) 62 result, err = readPktLine(ctx, r, pktLineTypeData) 63 require.Error(t, err) 64 assert.Nil(t, result) 65 66 data := strings.Repeat("x", 65516) 67 r = bufio.NewReader(strings.NewReader("fff0" + data)) 68 result, err = readPktLine(ctx, r, pktLineTypeData) 69 require.NoError(t, err) 70 assert.Equal(t, pktLineTypeData, result.Type) 71 assert.Equal(t, []byte(data), result.Data) 72 73 r = bufio.NewReader(strings.NewReader("fff1a")) 74 result, err = readPktLine(ctx, r, pktLineTypeData) 75 require.Error(t, err) 76 assert.Nil(t, result) 77 }) 78 79 t.Run("Write", func(t *testing.T) { 80 w := bytes.NewBuffer([]byte{}) 81 err := writeFlushPktLine(ctx, w) 82 require.NoError(t, err) 83 assert.Equal(t, []byte("0000"), w.Bytes()) 84 85 w.Reset() 86 err = writeDataPktLine(ctx, w, []byte("a\nb")) 87 require.NoError(t, err) 88 assert.Equal(t, []byte("0007a\nb"), w.Bytes()) 89 90 w.Reset() 91 data := bytes.Repeat([]byte{0x05}, 288) 92 err = writeDataPktLine(ctx, w, data) 93 require.NoError(t, err) 94 assert.Equal(t, append([]byte("0124"), data...), w.Bytes()) 95 96 w.Reset() 97 err = writeDataPktLine(ctx, w, nil) 98 require.Error(t, err) 99 assert.Empty(t, w.Bytes()) 100 101 w.Reset() 102 data = bytes.Repeat([]byte{0x64}, 65516) 103 err = writeDataPktLine(ctx, w, data) 104 require.NoError(t, err) 105 assert.Equal(t, append([]byte("fff0"), data...), w.Bytes()) 106 107 w.Reset() 108 err = writeDataPktLine(ctx, w, bytes.Repeat([]byte{0x64}, 65516+1)) 109 require.Error(t, err) 110 assert.Empty(t, w.Bytes()) 111 }) 112} 113 114func TestDelayWriter(t *testing.T) { 115 // Setup the environment. 116 defer test.MockVariableValue(&setting.InternalToken, "Random")() 117 defer test.MockVariableValue(&setting.InstallLock, true)() 118 defer test.MockVariableValue(&setting.Git.VerbosePush, true)() 119 t.Setenv("SSH_ORIGINAL_COMMAND", "true") 120 121 // Setup the Stdin. 122 f, err := os.OpenFile(t.TempDir()+"/stdin", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o666) 123 require.NoError(t, err) 124 _, err = f.Write([]byte("00000000000000000000 00000000000000000001 refs/head/main\n")) 125 require.NoError(t, err) 126 _, err = f.Seek(0, 0) 127 require.NoError(t, err) 128 defer test.MockVariableValue(os.Stdin, *f)() 129 130 // Setup the server that processes the hooks. 131 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 132 time.Sleep(time.Millisecond * 600) 133 })) 134 defer ts.Close() 135 defer test.MockVariableValue(&setting.LocalURL, ts.URL+"/")() 136 137 app := cli.NewApp() 138 app.Commands = []*cli.Command{subcmdHookPreReceive} 139 140 t.Run("Should delay", func(t *testing.T) { 141 defer test.MockVariableValue(&setting.Git.VerbosePushDelay, time.Millisecond*500)() 142 finish := captureOutput(t, os.Stdout) 143 144 err = app.Run([]string{"./forgejo", "pre-receive"}) 145 require.NoError(t, err) 146 out := finish() 147 148 require.Contains(t, out, "* Checking 1 references") 149 require.Contains(t, out, "Checked 1 references in total") 150 }) 151 152 t.Run("Shouldn't delay", func(t *testing.T) { 153 defer test.MockVariableValue(&setting.Git.VerbosePushDelay, time.Second*5)() 154 finish := captureOutput(t, os.Stdout) 155 156 err = app.Run([]string{"./forgejo", "pre-receive"}) 157 require.NoError(t, err) 158 out := finish() 159 160 require.NoError(t, err) 161 require.Empty(t, out) 162 }) 163} 164 165func TestRunHookUpdate(t *testing.T) { 166 app := cli.NewApp() 167 app.Commands = []*cli.Command{subcmdHookUpdate} 168 169 t.Run("Removal of internal reference", func(t *testing.T) { 170 defer test.MockVariableValue(&cli.OsExiter, func(code int) {})() 171 defer test.MockVariableValue(&setting.IsProd, false)() 172 finish := captureOutput(t, os.Stderr) 173 174 err := app.Run([]string{"./forgejo", "update", "refs/pull/1/head", "0a51ae26bc73c47e2f754560c40904cf14ed51a9", "0000000000000000000000000000000000000000"}) 175 out := finish() 176 require.Error(t, err) 177 178 assert.Contains(t, out, "The deletion of refs/pull/1/head is skipped as it's an internal reference.") 179 }) 180 181 t.Run("Update of internal reference", func(t *testing.T) { 182 defer test.MockVariableValue(&cli.OsExiter, func(code int) {})() 183 defer test.MockVariableValue(&setting.IsProd, false)() 184 finish := captureOutput(t, os.Stderr) 185 186 err := app.Run([]string{"./forgejo", "update", "refs/pull/1/head", "0a51ae26bc73c47e2f754560c40904cf14ed51a9", "0000000000000000000000000000000000000001"}) 187 out := finish() 188 require.Error(t, err) 189 190 assert.Contains(t, out, "The modification of refs/pull/1/head is skipped as it's an internal reference.") 191 }) 192 193 t.Run("Removal of branch", func(t *testing.T) { 194 err := app.Run([]string{"./forgejo", "update", "refs/head/main", "0a51ae26bc73c47e2f754560c40904cf14ed51a9", "0000000000000000000000000000000000000000"}) 195 require.NoError(t, err) 196 }) 197 198 t.Run("Not enough arguments", func(t *testing.T) { 199 err := app.Run([]string{"./forgejo", "update"}) 200 require.NoError(t, err) 201 }) 202}