golang.org/x/playground@v0.0.0-20230418134305-14ebe15bcd59/sandbox/sandbox_test.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "bytes" 9 "io" 10 "strings" 11 "testing" 12 "testing/iotest" 13 14 "github.com/google/go-cmp/cmp" 15 ) 16 17 func TestLimitedWriter(t *testing.T) { 18 cases := []struct { 19 desc string 20 lw *limitedWriter 21 in []byte 22 want []byte 23 wantN int64 24 wantRemaining int64 25 err error 26 }{ 27 { 28 desc: "simple", 29 lw: &limitedWriter{dst: &bytes.Buffer{}, n: 10}, 30 in: []byte("hi"), 31 want: []byte("hi"), 32 wantN: 2, 33 wantRemaining: 8, 34 }, 35 { 36 desc: "writing nothing", 37 lw: &limitedWriter{dst: &bytes.Buffer{}, n: 10}, 38 in: []byte(""), 39 want: []byte(""), 40 wantN: 0, 41 wantRemaining: 10, 42 }, 43 { 44 desc: "writing exactly enough", 45 lw: &limitedWriter{dst: &bytes.Buffer{}, n: 6}, 46 in: []byte("enough"), 47 want: []byte("enough"), 48 wantN: 6, 49 wantRemaining: 0, 50 err: nil, 51 }, 52 { 53 desc: "writing too much", 54 lw: &limitedWriter{dst: &bytes.Buffer{}, n: 10}, 55 in: []byte("this is much longer than 10"), 56 want: []byte("this is mu"), 57 wantN: 10, 58 wantRemaining: -1, 59 err: errTooMuchOutput, 60 }, 61 } 62 for _, c := range cases { 63 t.Run(c.desc, func(t *testing.T) { 64 n, err := io.Copy(c.lw, iotest.OneByteReader(bytes.NewReader(c.in))) 65 if err != c.err { 66 t.Errorf("c.lw.Write(%q) = %d, %q, wanted %d, %q", c.in, n, err, c.wantN, c.err) 67 } 68 if n != c.wantN { 69 t.Errorf("c.lw.Write(%q) = %d, %q, wanted %d, %q", c.in, n, err, c.wantN, c.err) 70 } 71 if c.lw.n != c.wantRemaining { 72 t.Errorf("c.lw.n = %d, wanted %d", c.lw.n, c.wantRemaining) 73 } 74 if string(c.lw.dst.Bytes()) != string(c.want) { 75 t.Errorf("c.lw.dst.Bytes() = %q, wanted %q", c.lw.dst.Bytes(), c.want) 76 } 77 }) 78 } 79 } 80 81 func TestSwitchWriter(t *testing.T) { 82 cases := []struct { 83 desc string 84 sw *switchWriter 85 in []byte 86 want1 []byte 87 want2 []byte 88 wantN int64 89 wantFound bool 90 err error 91 }{ 92 { 93 desc: "not found", 94 sw: &switchWriter{switchAfter: []byte("UNIQUE")}, 95 in: []byte("hi"), 96 want1: []byte("hi"), 97 want2: []byte(""), 98 wantN: 2, 99 wantFound: false, 100 }, 101 { 102 desc: "writing nothing", 103 sw: &switchWriter{switchAfter: []byte("UNIQUE")}, 104 in: []byte(""), 105 want1: []byte(""), 106 want2: []byte(""), 107 wantN: 0, 108 wantFound: false, 109 }, 110 { 111 desc: "writing exactly switchAfter", 112 sw: &switchWriter{switchAfter: []byte("UNIQUE")}, 113 in: []byte("UNIQUE"), 114 want1: []byte("UNIQUE"), 115 want2: []byte(""), 116 wantN: 6, 117 wantFound: true, 118 }, 119 { 120 desc: "writing before and after switchAfter", 121 sw: &switchWriter{switchAfter: []byte("UNIQUE")}, 122 in: []byte("this is before UNIQUE and this is after"), 123 want1: []byte("this is before UNIQUE"), 124 want2: []byte(" and this is after"), 125 wantN: 39, 126 wantFound: true, 127 }, 128 } 129 for _, c := range cases { 130 t.Run(c.desc, func(t *testing.T) { 131 dst1, dst2 := &bytes.Buffer{}, &bytes.Buffer{} 132 c.sw.dst1, c.sw.dst2 = dst1, dst2 133 n, err := io.Copy(c.sw, iotest.OneByteReader(bytes.NewReader(c.in))) 134 if err != c.err { 135 t.Errorf("c.sw.Write(%q) = %d, %q, wanted %d, %q", c.in, n, err, c.wantN, c.err) 136 } 137 if n != c.wantN { 138 t.Errorf("c.sw.Write(%q) = %d, %q, wanted %d, %q", c.in, n, err, c.wantN, c.err) 139 } 140 if c.sw.found != c.wantFound { 141 t.Errorf("c.sw.found = %v, wanted %v", c.sw.found, c.wantFound) 142 } 143 if string(dst1.Bytes()) != string(c.want1) { 144 t.Errorf("dst1.Bytes() = %q, wanted %q", dst1.Bytes(), c.want1) 145 } 146 if string(dst2.Bytes()) != string(c.want2) { 147 t.Errorf("dst2.Bytes() = %q, wanted %q", dst2.Bytes(), c.want2) 148 } 149 }) 150 } 151 } 152 153 func TestSwitchWriterMultipleWrites(t *testing.T) { 154 dst1, dst2 := &bytes.Buffer{}, &bytes.Buffer{} 155 sw := &switchWriter{ 156 dst1: dst1, 157 dst2: dst2, 158 switchAfter: []byte("GOPHER"), 159 } 160 n, err := io.Copy(sw, iotest.OneByteReader(strings.NewReader("this is before GO"))) 161 if err != nil || n != 17 { 162 t.Errorf("sw.Write(%q) = %d, %q, wanted %d, no error", "this is before GO", n, err, 17) 163 } 164 if sw.found { 165 t.Errorf("sw.found = %v, wanted %v", sw.found, false) 166 } 167 if string(dst1.Bytes()) != "this is before GO" { 168 t.Errorf("dst1.Bytes() = %q, wanted %q", dst1.Bytes(), "this is before GO") 169 } 170 if string(dst2.Bytes()) != "" { 171 t.Errorf("dst2.Bytes() = %q, wanted %q", dst2.Bytes(), "") 172 } 173 n, err = io.Copy(sw, iotest.OneByteReader(strings.NewReader("PHER and this is after"))) 174 if err != nil || n != 22 { 175 t.Errorf("sw.Write(%q) = %d, %q, wanted %d, no error", "this is before GO", n, err, 22) 176 } 177 if !sw.found { 178 t.Errorf("sw.found = %v, wanted %v", sw.found, true) 179 } 180 if string(dst1.Bytes()) != "this is before GOPHER" { 181 t.Errorf("dst1.Bytes() = %q, wanted %q", dst1.Bytes(), "this is before GOPHEr") 182 } 183 if string(dst2.Bytes()) != " and this is after" { 184 t.Errorf("dst2.Bytes() = %q, wanted %q", dst2.Bytes(), " and this is after") 185 } 186 } 187 188 func TestParseDockerContainers(t *testing.T) { 189 cases := []struct { 190 desc string 191 output string 192 want []dockerContainer 193 wantErr bool 194 }{ 195 { 196 desc: "normal output (container per line)", 197 output: `{"Command":"\"/usr/local/bin/play…\"","CreatedAt":"2020-04-23 17:44:02 -0400 EDT","ID":"f7f170fde076","Image":"gcr.io/golang-org/playground-sandbox-gvisor:latest","Labels":"","LocalVolumes":"0","Mounts":"","Names":"play_run_a02cfe67","Networks":"none","Ports":"","RunningFor":"8 seconds ago","Size":"0B","Status":"Up 7 seconds"} 198 {"Command":"\"/usr/local/bin/play…\"","CreatedAt":"2020-04-23 17:44:02 -0400 EDT","ID":"af872e55a773","Image":"gcr.io/golang-org/playground-sandbox-gvisor:latest","Labels":"","LocalVolumes":"0","Mounts":"","Names":"play_run_0a69c3e8","Networks":"none","Ports":"","RunningFor":"8 seconds ago","Size":"0B","Status":"Up 7 seconds"}`, 199 want: []dockerContainer{ 200 {ID: "f7f170fde076", Image: "gcr.io/golang-org/playground-sandbox-gvisor:latest", Names: "play_run_a02cfe67"}, 201 {ID: "af872e55a773", Image: "gcr.io/golang-org/playground-sandbox-gvisor:latest", Names: "play_run_0a69c3e8"}, 202 }, 203 wantErr: false, 204 }, 205 { 206 desc: "empty output", 207 wantErr: false, 208 }, 209 { 210 desc: "malformatted output", 211 output: `xyzzy{}`, 212 wantErr: true, 213 }, 214 } 215 for _, tc := range cases { 216 t.Run(tc.desc, func(t *testing.T) { 217 cs, err := parseDockerContainers([]byte(tc.output)) 218 if (err != nil) != tc.wantErr { 219 t.Errorf("parseDockerContainers(_) = %v, %v, wantErr: %v", cs, err, tc.wantErr) 220 } 221 if diff := cmp.Diff(tc.want, cs); diff != "" { 222 t.Errorf("parseDockerContainers() mismatch (-want +got):\n%s", diff) 223 } 224 }) 225 } 226 }