github.com/ratrocket/u-root@v0.0.0-20180201221235-1cf9f48ee2cf/cmds/ed/ed_test.go (about)

     1  // iopyright 2012-2017 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  		// We are adding the file after a 0-length slice
    65  		// We want dot to be at the point we added it.
    66  		f.Move(v.where)
    67  		r = bytes.NewBufferString(v.d)
    68  		_, err = f.Read(r, v.where, v.where)
    69  		if err != nil {
    70  			t.Errorf("Error reading %v: %v", v.d, err)
    71  			continue
    72  		}
    73  		if err := v.f.Equal(f); err != nil {
    74  			t.Errorf("%v vs. %v: want nil, got %v", v.f, *f.(*file), err)
    75  		}
    76  
    77  	}
    78  
    79  }
    80  
    81  func TestWriteTextFile(t *testing.T) {
    82  	var test = []struct {
    83  		d          string
    84  		start, end int
    85  		err        string
    86  		f          file
    87  	}{
    88  		{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}}},
    89  		{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}}},
    90  		{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}}},
    91  		{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}}},
    92  		{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}}},
    93  		{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}}},
    94  		{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}}},
    95  	}
    96  
    97  	debug = t.Logf
    98  	for _, v := range test {
    99  		n, err := ioutil.TempFile("", "ed")
   100  		if err != nil {
   101  			t.Fatalf("TempFile: want nil, got %v", err)
   102  		}
   103  		defer os.Remove(n.Name())
   104  
   105  		_, err = v.f.WriteFile(n.Name(), v.start, v.end)
   106  		if err != nil && v.err != err.Error() {
   107  			t.Errorf("Error Writing %v, want err \n%v got err \n%v", v.f, v.err, err)
   108  			continue
   109  		}
   110  		check, err := ioutil.ReadFile(n.Name())
   111  		if err != nil {
   112  			t.Errorf("Error reading back %v: %v", n.Name(), err)
   113  			continue
   114  		}
   115  		if string(check) != v.d {
   116  			t.Errorf("Error reading back: want %v, got %v", v.d, string(check))
   117  		}
   118  
   119  	}
   120  
   121  }
   122  
   123  func TestSimpleTextCommand(t *testing.T) {
   124  	var test = []struct {
   125  		c          string
   126  		start, end int
   127  		err        string
   128  		f          *file
   129  	}{
   130  		{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}}},
   131  		{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}}},
   132  		{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}}},
   133  		{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}}},
   134  		{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}}},
   135  	}
   136  
   137  	for _, v := range test {
   138  		err := DoCommand(v.f, v.c)
   139  		if err != nil && v.err != err.Error() {
   140  			t.Error(err.Error())
   141  		}
   142  	}
   143  
   144  }
   145  
   146  func TestFileTextCommand(t *testing.T) {
   147  	var test = []struct {
   148  		c          string
   149  		start, end int
   150  		err        string
   151  		res        string
   152  		f          file
   153  	}{
   154  		{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}}},
   155  		{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}}},
   156  	}
   157  
   158  	n, err := ioutil.TempFile("", "ed")
   159  	if err != nil {
   160  		t.Fatalf("TempFile: want nil, got %v", err)
   161  	}
   162  	defer os.Remove(n.Name())
   163  
   164  	d := "a\nb\nc\na\nb\nc\n"
   165  	if err := ioutil.WriteFile(n.Name(), []byte(d), 0666); err != nil {
   166  		t.Fatalf("writing test data %s: %v", d, err)
   167  	}
   168  
   169  	f, err := NewTextEditor(readerio(bytes.NewBufferString(d)))
   170  	if err != nil {
   171  		t.Fatal(err.Error())
   172  	}
   173  	for _, v := range test {
   174  		cmd := fmt.Sprintf(v.c, n.Name())
   175  		err := DoCommand(f, cmd)
   176  		t.Logf("f after %v command is %v", v.c, f)
   177  		if err != nil && v.err != err.Error() {
   178  			t.Error(err.Error())
   179  		}
   180  		if err := v.f.Equal(f); err != nil {
   181  			t.Errorf("%v: want nil, got %v", cmd, err)
   182  		}
   183  	}
   184  
   185  }
   186  
   187  func TestFileDelete(t *testing.T) {
   188  	var test = []struct {
   189  		start, end int
   190  		fi         *file
   191  		fo         *file
   192  	}{
   193  		{
   194  			start: 1, end: 2,
   195  			fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}},
   196  			fo: &file{dot: 1, data: []byte("b\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8}},
   197  		},
   198  		{
   199  			start: 1, end: 4,
   200  			fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}},
   201  			fo: &file{dot: 1, data: []byte("a\nb\nc"), lines: []int{0, 2, 4}},
   202  		},
   203  	}
   204  
   205  	debug = t.Logf
   206  	for _, v := range test {
   207  		v.fi.Replace([]byte{}, v.start, v.end)
   208  		if v.fi.dot != v.fo.dot {
   209  			t.Errorf("Delete [%d, %d]: want dot %v, got %v", v.start, v.end, v.fo.dot, v.fi.dot)
   210  		}
   211  		if !reflect.DeepEqual(v.fi.lines, v.fo.lines) {
   212  			t.Errorf("Delete [%d, %d]: want %v, got %v", v.start, v.end, v.fo.lines, v.fi.lines)
   213  		}
   214  		if !reflect.DeepEqual(v.fi.data, v.fo.data) {
   215  			t.Errorf("Delete [%d, %d]: want %v, got %v", v.start, v.end, v.fo.data, v.fi.data)
   216  		}
   217  	}
   218  
   219  }
   220  
   221  func TestFileDCommand(t *testing.T) {
   222  	var test = []struct {
   223  		c   string
   224  		fi  *file
   225  		err string
   226  		fo  *file
   227  	}{
   228  		{
   229  			c:  "1d",
   230  			fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}},
   231  			fo: &file{dot: 1, data: []byte("b\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8}},
   232  		},
   233  		{
   234  			c:  "1,3d",
   235  			fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}},
   236  			fo: &file{dot: 1, data: []byte("a\nb\nc"), lines: []int{0, 2, 4}},
   237  		},
   238  	}
   239  
   240  	debug = t.Logf
   241  	for _, v := range test {
   242  		err := DoCommand(v.fi, v.c)
   243  		if v.err == "" && err != nil {
   244  			t.Errorf("%v: want nil, got %v", v.c, err)
   245  			continue
   246  		}
   247  		if err != nil && err.Error() != v.err {
   248  			t.Errorf("%v: want %v, got %v", v.c, v.err, err)
   249  			continue
   250  		}
   251  		if v.fi.dot != v.fo.dot {
   252  			t.Errorf("want dot %v, got %v", v.fo.dot, v.fi.dot)
   253  		}
   254  		if !reflect.DeepEqual(v.fi.lines, v.fo.lines) {
   255  			t.Errorf("%v: want %v, got %v", v.c, v.fo.lines, v.fi.lines)
   256  		}
   257  		if !reflect.DeepEqual(v.fi.data, v.fo.data) {
   258  			t.Errorf("%v: want %v, got %v", v.c, v.fo.data, v.fi.data)
   259  		}
   260  	}
   261  
   262  }
   263  
   264  func TestFileSCommand(t *testing.T) {
   265  	var test = []struct {
   266  		c   string
   267  		fi  *file
   268  		err string
   269  		fo  *file
   270  	}{
   271  		{
   272  			c:  "1s/a/b/",
   273  			fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}},
   274  			fo: &file{dot: 1, data: []byte("b\nb\nc\na\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}},
   275  		},
   276  		{
   277  			c:  "1,2s/a/A/g",
   278  			fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}},
   279  			fo: &file{dot: 1, data: []byte("A\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}},
   280  		},
   281  		{
   282  			c:  "1,$s/a/A/g",
   283  			fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}},
   284  			fo: &file{dot: 1, data: []byte("A\nb\nc\nA\nb\nc\n"), lines: []int{0, 2, 4, 6, 8, 10}},
   285  		},
   286  		{
   287  			c:  "1,$s/a/A/g",
   288  			fi: &file{dot: 1, data: []byte("a\nb\nc\na\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}},
   289  			fo: &file{dot: 1, data: []byte("A\nb\nc\nA\nb\nc"), lines: []int{0, 2, 4, 6, 8, 10}},
   290  		},
   291  	}
   292  
   293  	debug = t.Logf
   294  	for _, v := range test {
   295  		err := DoCommand(v.fi, v.c)
   296  		if v.err == "" && err != nil {
   297  			t.Errorf("%v: want nil, got %v", v.c, err)
   298  			continue
   299  		}
   300  		if err != nil && err.Error() != v.err {
   301  			t.Errorf("%v: want %v, got %v", v.c, v.err, err)
   302  			continue
   303  		}
   304  		if v.fi.dot != v.fo.dot {
   305  			t.Errorf("want dot %v, got %v", v.fo.dot, v.fi.dot)
   306  		}
   307  		if !reflect.DeepEqual(v.fi.lines, v.fo.lines) {
   308  			t.Errorf("%v: want %v, got %v", v.c, v.fo.lines, v.fi.lines)
   309  		}
   310  		if !reflect.DeepEqual(v.fi.data, v.fo.data) {
   311  			t.Errorf("%v: want %v, got %v", v.c, v.fo.data, v.fi.data)
   312  		}
   313  	}
   314  
   315  }