github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/dt/fdt_test.go (about)

     1  // Copyright 2019 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  package dt
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/json"
    10  	"errors"
    11  	"os"
    12  	"os/exec"
    13  	"path/filepath"
    14  	"reflect"
    15  	"strings"
    16  	"testing"
    17  )
    18  
    19  func TestLoadFDT(t *testing.T) {
    20  	jsonData, err := os.ReadFile("testdata/fdt.json")
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  	testData := &FDT{}
    25  	if err := json.Unmarshal(jsonData, testData); err != nil {
    26  		t.Fatal(err)
    27  	}
    28  
    29  	// 1. Load by path given and succeed.
    30  	dtb, err := os.Open("testdata/fdt.dtb")
    31  	if err != nil {
    32  		t.Fatal(err)
    33  	}
    34  	fdt, err := LoadFDT(dtb)
    35  	if err != nil {
    36  		t.Fatal(err)
    37  	}
    38  	if !reflect.DeepEqual(fdt, testData) {
    39  		got, err := json.MarshalIndent(fdt, "", "    ")
    40  		if err != nil {
    41  			t.Fatal(err)
    42  		}
    43  		t.Errorf(`Read("fdt.dtb") = %s \n, want %s`, got, jsonData)
    44  	}
    45  
    46  	dir := t.TempDir()
    47  	nonexistDTB := filepath.Join(dir, "xxx")
    48  	// 2. Fallback to read from sys fs, and sys fs reading also failed.
    49  	if _, err = LoadFDT(nil, nonexistDTB); !errors.Is(err, ErrNoValidReaders) {
    50  		t.Errorf("LoadFDT(%s) got %v, want %v", nonexistDTB, err, ErrNoValidReaders)
    51  	}
    52  
    53  	// 3. Fallback to read from sys fs, and succeed.
    54  	fdt, err = LoadFDT(nil, "testdata/fdt.dtb")
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  	if !reflect.DeepEqual(fdt, testData) {
    59  		got, err := json.MarshalIndent(fdt, "", "    ")
    60  		if err != nil {
    61  			t.Fatal(err)
    62  		}
    63  		t.Errorf(`Read("fdt.dtb") = %s \n, want %s`, got, jsonData)
    64  	}
    65  }
    66  
    67  func TestRead(t *testing.T) {
    68  	f, err := os.Open("testdata/fdt.dtb")
    69  	if err != nil {
    70  		t.Fatal(err)
    71  	}
    72  	defer f.Close()
    73  
    74  	jsonData, err := os.ReadFile("testdata/fdt.json")
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  	testData := &FDT{}
    79  	if err := json.Unmarshal(jsonData, testData); err != nil {
    80  		t.Fatal(err)
    81  	}
    82  
    83  	fdt, err := ReadFDT(f)
    84  	if err != nil {
    85  		t.Fatal(err)
    86  	}
    87  
    88  	if !reflect.DeepEqual(fdt, testData) {
    89  		got, err := json.MarshalIndent(fdt, "", "    ")
    90  		if err != nil {
    91  			t.Fatal(err)
    92  		}
    93  		t.Errorf(`Read("fdt.dtb") = %s`, got)
    94  		t.Errorf(`want %s`, jsonData)
    95  	}
    96  }
    97  
    98  // TestParity tests that the fdt Read+Write operations are compatible with your
    99  // system's fdtdump command.
   100  func TestParity(t *testing.T) {
   101  	// TODO: I'm convinced my system's fdtdump command is broken.
   102  	t.Skip()
   103  
   104  	// Read and write the fdt.
   105  	fdt, err := New(WithFileName("testdata/fdt.dtb"))
   106  	if err != nil {
   107  		t.Fatal(err)
   108  	}
   109  	dir := t.TempDir()
   110  	dtb := filepath.Join(dir, "fdt2.dtb")
   111  	f, err := os.Create(dtb)
   112  	if err != nil {
   113  		t.Fatal(err)
   114  	}
   115  	_, err = fdt.Write(f)
   116  	f.Close()
   117  	if err != nil {
   118  		t.Fatal(err)
   119  	}
   120  
   121  	// Run your system's fdtdump command.
   122  	dts := filepath.Join(dir, "fdt2.dts")
   123  	f, err = os.Create(dts)
   124  	if err != nil {
   125  		t.Fatal(err)
   126  	}
   127  	cmd := exec.Command("fdtdump", dtb)
   128  	cmd.Stdout = f
   129  	err = cmd.Run()
   130  	f.Close()
   131  	if err != nil {
   132  		t.Fatal(err) // TODO: skip if system does not have fdtdump
   133  	}
   134  
   135  	// This used to run diff, has to be done better. It's not even working now so.
   136  	if false {
   137  		cmd = exec.Command("diff", "testdata/fdt.dts", "testdata/fdt2.dts")
   138  		cmd.Stdout = os.Stdout
   139  		cmd.Stderr = os.Stderr
   140  		cmd.Run()
   141  	}
   142  }
   143  
   144  func TestFindNode(t *testing.T) {
   145  	f, err := os.Open("testdata/fdt.dtb")
   146  	if err != nil {
   147  		t.Fatal(err)
   148  	}
   149  
   150  	fdt, err := ReadFDT(f)
   151  	f.Close()
   152  	if err != nil {
   153  		t.Fatal(err)
   154  	}
   155  
   156  	n, ok := fdt.NodeByName("psci")
   157  	if !ok {
   158  		t.Fatalf("Finding psci in %s: got false, want true", fdt)
   159  	}
   160  	t.Logf("Got the node: %s", n)
   161  }
   162  
   163  func TestFindAllNode(t *testing.T) {
   164  	f, err := os.Open("testdata/fdt.dtb")
   165  	if err != nil {
   166  		t.Fatal(err)
   167  	}
   168  
   169  	fdt, err := ReadFDT(f)
   170  	f.Close()
   171  	if err != nil {
   172  		t.Fatal(err)
   173  	}
   174  	const expectedVirtNodes = 32
   175  	nodes, err := fdt.Root().FindAll(func(n *Node) bool {
   176  		return strings.HasPrefix(n.Name, "virtio_mmio")
   177  	})
   178  	if err != nil {
   179  		t.Fatalf("Finding all virtio_mmio in %s: got err %v, want nil", fdt, err)
   180  	}
   181  
   182  	if len(nodes) != expectedVirtNodes {
   183  		t.Fatalf("Finding all virtio_mmio in %s: got returned %d nodes, want %d", fdt, len(nodes), expectedVirtNodes)
   184  	}
   185  }
   186  
   187  func TestFindProperty(t *testing.T) {
   188  	f, err := os.Open("testdata/fdt.dtb")
   189  	if err != nil {
   190  		t.Fatal(err)
   191  	}
   192  	fdt, err := ReadFDT(f)
   193  	f.Close()
   194  	if err != nil {
   195  		t.Fatal(err)
   196  	}
   197  
   198  	n, ok := fdt.NodeByName("psci")
   199  	if !ok {
   200  		t.Fatalf("Finding psci in %s: got false, want true", fdt)
   201  	}
   202  	t.Logf("Got the node: %s", n)
   203  	l := "migrate"
   204  	p, ok := n.LookProperty(l)
   205  	if !ok {
   206  		t.Fatalf("Find property %q in %s: got false, want true", l, n)
   207  	}
   208  	v := []byte{0x84, 0, 0, 0x5}
   209  	if !bytes.Equal(p.Value, v) {
   210  		t.Fatalf("Checking value of %s: got %q, want %q", p.Name, p.Value, v)
   211  	}
   212  	l = "bogosity"
   213  	p, ok = n.LookProperty(l)
   214  	if ok {
   215  		t.Fatalf("Find property %q in %s: got true, want false", l, n)
   216  	}
   217  }
   218  
   219  func TestWalk(t *testing.T) {
   220  	f, err := os.Open("testdata/fdt.dtb")
   221  	if err != nil {
   222  		t.Fatal(err)
   223  	}
   224  	fdt, err := ReadFDT(f)
   225  	f.Close()
   226  	if err != nil {
   227  		t.Fatal(err)
   228  	}
   229  
   230  	b, err := fdt.Root().Walk("psci").Property("migrate").AsBytes()
   231  	if err != nil {
   232  		t.Fatalf("Walk to psci/migrate: got %v, want nil", err)
   233  	}
   234  	v := []byte{0x84, 0, 0, 0x5}
   235  	if !bytes.Equal(b, v) {
   236  		t.Fatalf("Checking value of psci/migrate: got %q, want %q", b, v)
   237  	}
   238  }