| // Copyright 2026 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package main |
| |
| import ( |
| "bytes" |
| "encoding/binary" |
| "fmt" |
| "os" |
| "reflect" |
| "testing" |
| |
| "cos.googlesource.com/cos/tools.git/src/pkg/tools/partutil" |
| ) |
| |
| func TestReadAllowlist(t *testing.T) { |
| mockContent := `defaultA=2 |
| defaultB=3 |
| gptpriority $grubdisk 2 prioA |
| gptpriority $grubdisk 4 prioB |
| |
| KERNEL_CMDLINE_ALLOWLIST="arg1=val1 arg2 arg3=val3" |
| menuentry "verified image A" { |
| linux /vmlinuz |
| } |
| ` |
| readEFIFileFunc = func(disk, path string) ([]byte, error) { |
| if path == partutil.GRUBCfgEFIPath { |
| return []byte(mockContent), nil |
| } |
| return nil, os.ErrNotExist |
| } |
| defer func() { |
| readEFIFileFunc = nil |
| }() |
| |
| allowlist, content, err := readAllowlist("") |
| if err != nil { |
| t.Fatalf("readAllowlist failed: %v", err) |
| } |
| |
| expected := []string{"arg1=val1", "arg2", "arg3=val3"} |
| if !reflect.DeepEqual(allowlist, expected) { |
| t.Errorf("expected %v, got %v", expected, allowlist) |
| } |
| if content != mockContent { |
| t.Errorf("expected content to match mockContent") |
| } |
| } |
| |
| func TestWriteAllowlist(t *testing.T) { |
| originalContent := `gptpriority $grubdisk 4 prioB |
| |
| KERNEL_CMDLINE_ALLOWLIST="arg1 arg2" |
| ` |
| var writtenData []byte |
| var writtenPath string |
| |
| writeEFIFileFunc = func(disk, path string, data []byte, perm os.FileMode) error { |
| writtenPath = path |
| writtenData = data |
| return nil |
| } |
| |
| err := writeAllowlist("", originalContent, []string{"arg1", "arg2", "arg3"}) |
| if err != nil { |
| t.Fatalf("writeAllowlist failed: %v", err) |
| } |
| |
| if writtenPath != partutil.GRUBCfgEFIPath { |
| t.Errorf("expected to write to %s, got %s", partutil.GRUBCfgEFIPath, writtenPath) |
| } |
| |
| expectedContent := `gptpriority $grubdisk 4 prioB |
| |
| KERNEL_CMDLINE_ALLOWLIST="arg1 arg2 arg3" |
| ` |
| if string(writtenData) != expectedContent { |
| t.Errorf("expected content:\n%s\ngot:\n%s", expectedContent, string(writtenData)) |
| } |
| } |
| |
| func TestReadBitfield(t *testing.T) { |
| readEFIFileFunc = func(disk, path string) ([]byte, error) { |
| if path != cmdlineExtraBinPath { |
| return nil, fmt.Errorf("unexpected path %s", path) |
| } |
| buf := new(bytes.Buffer) |
| // Write a sample bitfield: 5 = b101, which means args 0 and 2 are enabled |
| binary.Write(buf, binary.LittleEndian, uint32(5)) |
| return buf.Bytes(), nil |
| } |
| |
| bitfield, err := readBitfield("") |
| if err != nil { |
| t.Fatalf("readBitfield failed: %v", err) |
| } |
| |
| if bitfield != 5 { |
| t.Errorf("expected bitfield to be 5, got %d", bitfield) |
| } |
| } |
| |
| func TestReadBitfield_NotFound(t *testing.T) { |
| readEFIFileFunc = func(disk, path string) ([]byte, error) { |
| return nil, os.ErrNotExist |
| } |
| |
| bitfield, err := readBitfield("") |
| if err != nil { |
| t.Fatalf("readBitfield should not error for os.ErrNotExist, got: %v", err) |
| } |
| |
| if bitfield != 0 { |
| t.Errorf("expected default bitfield 0, got %d", bitfield) |
| } |
| } |
| |
| func TestWriteBitfield(t *testing.T) { |
| var writtenData []byte |
| var writtenPath string |
| |
| writeEFIFileFunc = func(disk, path string, data []byte, perm os.FileMode) error { |
| writtenPath = path |
| writtenData = data |
| return nil |
| } |
| |
| err := writeBitfield("", uint32(9)) // binary 1001 |
| if err != nil { |
| t.Fatalf("writeBitfield failed: %v", err) |
| } |
| |
| if writtenPath != cmdlineExtraBinPath { |
| t.Errorf("expected to write to %s, got %s", cmdlineExtraBinPath, writtenPath) |
| } |
| |
| var readBack uint32 |
| binary.Read(bytes.NewReader(writtenData), binary.LittleEndian, &readBack) |
| |
| if readBack != 9 { |
| t.Errorf("expected to write bitfield 9, but read back %d", readBack) |
| } |
| } |
| |
| |