github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/mount/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", b.String()) 221 t.Fatalf("Reading back new header: new:%s\n%v", n, err) 222 } 223 }