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  }