github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/boot/ebda/ebda_test.go (about)

     1  // Copyright 2019 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 ebda
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/binary"
    10  	"strings"
    11  	"testing"
    12  )
    13  
    14  func checkErrPrefix(t *testing.T, testName string, prefix string, err error) {
    15  	if err != nil && prefix == "" {
    16  		t.Errorf("test %s expected no error, got %v", testName, err)
    17  	} else if err == nil && prefix != "" {
    18  		t.Errorf("test %s expected error beginning with %s, got nil", testName, prefix)
    19  	} else if err != nil && prefix != "" && !strings.HasPrefix(err.Error(), prefix) {
    20  		t.Errorf("test %s expected error beginning with %s, got %v", testName, prefix, err)
    21  	}
    22  }
    23  
    24  func checkEqualsEBDA(t *testing.T, testName string, e, g *EBDA) {
    25  	if e != nil && g == nil {
    26  		t.Errorf("test %s expected EBDA %v, got nil", testName, *e)
    27  	} else if e == nil && g != nil {
    28  		t.Errorf("test %s expected no EBDA, got %v", testName, *g)
    29  	} else if e != nil && g != nil {
    30  		if e.BaseOffset != g.BaseOffset || e.Length != g.Length || !bytes.Equal(e.Data, g.Data) {
    31  			t.Errorf("test %s expected EBDA: \n%v,\ngot:\n%v", testName, *e, *g)
    32  		}
    33  	}
    34  }
    35  
    36  func fakeEBDA(sizeKB int) []byte {
    37  	b := make([]byte, sizeKB*1024)
    38  	if sizeKB == 0 {
    39  		return append(b, make([]byte, 1024)...) // Helps us test weird edge cases
    40  	}
    41  	b[0] = byte(sizeKB)
    42  	copy(b[16:], []byte("UROOTEBDA"))
    43  	return b
    44  }
    45  
    46  func fakeDevMemEBDA(offset, sizeKB int) []byte {
    47  	b := make([]byte, offset)
    48  	binOffset := uint16(offset >> 4)
    49  	binary.LittleEndian.PutUint16(b[EBDAAddressOffset:EBDAAddressOffset+2], binOffset)
    50  	b = append(b, fakeEBDA(sizeKB)...)
    51  	return b
    52  }
    53  
    54  func TestFindEBDAOffset(t *testing.T) {
    55  	for _, tt := range []struct {
    56  		name      string
    57  		fakeMem   []byte
    58  		offset    int64
    59  		errPrefix string
    60  	}{
    61  		{
    62  			name:      "ReadFrom40EFail",
    63  			fakeMem:   make([]byte, 1),
    64  			errPrefix: "unable to read EBDA Pointer:",
    65  		},
    66  		{
    67  			name:      "EmptyEBDAPointerFail",
    68  			fakeMem:   make([]byte, EBDAAddressOffset+2),
    69  			errPrefix: "ebda offset is 0! unable to proceed",
    70  		},
    71  		{
    72  			name:    "FindEBDAOffsetSuccess",
    73  			fakeMem: fakeDevMemEBDA(0x9000, 1),
    74  			offset:  0x9000,
    75  		},
    76  	} {
    77  		t.Run(tt.name, func(t *testing.T) {
    78  			o, err := findEBDAOffset(bytes.NewReader(tt.fakeMem))
    79  			checkErrPrefix(t, tt.name, tt.errPrefix, err)
    80  			if o != tt.offset {
    81  				t.Errorf("test %s expected offset %v, got %v", tt.name, tt.offset, o)
    82  			}
    83  		})
    84  	}
    85  }
    86  
    87  func TestReadEBDA(t *testing.T) {
    88  	for _, tt := range []struct {
    89  		name      string
    90  		fakeMem   []byte
    91  		ebda      *EBDA
    92  		errPrefix string
    93  	}{
    94  		{
    95  			name:      "ReadSizeFail",
    96  			fakeMem:   fakeDevMemEBDA(0x9000, 1)[:0x9000], // Slice before length
    97  			errPrefix: "error reading EBDA length, got:",
    98  		},
    99  		{
   100  			name:      "ReadZeroSizeFail",
   101  			fakeMem:   fakeDevMemEBDA(0x9000, 0), // Fails because size is zero, so it tries to read to end of segment
   102  			errPrefix: "error reading EBDA region, tried to read from",
   103  		},
   104  		{
   105  			name:    "ReadEBDA",
   106  			fakeMem: fakeDevMemEBDA(0x9000, 1), // Fails because size is zero, so it tries to read to end of segment
   107  			ebda: &EBDA{
   108  				BaseOffset: 0x9000,
   109  				Length:     1024,
   110  				Data:       fakeEBDA(1),
   111  			},
   112  		},
   113  	} {
   114  		t.Run(tt.name, func(t *testing.T) {
   115  			g, err := ReadEBDA(bytes.NewReader(tt.fakeMem))
   116  			checkErrPrefix(t, tt.name, tt.errPrefix, err)
   117  			checkEqualsEBDA(t, tt.name, tt.ebda, g)
   118  		})
   119  	}
   120  }
   121  
   122  type MockByteReadWriteSeeker struct {
   123  	*bytes.Reader
   124  }
   125  
   126  func (MockByteReadWriteSeeker) Write(p []byte) (int, error) {
   127  	return len(p), nil
   128  }
   129  
   130  func TestWriteEBDA(t *testing.T) {
   131  	for _, tt := range []struct {
   132  		name      string
   133  		fakeMem   []byte
   134  		ebda      *EBDA
   135  		errPrefix string
   136  	}{
   137  		{
   138  			name:    "NoBaseOffsetFail",
   139  			fakeMem: make([]byte, 1),
   140  			ebda: &EBDA{
   141  				Length: 1024,
   142  				Data:   fakeEBDA(1),
   143  			},
   144  			errPrefix: "unable to read EBDA Pointer:",
   145  		},
   146  		{
   147  			name:    "UnalignedSizeFail",
   148  			fakeMem: fakeDevMemEBDA(0x9000, 1),
   149  			ebda: &EBDA{
   150  				Length: 1023,
   151  				Data:   fakeEBDA(1),
   152  			},
   153  			errPrefix: "length is not an integer multiple of 1 KiB, got",
   154  		},
   155  		{
   156  			name:    "MismatchedSizeFail",
   157  			fakeMem: fakeDevMemEBDA(0x9000, 1),
   158  			ebda: &EBDA{
   159  				BaseOffset: 0x9000,
   160  				Length:     1024,
   161  				Data:       fakeEBDA(2),
   162  			},
   163  			errPrefix: "length field is not equal to buffer length",
   164  		},
   165  		{
   166  			name:    "SizeTooBigFail",
   167  			fakeMem: fakeDevMemEBDA(0x9000, 1),
   168  			ebda: &EBDA{
   169  				BaseOffset: 0x9000,
   170  				Length:     256 * 1024,
   171  				Data:       fakeEBDA(256),
   172  			},
   173  			errPrefix: "length is greater than 255 KiB",
   174  		},
   175  		{
   176  			name:    "WriteEBDA",
   177  			fakeMem: fakeDevMemEBDA(0x9000, 1),
   178  			ebda: &EBDA{
   179  				BaseOffset: 0x9000,
   180  				Length:     1024,
   181  				Data:       fakeEBDA(1),
   182  			},
   183  		},
   184  	} {
   185  		t.Run(tt.name, func(t *testing.T) {
   186  			err := WriteEBDA(tt.ebda, MockByteReadWriteSeeker{bytes.NewReader(tt.fakeMem)})
   187  			checkErrPrefix(t, tt.name, tt.errPrefix, err)
   188  		})
   189  	}
   190  }