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 }