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