github.com/ratrocket/u-root@v0.0.0-20180201221235-1cf9f48ee2cf/pkg/gpt/gpt_test.go (about)

     1  package gpt
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"io"
     7  	"reflect"
     8  	"testing"
     9  
    10  	"github.com/google/uuid"
    11  )
    12  
    13  const (
    14  	equalHeaderError = "p.Signature(0x5452415020494646) != b.Signature(0x5452415020494645); p.Revision(65537) != b.Revision(65536); p.HeaderSize(93) != b.HeaderSize(92); p.CurrentLBA(0x2) != b.BackupLBA(0x1); p.FirstLBA(0x23) != b.FirstLBA(0x22); p.LastLBA(0x43cf9f) != b.LastLBA(0x43cf9e); p.DiskGUID(0x32653165643462612d656639332d346162302d383436652d326533613661326437336266) != b.DiskGUID(0x32643165643462612d656639332d346162302d383436652d326533613661326437336266); p.NPart(127) != b.NPart(128); p.PartSize(127) != b.PartSize(128)"
    15  	equalPartsError  = "Partition 3: p.PartGUID(0x35653261336166652d333234662d613734312d623732352d616363633332383561333039) != b.PartGUID(0x35643261336166652d333234662d613734312d623732352d616363633332383561333039); Partition 8: p.UniqueGUID(0x65643939336135312d336563342d346131342d383339382d613437613765366165343263) != b.UniqueGUID(0x65643938336135312d336563342d346131342d383339382d613437613765366165343263); Partition 11: p.FirstLBA(0x3d001) != b.FirstLBA(0x3d000); Partition 21: p.LastLBA(0x1) != b.LastLBA(0x0); Partition 61: p.Name(0x000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) != b.Name(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)"
    16  )
    17  
    18  var (
    19  	header = Header{
    20  		Signature:  Signature,
    21  		Revision:   Revision,
    22  		HeaderSize: HeaderSize,
    23  		CRC:        0x22519292,
    24  		Reserved:   0,
    25  		CurrentLBA: 1,
    26  		BackupLBA:  0x43cfbf,
    27  		FirstLBA:   0x22,
    28  		LastLBA:    0x43cf9e,
    29  		DiskGUID:   uuid.Must(uuid.Parse("2d1ed4ba-ef93-4ab0-846e-2e3a6a2d73bf")),
    30  		PartStart:  2,
    31  		NPart:      MaxNPart,
    32  		PartSize:   0x80, // This is not constant, but was used for this chromeos disk.
    33  		PartCRC:    0x8d728e57,
    34  	}
    35  	disk = make([]byte, 0x100000000)
    36  )
    37  
    38  func InstallGPT() {
    39  	for i, d := range block {
    40  		copy(disk[i:], d)
    41  	}
    42  }
    43  
    44  func TestGPTTable(t *testing.T) {
    45  	var tests = []struct {
    46  		mangle int
    47  		msg    string
    48  	}{
    49  		{-1, ""},
    50  		{0x8, "Primary GPT revision (100ff) is not supported value (10000)"},
    51  		{0x0, "Primary GPT signature invalid (54524150204946ff), needs to be 5452415020494645"},
    52  		{0xf, "Primary GPT HeaderSize (ff00005c) is not supported value (5c)"},
    53  		{0x51, "Primary GPT MaxNPart (ff80) is above maximum of 80"},
    54  		{0x59, "Primary Partition CRC: Header {\n\t\"Signature\": 6075990659671082565,\n\t\"Revision\": 65536,\n\t\"HeaderSize\": 92,\n\t\"CRC\": 575771282,\n\t\"Reserved\": 0,\n\t\"CurrentLBA\": 1,\n\t\"BackupLBA\": 4444095,\n\t\"FirstLBA\": 34,\n\t\"LastLBA\": 4444062,\n\t\"DiskGUID\": \"2d1ed4ba-ef93-4ab0-846e-2e3a6a2d73bf\",\n\t\"PartStart\": 2,\n\t\"NPart\": 128,\n\t\"PartSize\": 128,\n\t\"PartCRC\": 2373123927,\n\t\"Parts\": null\n}, computed checksum is 8d728e57, header has 8d72ff57"},
    55  		{0x10, "Primary Header CRC: computed checksum is 22519292, header has 225192ff"},
    56  	}
    57  
    58  	for _, test := range tests {
    59  		InstallGPT()
    60  		if test.mangle > -1 {
    61  			disk[BlockSize+test.mangle] = 0xff
    62  
    63  		}
    64  		r := bytes.NewReader(disk)
    65  		g, err := Table(r, BlockSize)
    66  		if err != nil {
    67  			if err.Error() != test.msg {
    68  				t.Errorf("New GPT: got %q, want %q", err, test.msg)
    69  				continue
    70  			}
    71  			t.Logf("Got expected error %q", err)
    72  			continue
    73  		}
    74  
    75  		if err == nil && test.msg != "" {
    76  			t.Errorf("New GPT: got nil, want %s", test.msg)
    77  			continue
    78  		}
    79  
    80  		t.Logf("New GPT: %s", g)
    81  		if !reflect.DeepEqual(header, g.Header) {
    82  			t.Errorf("Check UUID equality from\n%v to\n%v: got false, want true", header, g.Header)
    83  			continue
    84  		}
    85  	}
    86  
    87  }
    88  
    89  // TestGPTTtables tests whether we can match the primary and backup
    90  // or, if they differ, we catch that error.
    91  // We know from other tests that the tables read fine.
    92  // This test verifies that they match and that therefore we
    93  // are able to read the backup table and test that it is ok.
    94  func TestGPTTables(t *testing.T) {
    95  	var tests = []struct {
    96  		mangle int
    97  		what   string
    98  	}{
    99  		{-1, "No error test"},
   100  		{0x10, "Should differ test"},
   101  	}
   102  
   103  	for _, test := range tests {
   104  		InstallGPT()
   105  		if test.mangle > -1 {
   106  			disk[BlockSize+test.mangle] = 0xff
   107  		}
   108  		r := bytes.NewReader(disk)
   109  		_, _, err := New(r)
   110  		switch {
   111  		case err != nil && test.mangle > -1:
   112  			t.Logf("Got expected error %s", test.what)
   113  		case err != nil && test.mangle == -1:
   114  			t.Errorf("%s: got %s, want nil", test.what, err)
   115  			continue
   116  		case err == nil && test.mangle > -1:
   117  			t.Errorf("%s: got nil, want err", test.what)
   118  			continue
   119  		}
   120  		t.Logf("Passed %s", test.what)
   121  	}
   122  }
   123  
   124  // TestEqualHeader tests all variations of headers not being equal.
   125  // We test to make sure it works, then break some aspect of the header
   126  // and test that too.
   127  func TestEqualHeader(t *testing.T) {
   128  	InstallGPT()
   129  	r := bytes.NewReader(disk)
   130  	p, b, err := New(r)
   131  	if err != nil {
   132  		t.Fatalf("TestEqualHeader: Reading in gpt: got %v, want nil", err)
   133  	}
   134  
   135  	if err := EqualHeader(p.Header, b.Header); err != nil {
   136  		t.Fatalf("TestEqualHeader: got %v, want nil", err)
   137  	}
   138  	// Yes, we assume a certain order, but it sure simplifies the test :-)
   139  	p.Signature++
   140  	p.Revision++
   141  	p.HeaderSize++
   142  	p.CurrentLBA++
   143  	p.FirstLBA++
   144  	p.LastLBA++
   145  	p.DiskGUID[0]++
   146  	p.NPart--
   147  	p.PartSize--
   148  	p.PartCRC++
   149  	if err = EqualHeader(p.Header, b.Header); err == nil {
   150  		t.Fatalf("TestEqualHeader: got %v, want nil", err)
   151  	}
   152  	t.Logf("TestEqualHeader: EqualHeader returns %v", err)
   153  
   154  	if err.Error() != equalHeaderError {
   155  		t.Fatalf("TestEqualHeader: got %v, want %v", err.Error(), equalHeaderError)
   156  	}
   157  
   158  }
   159  
   160  func TestEqualParts(t *testing.T) {
   161  	InstallGPT()
   162  	r := bytes.NewReader(disk)
   163  	p, b, err := New(r)
   164  	if err != nil {
   165  		t.Fatalf("TestEqualParts: Reading in gpt: got %v, want nil", err)
   166  	}
   167  
   168  	if err = EqualParts(p, b); err != nil {
   169  		t.Fatalf("TestEqualParts: Checking equality: got %v, want nil", err)
   170  	}
   171  	// Test some equality things before we do the 'length is the same' test
   172  	// Note that testing the NParts header variable is done in the HeaderTest
   173  	p.Parts[3].PartGUID[0]++
   174  	p.Parts[8].UniqueGUID[1]++
   175  	p.Parts[11].FirstLBA++
   176  	p.Parts[21].LastLBA++
   177  	p.Parts[53].Attribute++
   178  	p.Parts[61].Name[1]++
   179  	if err = EqualParts(p, b); err == nil {
   180  		t.Errorf("TestEqualParts: Checking equality: got nil, want '%v'", equalPartsError)
   181  	}
   182  	if err.Error() != equalPartsError {
   183  		t.Errorf("TestEqualParts: Checking equality: got '%v', want '%v'", err, equalPartsError)
   184  	}
   185  
   186  	if err = EqualParts(p, b); err == nil {
   187  		t.Errorf("TestEqualParts: Checking number of parts: got nil, want 'Primary Number of partitions (127) differs from Backup (128)'")
   188  	}
   189  
   190  }
   191  
   192  type iodisk []byte
   193  
   194  func (d *iodisk) WriteAt(b []byte, off int64) (int, error) {
   195  	copy([]byte(*d)[off:], b)
   196  	return len(b), nil
   197  }
   198  
   199  func TestWrite(t *testing.T) {
   200  	InstallGPT()
   201  	r := bytes.NewReader(disk)
   202  	g, err := Table(r, BlockSize)
   203  	if err != nil {
   204  		t.Fatalf("Reading table: got %v, want nil", err)
   205  	}
   206  	var targ = make(iodisk, len(disk))
   207  
   208  	if err := Write(&targ, g); err != nil {
   209  		t.Fatalf("Writing: got %v, want nil", err)
   210  	}
   211  	if n, err := Table(bytes.NewReader([]byte(targ)), BlockSize); err != nil {
   212  		t.Logf("Old GPT: %s", g)
   213  		var b bytes.Buffer
   214  		w := hex.Dumper(&b)
   215  		io.Copy(w, bytes.NewReader(disk[:4096]))
   216  		t.Logf("%s\n", string(b.Bytes()))
   217  		t.Fatalf("Reading back new header: new:%s\n%v", n, err)
   218  	}
   219  }