github.com/hugelgupf/u-root@v0.0.0-20191023214958-4807c632154c/cmds/exp/ed/ed_test.go (about) 1 // Copyright 2017-2018 the u-root 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 // Ed is a simple line-oriented editor 6 // 7 // Synopsis: 8 // dd 9 // 10 // Description: 11 // 12 // Options: 13 package main 14 15 import ( 16 "bytes" 17 "fmt" 18 "io/ioutil" 19 "os" 20 "reflect" 21 "testing" 22 ) 23 24 func TestNewTextFile(t *testing.T) { 25 var test = []struct { 26 d string 27 start, end int 28 f file 29 }{ 30 {d: "a\nb\nc\n", start: 1, end: 3, f: file{dot: 1, data: []byte("a\nb\nc\n"), lines: []int{0, 2, 4}}}, 31 // I'm not sure this is right. 32 {d: "", start: 1, end: 1, f: file{dot: 1}}, 33 } 34 35 for _, v := range test { 36 f, err := NewTextEditor(readerio(bytes.NewBufferString(v.d))) 37 if err != nil { 38 t.Errorf("%v: want nil, got %v", v.d, err) 39 continue 40 } 41 if err := v.f.Equal(f); err != nil { 42 t.Errorf("%v vs %v: want nil, got %v", v.f, *f.(*file), err) 43 } 44 45 } 46 47 } 48 49 func TestReadTextFile(t *testing.T) { 50 var test = []struct { 51 d string 52 where int 53 f file 54 }{ 55 //{"a\nb\nc\n", 1, file{dot: 1, data: []byte("a\na\nb\nc\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}}}, 56 //{"a\nb\nc\n", 4, file{dot: 4, data: []byte("a\nb\nc\na\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}}}, 57 //{"a\nb\nc\n", 2, file{dot: 2, data: []byte("a\nb\na\nb\nc\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}}}, 58 {"a\nb\nc\n", 0, file{dot: 1, data: []byte("a\nb\nc\na\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}}}, 59 } 60 debug = t.Logf 61 for _, v := range test { 62 r := bytes.NewBufferString(v.d) 63 f, err := NewTextEditor(readerio(r)) 64 if err != nil { 65 t.Error(err) 66 continue 67 } 68 // We are adding the file after a 0-length slice 69 // We want dot to be at the point we added it. 70 f.Move(v.where) 71 r = bytes.NewBufferString(v.d) 72 _, err = f.Read(r, v.where, v.where) 73 if err != nil { 74 t.Errorf("Error reading %v: %v", v.d, err) 75 continue 76 } 77 if err := v.f.Equal(f); err != nil { 78 t.Errorf("%v vs. %v: want nil, got %v", v.f, *f.(*file), err) 79 } 80 81 } 82 83 } 84 85 func TestWriteTextFile(t *testing.T) { 86 var test = []struct { 87 d string 88 start, end int 89 err string 90 f file 91 }{ 92 {d: "a\nb\n", start: 1, end: 3, f: file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}}, 93 {d: "b\nc\n", start: 2, end: 4, f: file{dot: 3, data: []byte("a\nb\nc\na\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}}}, 94 {d: "b\n", start: 2, end: 3, f: file{dot: 2, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}}, 95 {d: "a\n", start: 1, end: 2, f: file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}}, 96 {err: "file is 6 lines and [start, end] is [40, 1]", start: 40, end: 1, f: file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}}, 97 {err: "file is 6 lines and [start, end] is [1, 40]", start: 1, end: 40, f: file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}}, 98 {err: "file is 6 lines and [start, end] is [40, 60]", start: 40, end: 60, f: file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}}, 99 } 100 101 debug = t.Logf 102 for _, v := range test { 103 n, err := ioutil.TempFile("", "ed") 104 if err != nil { 105 t.Fatalf("TempFile: want nil, got %v", err) 106 } 107 defer os.Remove(n.Name()) 108 109 _, err = v.f.WriteFile(n.Name(), v.start, v.end) 110 if err != nil && v.err != err.Error() { 111 t.Errorf("Error Writing %v, want err \n%v got err \n%v", v.f, v.err, err) 112 continue 113 } 114 check, err := ioutil.ReadFile(n.Name()) 115 if err != nil { 116 t.Errorf("Error reading back %v: %v", n.Name(), err) 117 continue 118 } 119 if string(check) != v.d { 120 t.Errorf("Error reading back: want %v, got %v", v.d, string(check)) 121 } 122 123 } 124 125 } 126 127 func TestSimpleTextCommand(t *testing.T) { 128 var test = []struct { 129 c string 130 start, end int 131 err string 132 f *file 133 }{ 134 {c: "Z", err: "Z: unknown command", start: 1, end: 2, f: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}}, 135 {c: ".Z", err: "Z: unknown command", start: 1, end: 2, f: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}}, 136 {c: "4Z", err: "Z: unknown command", start: 1, end: 2, f: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}}, 137 {c: "1,3Z", err: "Z: unknown command", start: 1, end: 2, f: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}}, 138 {c: "/a/Z", err: "Z: unknown command", start: 1, end: 2, f: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}}, 139 } 140 141 for _, v := range test { 142 err := DoCommand(v.f, v.c) 143 if err != nil && v.err != err.Error() { 144 t.Error(err.Error()) 145 } 146 } 147 148 } 149 150 func TestFileTextCommand(t *testing.T) { 151 var test = []struct { 152 c string 153 start, end int 154 err string 155 res string 156 f file 157 }{ 158 {c: "e%s", start: 1, end: 7, f: file{dot: 1, data: []byte("a\nb\nc\na\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}}}, 159 {c: "0r%s", start: 1, end: 12, f: file{dot: 1, data: []byte("a\nb\nc\na\nb\nc\na\nb\nc\na\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22}}}, 160 } 161 162 n, err := ioutil.TempFile("", "ed") 163 if err != nil { 164 t.Fatalf("TempFile: want nil, got %v", err) 165 } 166 defer os.Remove(n.Name()) 167 168 d := "a\nb\nc\na\nb\nc\n" 169 if err := ioutil.WriteFile(n.Name(), []byte(d), 0666); err != nil { 170 t.Fatalf("writing test data %s: %v", d, err) 171 } 172 173 f, err := NewTextEditor(readerio(bytes.NewBufferString(d))) 174 if err != nil { 175 t.Fatal(err.Error()) 176 } 177 for _, v := range test { 178 cmd := fmt.Sprintf(v.c, n.Name()) 179 err := DoCommand(f, cmd) 180 t.Logf("f after %v command is %v", v.c, f) 181 if err != nil && v.err != err.Error() { 182 t.Error(err.Error()) 183 } 184 if err := v.f.Equal(f); err != nil { 185 t.Errorf("%v: want nil, got %v", cmd, err) 186 } 187 } 188 189 } 190 191 func TestFileDelete(t *testing.T) { 192 var test = []struct { 193 start, end int 194 fi *file 195 fo *file 196 }{ 197 { 198 start: 1, end: 2, 199 fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}, 200 fo: &file{dot: 1, data: []byte("b\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8}}, 201 }, 202 { 203 start: 1, end: 4, 204 fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}, 205 fo: &file{dot: 1, data: []byte("a\nb\nc"), lines: []int{0, 2, 4}}, 206 }, 207 } 208 209 debug = t.Logf 210 for _, v := range test { 211 v.fi.Replace([]byte{}, v.start, v.end) 212 if v.fi.dot != v.fo.dot { 213 t.Errorf("Delete [%d, %d]: want dot %v, got %v", v.start, v.end, v.fo.dot, v.fi.dot) 214 } 215 if !reflect.DeepEqual(v.fi.lines, v.fo.lines) { 216 t.Errorf("Delete [%d, %d]: want %v, got %v", v.start, v.end, v.fo.lines, v.fi.lines) 217 } 218 if !reflect.DeepEqual(v.fi.data, v.fo.data) { 219 t.Errorf("Delete [%d, %d]: want %v, got %v", v.start, v.end, v.fo.data, v.fi.data) 220 } 221 } 222 223 } 224 225 func TestFileDCommand(t *testing.T) { 226 var test = []struct { 227 c string 228 fi *file 229 err string 230 fo *file 231 }{ 232 { 233 c: "1d", 234 fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}, 235 fo: &file{dot: 1, data: []byte("b\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8}}, 236 }, 237 { 238 c: "1,3d", 239 fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}, 240 fo: &file{dot: 1, data: []byte("a\nb\nc"), lines: []int{0, 2, 4}}, 241 }, 242 } 243 244 debug = t.Logf 245 for _, v := range test { 246 err := DoCommand(v.fi, v.c) 247 if v.err == "" && err != nil { 248 t.Errorf("%v: want nil, got %v", v.c, err) 249 continue 250 } 251 if err != nil && err.Error() != v.err { 252 t.Errorf("%v: want %v, got %v", v.c, v.err, err) 253 continue 254 } 255 if v.fi.dot != v.fo.dot { 256 t.Errorf("want dot %v, got %v", v.fo.dot, v.fi.dot) 257 } 258 if !reflect.DeepEqual(v.fi.lines, v.fo.lines) { 259 t.Errorf("%v: want %v, got %v", v.c, v.fo.lines, v.fi.lines) 260 } 261 if !reflect.DeepEqual(v.fi.data, v.fo.data) { 262 t.Errorf("%v: want %v, got %v", v.c, v.fo.data, v.fi.data) 263 } 264 } 265 266 } 267 268 func TestFileSCommand(t *testing.T) { 269 var test = []struct { 270 c string 271 fi *file 272 err string 273 fo *file 274 }{ 275 { 276 c: "1s/a/b/", 277 fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}}, 278 fo: &file{dot: 1, data: []byte("b\nb\nc\na\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}}, 279 }, 280 { 281 c: "1,2s/a/A/g", 282 fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}, 283 fo: &file{dot: 1, data: []byte("A\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}, 284 }, 285 { 286 c: "1,$s/a/A/g", 287 fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}}, 288 fo: &file{dot: 1, data: []byte("A\nb\nc\nA\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}}, 289 }, 290 { 291 c: "1,$s/a/A/g", 292 fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}, 293 fo: &file{dot: 1, data: []byte("A\nb\nc\nA\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}}, 294 }, 295 } 296 297 debug = t.Logf 298 for _, v := range test { 299 err := DoCommand(v.fi, v.c) 300 if v.err == "" && err != nil { 301 t.Errorf("%v: want nil, got %v", v.c, err) 302 continue 303 } 304 if err != nil && err.Error() != v.err { 305 t.Errorf("%v: want %v, got %v", v.c, v.err, err) 306 continue 307 } 308 if v.fi.dot != v.fo.dot { 309 t.Errorf("want dot %v, got %v", v.fo.dot, v.fi.dot) 310 } 311 if !reflect.DeepEqual(v.fi.lines, v.fo.lines) { 312 t.Errorf("%v: want %v, got %v", v.c, v.fo.lines, v.fi.lines) 313 } 314 if !reflect.DeepEqual(v.fi.data, v.fo.data) { 315 t.Errorf("%v: want %v, got %v", v.c, v.fo.data, v.fi.data) 316 } 317 } 318 319 }