github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/exp/ed/filebuffer_test.go (about)

     1  // Copyright 2015-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  package main
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io"
    11  	"os"
    12  	"reflect"
    13  	"testing"
    14  
    15  	"github.com/google/go-cmp/cmp"
    16  )
    17  
    18  // Test all functions with func() int signatur
    19  var testTableInt = []struct {
    20  	name   string
    21  	in     *FileBuffer
    22  	exp    interface{}
    23  	method func(f *FileBuffer) int
    24  }{
    25  	{
    26  		name:   "Test Len: Len()=0",
    27  		in:     &FileBuffer{file: []int{}},
    28  		exp:    0,
    29  		method: (*FileBuffer).Len,
    30  	},
    31  	{
    32  		name:   "Test Len: Len()=4",
    33  		in:     &FileBuffer{file: []int{0, 1, 2, 3}},
    34  		exp:    4,
    35  		method: (*FileBuffer).Len,
    36  	},
    37  	{
    38  		name:   "Test GetAddr: GetAddr()=0",
    39  		in:     &FileBuffer{addr: 0},
    40  		exp:    0,
    41  		method: (*FileBuffer).GetAddr,
    42  	},
    43  	{
    44  		name:   "Test GetAddr: GetAddr()=4",
    45  		in:     &FileBuffer{addr: 4},
    46  		exp:    4,
    47  		method: (*FileBuffer).GetAddr,
    48  	},
    49  	{
    50  		name:   "Test Size: Size()=4",
    51  		in:     &FileBuffer{file: []int{0, 1, 2, 3}, buffer: []string{"0", "1", "2", "3"}},
    52  		exp:    4,
    53  		method: (*FileBuffer).Size,
    54  	},
    55  }
    56  
    57  func TestBasicFuncsInt(t *testing.T) {
    58  	for _, tt := range testTableInt {
    59  		t.Run(tt.name, func(t *testing.T) {
    60  			got := tt.method(tt.in)
    61  			if got != tt.exp {
    62  				t.Errorf("Expected value: %v, got: %v", tt.exp, got)
    63  			}
    64  		})
    65  	}
    66  }
    67  
    68  // Test Dirty
    69  var testTableDirty = []struct {
    70  	name   string
    71  	in     *FileBuffer
    72  	exp    interface{}
    73  	method func(f *FileBuffer) bool
    74  }{
    75  	{
    76  		name:   "Test Dirty: dirty = false",
    77  		in:     &FileBuffer{dirty: false},
    78  		exp:    false,
    79  		method: (*FileBuffer).Dirty,
    80  	},
    81  	{
    82  		name:   "Test Dirty: dirty = true",
    83  		in:     &FileBuffer{dirty: true},
    84  		exp:    true,
    85  		method: (*FileBuffer).Dirty,
    86  	},
    87  }
    88  
    89  func TestDirty(t *testing.T) {
    90  	for _, tt := range testTableDirty {
    91  		t.Run(tt.name, func(t *testing.T) {
    92  			got := tt.method(tt.in)
    93  			if got != tt.exp {
    94  				t.Errorf("Expected value: %v, got: %v", tt.exp, got)
    95  			}
    96  		})
    97  	}
    98  }
    99  
   100  // Test all functions with func() signatur
   101  var testTable = []struct {
   102  	name   string
   103  	in     *FileBuffer
   104  	exp    interface{}
   105  	method func(f *FileBuffer)
   106  }{
   107  	{
   108  		name:   "Test Touch",
   109  		in:     &FileBuffer{dirty: false, mod: false},
   110  		exp:    &FileBuffer{dirty: true, mod: true},
   111  		method: (*FileBuffer).Touch,
   112  	},
   113  	{
   114  		name:   "Test Start",
   115  		in:     &FileBuffer{mod: true, tmpFile: []int{}, file: []int{0, 1, 2, 3}, tmpAddr: 0, addr: 10, tmpDirty: false, dirty: true},
   116  		exp:    &FileBuffer{mod: false, tmpFile: []int{0, 1, 2, 3}, file: []int{0, 1, 2, 3}, tmpAddr: 10, addr: 10, tmpDirty: true, dirty: true},
   117  		method: (*FileBuffer).Start,
   118  	},
   119  	{
   120  		name:   "Test End",
   121  		in:     &FileBuffer{mod: true, lastFile: []int{}, tmpFile: []int{0, 1, 2, 3}, lastAddr: 0, tmpAddr: 10, lastDirty: false, tmpDirty: true},
   122  		exp:    &FileBuffer{mod: true, lastFile: []int{0, 1, 2, 3}, tmpFile: []int{0, 1, 2, 3}, lastAddr: 10, tmpAddr: 10, lastDirty: true, tmpDirty: true},
   123  		method: (*FileBuffer).End,
   124  	},
   125  	{
   126  		name:   "Test Rewind",
   127  		in:     &FileBuffer{mod: false, file: []int{}, lastFile: []int{0, 1, 2, 3}, addr: 0, lastAddr: 10, dirty: true, lastDirty: false},
   128  		exp:    &FileBuffer{mod: true, file: []int{0, 1, 2, 3}, lastFile: []int{0, 1, 2, 3}, addr: 10, lastAddr: 10, dirty: false, lastDirty: false},
   129  		method: (*FileBuffer).Rewind,
   130  	},
   131  	{
   132  		name:   "Test Clean",
   133  		in:     &FileBuffer{dirty: true, lastDirty: true, lastFile: []int{0, 1, 2, 3}, lastAddr: 10},
   134  		exp:    &FileBuffer{dirty: false, lastDirty: false, lastFile: []int{}, lastAddr: 0},
   135  		method: (*FileBuffer).Clean,
   136  	},
   137  }
   138  
   139  func TestBasicFuncs(t *testing.T) {
   140  	for _, tt := range testTable {
   141  		t.Run(tt.name, func(t *testing.T) {
   142  			tt.method(tt.in)
   143  			if !reflect.DeepEqual(tt.in, tt.exp) {
   144  				t.Errorf("Expected value: %v, got: %v", tt.exp, tt.in)
   145  			}
   146  		})
   147  	}
   148  }
   149  
   150  // Test NewFileBuffer
   151  var testTableNewFileBuffer = []struct {
   152  	name string
   153  	in   []string
   154  	exp  *FileBuffer
   155  }{
   156  	{
   157  		name: "Test NewFileBuffer",
   158  		in:   []string{"0", "1", "2", "3"},
   159  		exp:  &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}, dirty: false, mod: false, addr: 0, marks: make(map[byte]int)},
   160  	},
   161  }
   162  
   163  func TestNewFileBuffer(t *testing.T) {
   164  	for _, tt := range testTableNewFileBuffer {
   165  		t.Run(tt.name, func(t *testing.T) {
   166  			got := NewFileBuffer(tt.in)
   167  			if !reflect.DeepEqual(got, tt.exp) {
   168  				t.Errorf("Expected value: %v, got: %v", tt.exp, got)
   169  			}
   170  		})
   171  	}
   172  }
   173  
   174  // Test OOB
   175  var testTableOOB = []struct {
   176  	name     string
   177  	in       *FileBuffer
   178  	exp      interface{}
   179  	methodin int
   180  }{
   181  	{
   182  		name:     "Test OOB: return true",
   183  		in:       &FileBuffer{},
   184  		exp:      true,
   185  		methodin: 4,
   186  	},
   187  	{
   188  		name:     "Test OOB: return false",
   189  		in:       &FileBuffer{file: []int{0, 1, 2, 3}},
   190  		exp:      false,
   191  		methodin: 2,
   192  	},
   193  }
   194  
   195  func TestOOB(t *testing.T) {
   196  	for _, tt := range testTableOOB {
   197  		t.Run(tt.name, func(t *testing.T) {
   198  			got := tt.in.OOB(tt.methodin)
   199  			if !reflect.DeepEqual(got, tt.exp) {
   200  				t.Errorf("Expected value: %v, got: %v", tt.exp, got)
   201  			}
   202  		})
   203  	}
   204  }
   205  
   206  // Test GetMust
   207  var testTableGetMust = []struct {
   208  	name      string
   209  	in        *FileBuffer
   210  	exp       string
   211  	methodin1 int
   212  	methodin2 bool
   213  }{
   214  	{
   215  		name:      "Test GetMust",
   216  		in:        &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}},
   217  		exp:       "3",
   218  		methodin1: 3,
   219  		methodin2: true,
   220  	},
   221  }
   222  
   223  func TestGetMust(t *testing.T) {
   224  	for _, tt := range testTableGetMust {
   225  		t.Run(tt.name, func(t *testing.T) {
   226  			got := tt.in.GetMust(tt.methodin1, tt.methodin2)
   227  			if !reflect.DeepEqual(got, tt.exp) {
   228  				t.Errorf("Expected value: %v, got: %v", tt.exp, got)
   229  			}
   230  		})
   231  	}
   232  }
   233  
   234  // Test Get
   235  var testTableGet = []struct {
   236  	name     string
   237  	in       *FileBuffer
   238  	exp1     []string
   239  	exp2     error
   240  	methodin [2]int
   241  }{
   242  	{
   243  		name:     "Test Get: with OOB error",
   244  		in:       &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}},
   245  		exp1:     []string{},
   246  		exp2:     ErrOOB,
   247  		methodin: [2]int{0, 4},
   248  	},
   249  	{
   250  		name:     "Test Get: without OOB error",
   251  		in:       &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}},
   252  		exp1:     []string{"0", "1"},
   253  		exp2:     fmt.Errorf(""),
   254  		methodin: [2]int{0, 1},
   255  	},
   256  }
   257  
   258  func TestGet(t *testing.T) {
   259  	for _, tt := range testTableGet {
   260  		t.Run(tt.name, func(t *testing.T) {
   261  			got, err := tt.in.Get(tt.methodin)
   262  			if err != nil {
   263  				// Using cmp pkf with weird opt because reflect.DeepEqual does not work for empty string arrays
   264  				alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true })
   265  				opt := cmp.FilterValues(func(x, y interface{}) bool {
   266  					vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
   267  					return (vx.IsValid() && vy.IsValid() && vx.Type() == vy.Type()) &&
   268  						(vx.Kind() == reflect.Slice || vx.Kind() == reflect.Map) &&
   269  						(vx.Len() == 0 && vy.Len() == 0)
   270  				}, alwaysEqual)
   271  				if !cmp.Equal(got, tt.exp1, opt) || !reflect.DeepEqual(err.Error(), tt.exp2.Error()) {
   272  					t.Errorf("Expected values: %v, %v, got: %v, %v", tt.exp1, tt.exp2, got, err)
   273  				}
   274  			}
   275  		})
   276  	}
   277  }
   278  
   279  // Test Copy
   280  var testTableCopy = []struct {
   281  	name     string
   282  	in       *FileBuffer
   283  	exp      error
   284  	methodin [2]int
   285  }{
   286  	{
   287  		name:     "Test Copy: with OOB error",
   288  		in:       &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}},
   289  		exp:      ErrOOB,
   290  		methodin: [2]int{0, 4},
   291  	},
   292  	{
   293  		name:     "Test Copy: without OOB error",
   294  		in:       &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}},
   295  		exp:      nil,
   296  		methodin: [2]int{0, 1},
   297  	},
   298  }
   299  
   300  func TestCopy(t *testing.T) {
   301  	for _, tt := range testTableCopy {
   302  		t.Run(tt.name, func(t *testing.T) {
   303  			err := tt.in.Copy(tt.methodin)
   304  			if err != nil {
   305  				if !reflect.DeepEqual(err.Error(), tt.exp.Error()) {
   306  					t.Errorf("Expected value: %v, got: %v", tt.exp, err)
   307  				}
   308  
   309  			}
   310  		})
   311  	}
   312  }
   313  
   314  // Test Paste & Insert
   315  var testTablePasteInsert = []struct {
   316  	name     string
   317  	in       *FileBuffer
   318  	exp      error
   319  	methodin int
   320  }{
   321  	{
   322  		name:     "Test Paste & Insert: with OOB error",
   323  		in:       &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}},
   324  		exp:      ErrOOB,
   325  		methodin: 5,
   326  	},
   327  	{
   328  		name:     "Test Paste & Insert: without OOB error and nlines == 0",
   329  		in:       &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}},
   330  		exp:      nil,
   331  		methodin: 1,
   332  	},
   333  	{
   334  		name:     "Test Paste & Insert: without OOB error and nlines != 0",
   335  		in:       &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}, cbuf: []string{"0", "1", "2", "3"}},
   336  		exp:      nil,
   337  		methodin: 1,
   338  	},
   339  }
   340  
   341  func TestPasteInsert(t *testing.T) {
   342  	for _, tt := range testTablePasteInsert {
   343  		t.Run(tt.name, func(t *testing.T) {
   344  			err := tt.in.Paste(tt.methodin)
   345  			if err != nil {
   346  				if !reflect.DeepEqual(err.Error(), tt.exp.Error()) {
   347  					t.Errorf("Expected value: %v, got: %v", tt.exp, err)
   348  				}
   349  			}
   350  		})
   351  	}
   352  }
   353  
   354  // Test Delete
   355  var testTableDelete = []struct {
   356  	name     string
   357  	in       *FileBuffer
   358  	exp      error
   359  	methodin [2]int
   360  }{
   361  	{
   362  		name:     "Test Delete: with OOB error",
   363  		in:       &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}},
   364  		exp:      ErrOOB,
   365  		methodin: [2]int{0, 4},
   366  	},
   367  	{
   368  		name:     "Test Delete: without OOB error and addr OOB edge case",
   369  		in:       &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}},
   370  		exp:      nil,
   371  		methodin: [2]int{0, 3},
   372  	},
   373  }
   374  
   375  func TestDelete(t *testing.T) {
   376  	for _, tt := range testTableDelete {
   377  		t.Run(tt.name, func(t *testing.T) {
   378  			err := tt.in.Delete(tt.methodin)
   379  			if err != nil {
   380  				if !reflect.DeepEqual(err.Error(), tt.exp.Error()) {
   381  					t.Errorf("Expected value: %v, got: %v", tt.exp, err)
   382  				}
   383  			}
   384  		})
   385  	}
   386  }
   387  
   388  // Test SetAddr
   389  var testTableSetAddr = []struct {
   390  	name     string
   391  	in       *FileBuffer
   392  	exp      error
   393  	methodin int
   394  }{
   395  	{
   396  		name:     "Test SetAddr: with OOB error",
   397  		in:       &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}},
   398  		exp:      ErrOOB,
   399  		methodin: 4,
   400  	},
   401  	{
   402  		name:     "Test SetAddr: without OOB error and addr OOB edge case",
   403  		in:       &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}},
   404  		exp:      nil,
   405  		methodin: 0,
   406  	},
   407  }
   408  
   409  func TestSetAddr(t *testing.T) {
   410  	for _, tt := range testTableSetAddr {
   411  		t.Run(tt.name, func(t *testing.T) {
   412  			err := tt.in.SetAddr(tt.methodin)
   413  			if err != nil {
   414  				if err.Error() != tt.exp.Error() {
   415  					t.Errorf("Expected value: %v, got: %v", tt.exp, err)
   416  				}
   417  			} else {
   418  				if tt.methodin != tt.in.addr {
   419  					t.Errorf("Expected value: %v, got: %v", tt.methodin, tt.in.addr)
   420  				}
   421  			}
   422  		})
   423  	}
   424  }
   425  
   426  // Test SetMark
   427  var testTableSetMark = []struct {
   428  	name      string
   429  	in        *FileBuffer
   430  	exp       int
   431  	err       error
   432  	methodin1 byte
   433  	methodin2 int
   434  }{
   435  	{
   436  		name:      "Test SetMark: with OOB error",
   437  		in:        &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}, marks: make(map[byte]int)},
   438  		exp:       0,
   439  		err:       ErrOOB,
   440  		methodin1: 0,
   441  		methodin2: 5,
   442  	},
   443  	{
   444  		name:      "Test SetMark: without OOB error",
   445  		in:        &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}, marks: make(map[byte]int)},
   446  		exp:       3,
   447  		err:       ErrOOB,
   448  		methodin1: 0,
   449  		methodin2: 3,
   450  	},
   451  }
   452  
   453  func TestSetMark(t *testing.T) {
   454  	for _, tt := range testTableSetMark {
   455  		t.Run(tt.name, func(t *testing.T) {
   456  			err := tt.in.SetMark(tt.methodin1, tt.methodin2)
   457  			if err != nil {
   458  				if err.Error() != tt.err.Error() {
   459  					t.Errorf("Expected value: %v, got: %v", tt.exp, err)
   460  				}
   461  			} else {
   462  				if tt.exp != tt.in.marks[0] {
   463  					t.Errorf("Expected value: %v, got: %v", tt.exp, tt.in.marks[0])
   464  				}
   465  			}
   466  		})
   467  	}
   468  }
   469  
   470  // Test GetMark
   471  var testTableGetMark = []struct {
   472  	name     string
   473  	in       *FileBuffer
   474  	exp      int
   475  	err      int
   476  	methodin byte
   477  }{
   478  	{
   479  		name:     "Test GetMark: with error",
   480  		in:       &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}, marks: make(map[byte]int)},
   481  		exp:      0,
   482  		err:      -1,
   483  		methodin: 0x00,
   484  	},
   485  	{
   486  		name:     "Test GetMark: without error",
   487  		in:       &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}, marks: make(map[byte]int)},
   488  		exp:      1,
   489  		err:      0,
   490  		methodin: 0x01,
   491  	},
   492  	{
   493  		name:     "Test GetMark: without second error",
   494  		in:       &FileBuffer{marks: make(map[byte]int)},
   495  		exp:      1,
   496  		err:      -1,
   497  		methodin: 0x01,
   498  	},
   499  }
   500  
   501  func TestGetMark(t *testing.T) {
   502  	for _, tt := range testTableGetMark {
   503  		t.Run(tt.name, func(t *testing.T) {
   504  			tt.in.marks[1] = 1
   505  			got, err := tt.in.GetMark(tt.methodin)
   506  			if err != nil {
   507  				if got != tt.err {
   508  					t.Errorf("Expected value: %v, got: %v", tt.err, err)
   509  				}
   510  			} else {
   511  				if reflect.DeepEqual(got, tt.in.marks[0]) {
   512  					t.Errorf("Expected value: %v, got: %v", tt.exp, got)
   513  				}
   514  			}
   515  		})
   516  	}
   517  }
   518  
   519  // Test Read
   520  var testTableRead = []struct {
   521  	name      string
   522  	in        *FileBuffer
   523  	err       error
   524  	methodin1 int
   525  	methodin2 io.Reader
   526  }{
   527  	{
   528  		name:      "Test Read",
   529  		in:        &FileBuffer{},
   530  		err:       nil,
   531  		methodin1: 0,
   532  		methodin2: &bytes.Buffer{},
   533  	},
   534  }
   535  
   536  func TestRead(t *testing.T) {
   537  	for _, tt := range testTableRead {
   538  		t.Run(tt.name, func(t *testing.T) {
   539  			err := tt.in.Read(tt.methodin1, tt.methodin2)
   540  			if err != nil {
   541  				if err != tt.err {
   542  					t.Errorf("Expected value: %v, got: %v", tt.err, err)
   543  				}
   544  			}
   545  		})
   546  	}
   547  }
   548  
   549  // Test ReadFile
   550  func CreateFile(name string) string {
   551  	f, err := os.Create(name)
   552  	if err != nil {
   553  		return ""
   554  	}
   555  	defer f.Close()
   556  	f.Write([]byte{0x01})
   557  	return f.Name()
   558  }
   559  
   560  var testTableReadFile = []struct {
   561  	name      string
   562  	in        *FileBuffer
   563  	err       error
   564  	methodin1 int
   565  	methodin2 string
   566  }{
   567  	{
   568  		name:      "Test ReadFile: file exists",
   569  		in:        &FileBuffer{},
   570  		err:       nil,
   571  		methodin1: 0,
   572  		methodin2: CreateFile("readfile"),
   573  	},
   574  	{
   575  		name:      "Test ReadFile: file does not exist",
   576  		in:        &FileBuffer{},
   577  		err:       fmt.Errorf("could not read file: open dir: no such file or directory"),
   578  		methodin1: 0,
   579  		methodin2: "dir",
   580  	},
   581  }
   582  
   583  func TestReadFile(t *testing.T) {
   584  	for _, tt := range testTableReadFile {
   585  		t.Run(tt.name, func(t *testing.T) {
   586  			err := tt.in.ReadFile(tt.methodin1, tt.methodin2)
   587  			if err != nil {
   588  				if err.Error() != tt.err.Error() {
   589  					t.Errorf("Expected value: %v, got: %v", tt.err, err)
   590  				}
   591  			}
   592  			os.Remove(tt.methodin2)
   593  
   594  		})
   595  	}
   596  }
   597  
   598  // Test FileToBuffer
   599  var testTableFileToBuffer = []struct {
   600  	name     string
   601  	in       *FileBuffer
   602  	exp      *FileBuffer
   603  	err      error
   604  	methodin string
   605  }{
   606  	{
   607  		name:     "Test FileToBuffer: file exists",
   608  		in:       &FileBuffer{},
   609  		exp:      &FileBuffer{mod: true, file: []int{0}},
   610  		err:      fmt.Errorf(""),
   611  		methodin: CreateFile("filetobuffer"),
   612  	},
   613  	{
   614  		name:     "Test FileToBuffer: file does not exist",
   615  		in:       &FileBuffer{},
   616  		exp:      NewFileBuffer(nil),
   617  		err:      fmt.Errorf("could not read file: open %s: no such file or directory", "dir"),
   618  		methodin: "dir",
   619  	},
   620  }
   621  
   622  func TestFileToBuffer(t *testing.T) {
   623  	for _, tt := range testTableFileToBuffer {
   624  		t.Run(tt.name, func(t *testing.T) {
   625  			got, err := FileToBuffer(tt.methodin)
   626  			if err != nil {
   627  				if err.Error() != tt.err.Error() {
   628  					t.Errorf("Expected value: %v, got: %v", tt.err, err)
   629  				}
   630  			} else if reflect.DeepEqual(tt.exp, got) {
   631  				t.Errorf("Expected value: %v, got: %v", tt.exp, got)
   632  			}
   633  			os.Remove(tt.methodin)
   634  		})
   635  	}
   636  }