github.com/hugelgupf/u-root@v0.0.0-20191023214958-4807c632154c/pkg/kexec/memory_linux_test.go (about)

     1  // Copyright 2018-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 kexec
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"os"
    12  	"path"
    13  	"reflect"
    14  	"testing"
    15  )
    16  
    17  func TestParseMemoryMap(t *testing.T) {
    18  	root, err := ioutil.TempDir("", "memmap")
    19  	if err != nil {
    20  		t.Fatalf("Cannot create test dir: %v", err)
    21  	}
    22  	defer os.RemoveAll(root)
    23  
    24  	create := func(dir string, start, end uintptr, typ RangeType) error {
    25  		p := path.Join(root, dir)
    26  		if err := os.Mkdir(p, 0755); err != nil {
    27  			return err
    28  		}
    29  		if err := ioutil.WriteFile(path.Join(p, "start"), []byte(fmt.Sprintf("%#x\n", start)), 0655); err != nil {
    30  			return err
    31  		}
    32  		if err := ioutil.WriteFile(path.Join(p, "end"), []byte(fmt.Sprintf("%#x\n", end)), 0655); err != nil {
    33  			return err
    34  		}
    35  		return ioutil.WriteFile(path.Join(p, "type"), append([]byte(typ), '\n'), 0655)
    36  	}
    37  
    38  	if err := create("0", 0, 49, RangeRAM); err != nil {
    39  		t.Fatal(err)
    40  	}
    41  	if err := create("1", 100, 149, RangeACPI); err != nil {
    42  		t.Fatal(err)
    43  	}
    44  	if err := create("2", 200, 249, RangeNVS); err != nil {
    45  		t.Fatal(err)
    46  	}
    47  	if err := create("3", 300, 349, RangeReserved); err != nil {
    48  		t.Fatal(err)
    49  	}
    50  
    51  	want := MemoryMap{
    52  		{Range: Range{Start: 0, Size: 50}, Type: RangeRAM},
    53  		{Range: Range{Start: 100, Size: 50}, Type: RangeACPI},
    54  		{Range: Range{Start: 200, Size: 50}, Type: RangeNVS},
    55  		{Range: Range{Start: 300, Size: 50}, Type: RangeReserved},
    56  	}
    57  
    58  	phys, err := internalParseMemoryMap(root)
    59  	if err != nil {
    60  		t.Fatalf("ParseMemoryMap() error: %v", err)
    61  	}
    62  	if !reflect.DeepEqual(phys, want) {
    63  		t.Errorf("ParseMemoryMap() got %v, want %v", phys, want)
    64  	}
    65  }
    66  
    67  func TestAvailableRAM(t *testing.T) {
    68  	old := pageMask
    69  	defer func() {
    70  		pageMask = old
    71  	}()
    72  	// suppose we have 4K pages.
    73  	pageMask = 4095
    74  
    75  	var mem Memory
    76  	mem.Phys = MemoryMap{
    77  		TypedRange{Range: Range{Start: 0, Size: 8192}, Type: RangeRAM},
    78  		TypedRange{Range: Range{Start: 8192, Size: 8000}, Type: RangeRAM},
    79  		TypedRange{Range: Range{Start: 20480, Size: 1000}, Type: RangeRAM},
    80  		TypedRange{Range: Range{Start: 24576, Size: 1000}, Type: RangeRAM},
    81  		TypedRange{Range: Range{Start: 28672, Size: 1000}, Type: RangeRAM},
    82  	}
    83  
    84  	mem.Segments = []Segment{
    85  		{Phys: Range{Start: 40, Size: 50}},
    86  		{Phys: Range{Start: 8000, Size: 200}},
    87  		{Phys: Range{Start: 18000, Size: 1000}},
    88  		{Phys: Range{Start: 24600, Size: 1000}},
    89  		{Phys: Range{Start: 28000, Size: 10000}},
    90  	}
    91  
    92  	want := Ranges{
    93  		Range{Start: 0, Size: 40},
    94  		Range{Start: 4096, Size: 8000 - 4096},
    95  		Range{Start: 12288, Size: 8192 + 8000 - 12288},
    96  		Range{Start: 20480, Size: 1000},
    97  		Range{Start: 24576, Size: 24},
    98  	}
    99  
   100  	got := mem.AvailableRAM()
   101  	if !reflect.DeepEqual(got, want) {
   102  		t.Errorf("AvailableRAM() got %+v, want %+v", got, want)
   103  	}
   104  }
   105  
   106  func TestAlignPhys(t *testing.T) {
   107  	for _, test := range []struct {
   108  		name      string
   109  		seg, want Segment
   110  	}{
   111  		{
   112  			name: "aligned",
   113  			seg: Segment{
   114  				Buf:  Range{Start: 0x1000, Size: 0x1000},
   115  				Phys: Range{Start: 0x2000, Size: 0x1000},
   116  			},
   117  			want: Segment{
   118  				Buf:  Range{Start: 0x1000, Size: 0x1000},
   119  				Phys: Range{Start: 0x2000, Size: 0x1000},
   120  			},
   121  		},
   122  		{
   123  			name: "unaligned",
   124  			seg: Segment{
   125  				Buf:  Range{Start: 0x1011, Size: 0x1022},
   126  				Phys: Range{Start: 0x2011, Size: 0x1022},
   127  			},
   128  			want: Segment{
   129  				Buf:  Range{Start: 0x1000, Size: 0x1033},
   130  				Phys: Range{Start: 0x2000, Size: 0x2000},
   131  			},
   132  		},
   133  		{
   134  			name: "unaligned_size",
   135  			seg: Segment{
   136  				Buf:  Range{Start: 0x1000, Size: 0x1022},
   137  				Phys: Range{Start: 0x2000, Size: 0x1022},
   138  			},
   139  			want: Segment{
   140  				Buf:  Range{Start: 0x1000, Size: 0x1022},
   141  				Phys: Range{Start: 0x2000, Size: 0x2000},
   142  			},
   143  		},
   144  		{
   145  			name: "empty_buf",
   146  			seg: Segment{
   147  				Buf:  Range{Start: 0x1011, Size: 0},
   148  				Phys: Range{Start: 0x2011, Size: 0},
   149  			},
   150  			want: Segment{
   151  				Buf:  Range{Start: 0x1000, Size: 0},
   152  				Phys: Range{Start: 0x2000, Size: 0x1000},
   153  			},
   154  		},
   155  	} {
   156  		t.Run(test.name, func(t *testing.T) {
   157  			got := AlignPhys(test.seg)
   158  			if got != test.want {
   159  				t.Errorf("AlignPhys() got %v, want %v", got, test.want)
   160  			}
   161  		})
   162  	}
   163  }
   164  
   165  func TestTryMerge(t *testing.T) {
   166  	for _, test := range []struct {
   167  		name   string
   168  		phys   Range
   169  		merged bool
   170  		want   Range
   171  	}{
   172  		{
   173  			name:   "disjunct",
   174  			phys:   Range{Start: 100, Size: 150},
   175  			merged: false,
   176  		},
   177  		{
   178  			name:   "superset",
   179  			phys:   Range{Start: 0, Size: 80},
   180  			merged: true,
   181  			want:   Range{Start: 0, Size: 100},
   182  		},
   183  		{
   184  			name:   "superset",
   185  			phys:   Range{Start: 10, Size: 80},
   186  			merged: true,
   187  			want:   Range{Start: 0, Size: 100},
   188  		},
   189  		{
   190  			name:   "superset",
   191  			phys:   Range{Start: 10, Size: 90},
   192  			merged: true,
   193  			want:   Range{Start: 0, Size: 100},
   194  		},
   195  		{
   196  			name:   "superset",
   197  			phys:   Range{Start: 0, Size: 100},
   198  			merged: true,
   199  			want:   Range{Start: 0, Size: 100},
   200  		},
   201  		{
   202  			name:   "overlap",
   203  			phys:   Range{Start: 0, Size: 150},
   204  			merged: true,
   205  			want:   Range{Start: 0, Size: 150},
   206  		},
   207  		{
   208  			name:   "overlap",
   209  			phys:   Range{Start: 50, Size: 100},
   210  			merged: true,
   211  			want:   Range{Start: 0, Size: 150},
   212  		},
   213  		{
   214  			name:   "overlap",
   215  			phys:   Range{Start: 99, Size: 51},
   216  			merged: true,
   217  			want:   Range{Start: 0, Size: 150},
   218  		},
   219  	} {
   220  		t.Run(test.name, func(t *testing.T) {
   221  			a := NewSegment([]byte("aaaa"), Range{Start: 0, Size: 100})
   222  			b := NewSegment([]byte("bbbb"), test.phys)
   223  
   224  			merged := a.tryMerge(b)
   225  			if merged != test.merged {
   226  				t.Fatalf("tryMerge() got %v, want %v", merged, test.merged)
   227  			}
   228  			if !merged {
   229  				return
   230  			}
   231  			if a.Phys != test.want {
   232  				t.Fatalf("Wrong merge result: got %+v, want %+v", a.Phys, test.want)
   233  			}
   234  
   235  			got := a.Buf.toSlice()
   236  			want := []byte("aaaabbbb")
   237  			if !bytes.Equal(got, want) {
   238  				t.Errorf("Wrong buf: got %s, want %s", got, want)
   239  			}
   240  		})
   241  	}
   242  }
   243  
   244  func TestDedup(t *testing.T) {
   245  	s := []Segment{
   246  		NewSegment([]byte("test"), Range{Start: 0, Size: 100}),
   247  		NewSegment([]byte("test"), Range{Start: 100, Size: 100}),
   248  		NewSegment([]byte("test"), Range{Start: 200, Size: 100}),
   249  		NewSegment([]byte("test"), Range{Start: 250, Size: 50}),
   250  		NewSegment([]byte("test"), Range{Start: 300, Size: 100}),
   251  		NewSegment([]byte("test"), Range{Start: 350, Size: 100}),
   252  	}
   253  	want := []Range{
   254  		{Start: 0, Size: 100},
   255  		{Start: 100, Size: 100},
   256  		{Start: 200, Size: 100},
   257  		{Start: 300, Size: 150},
   258  	}
   259  
   260  	got := Dedup(s)
   261  	for i := range got {
   262  		if got[i].Phys != want[i] {
   263  			t.Errorf("Dedup() got %v, want %v", got[i].Phys, want[i])
   264  		}
   265  	}
   266  }
   267  
   268  func TestFindSpaceIn(t *testing.T) {
   269  	for i, tt := range []struct {
   270  		name  string
   271  		rs    Ranges
   272  		size  uint
   273  		limit Range
   274  		want  Range
   275  		err   error
   276  	}{
   277  		{
   278  			name: "no space above 0x1000",
   279  			rs: Ranges{
   280  				Range{Start: 0x0, Size: 0x1000},
   281  			},
   282  			size:  0x10,
   283  			limit: RangeFromInterval(0x1000, MaxAddr),
   284  			err:   ErrNotEnoughSpace{Size: 0x10},
   285  		},
   286  		{
   287  			name: "no space under 0x1000",
   288  			rs: Ranges{
   289  				Range{Start: 0x1000, Size: 0x10},
   290  			},
   291  			size:  0x10,
   292  			limit: RangeFromInterval(0, 0x1000),
   293  			err:   ErrNotEnoughSpace{Size: 0x10},
   294  		},
   295  		{
   296  			name: "disjunct space above 0x1000",
   297  			rs: Ranges{
   298  				Range{Start: 0x0, Size: 0x1000},
   299  				Range{Start: 0x1000, Size: 0x10},
   300  			},
   301  			size:  0x10,
   302  			limit: RangeFromInterval(0x1000, MaxAddr),
   303  			want:  Range{Start: 0x1000, Size: 0x10},
   304  		},
   305  		{
   306  			name: "just enough space under 0x1000",
   307  			rs: Ranges{
   308  				Range{Start: 0xFF, Size: 0xf},
   309  				Range{Start: 0xFF0, Size: 0x10},
   310  				Range{Start: 0x1000, Size: 0x10},
   311  			},
   312  			size:  0x10,
   313  			limit: RangeFromInterval(0, 0x1000),
   314  			want:  Range{Start: 0xFF0, Size: 0x10},
   315  		},
   316  		{
   317  			name: "all spaces abvoe 0x1000 and under 0x2000 are too small",
   318  			rs: Ranges{
   319  				Range{Start: 0x0, Size: 0x1000},
   320  				Range{Start: 0x1000, Size: 0xf},
   321  				Range{Start: 0x1010, Size: 0xf},
   322  				Range{Start: 0x1f00, Size: 0xf},
   323  				Range{Start: 0x2000, Size: 0x10},
   324  			},
   325  			size:  0x10,
   326  			limit: RangeFromInterval(0x1000, 0x2000),
   327  			err:   ErrNotEnoughSpace{Size: 0x10},
   328  		},
   329  		{
   330  			name: "space is split across 0x1000, with enough space above",
   331  			rs: Ranges{
   332  				Range{Start: 0x0, Size: 0x1010},
   333  			},
   334  			size:  0x10,
   335  			limit: RangeFromInterval(0x1000, MaxAddr),
   336  			want:  Range{Start: 0x1000, Size: 0x10},
   337  		},
   338  		{
   339  			name: "space is split across 0x1000, with enough space under",
   340  			rs: Ranges{
   341  				Range{Start: 0xFF0, Size: 0x20},
   342  			},
   343  			size:  0x10,
   344  			limit: RangeFromInterval(0, 0x1000),
   345  			want:  Range{Start: 0xFF0, Size: 0x10},
   346  		},
   347  		{
   348  			name: "space is split across 0x1000 and 0x2000, but not enough space above or below",
   349  			rs: Ranges{
   350  				Range{Start: 0xFF1, Size: 0xf + 0xf},
   351  				Range{Start: 0x1FF1, Size: 0xf + 0xf},
   352  			},
   353  			size:  0x10,
   354  			limit: RangeFromInterval(0x1000, 0x2000),
   355  			err:   ErrNotEnoughSpace{Size: 0x10},
   356  		},
   357  		{
   358  			name: "space is split across 0x1000, with enough space in the next one",
   359  			rs: Ranges{
   360  				Range{Start: 0x0, Size: 0x100f},
   361  				Range{Start: 0x1010, Size: 0x10},
   362  			},
   363  			size:  0x10,
   364  			limit: RangeFromInterval(0x1000, MaxAddr),
   365  			want:  Range{Start: 0x1010, Size: 0x10},
   366  		},
   367  		{
   368  			name:  "no ranges",
   369  			rs:    Ranges{},
   370  			size:  0x10,
   371  			limit: RangeFromInterval(0, MaxAddr),
   372  			err:   ErrNotEnoughSpace{Size: 0x10},
   373  		},
   374  		{
   375  			name:  "no ranges, zero size",
   376  			rs:    Ranges{},
   377  			size:  0,
   378  			limit: RangeFromInterval(0, MaxAddr),
   379  			err:   ErrNotEnoughSpace{Size: 0},
   380  		},
   381  	} {
   382  		t.Run(fmt.Sprintf("test_%d_%s", i, tt.name), func(t *testing.T) {
   383  			got, err := tt.rs.FindSpaceIn(tt.size, tt.limit)
   384  			if !reflect.DeepEqual(got, tt.want) || err != tt.err {
   385  				t.Errorf("%s.FindSpaceIn(%#x, limit = %s) = (%#x, %v), want (%#x, %v)", tt.rs, tt.size, tt.limit, got, err, tt.want, tt.err)
   386  			}
   387  		})
   388  	}
   389  }
   390  
   391  func TestIntersection(t *testing.T) {
   392  	for i, tt := range []struct {
   393  		r             Range
   394  		r2            Range
   395  		wantOverlap   bool
   396  		wantIntersect *Range
   397  	}{
   398  		{
   399  			r:             Range{Start: 0, Size: 50},
   400  			r2:            Range{Start: 49, Size: 1},
   401  			wantOverlap:   true,
   402  			wantIntersect: &Range{Start: 49, Size: 1},
   403  		},
   404  		{
   405  			r:             Range{Start: 0, Size: 50},
   406  			r2:            Range{Start: 50, Size: 1},
   407  			wantOverlap:   false,
   408  			wantIntersect: nil,
   409  		},
   410  		{
   411  			r:             Range{Start: 49, Size: 1},
   412  			r2:            Range{Start: 0, Size: 50},
   413  			wantOverlap:   true,
   414  			wantIntersect: &Range{Start: 49, Size: 1},
   415  		},
   416  		{
   417  			r:             Range{Start: 50, Size: 1},
   418  			r2:            Range{Start: 0, Size: 50},
   419  			wantOverlap:   false,
   420  			wantIntersect: nil,
   421  		},
   422  		{
   423  			r:             Range{Start: 0, Size: 50},
   424  			r2:            Range{Start: 10, Size: 1},
   425  			wantOverlap:   true,
   426  			wantIntersect: &Range{Start: 10, Size: 1},
   427  		},
   428  		{
   429  			r:             Range{Start: 10, Size: 1},
   430  			r2:            Range{Start: 0, Size: 50},
   431  			wantOverlap:   true,
   432  			wantIntersect: &Range{Start: 10, Size: 1},
   433  		},
   434  	} {
   435  		t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
   436  			if got := tt.r.Overlaps(tt.r2); got != tt.wantOverlap {
   437  				t.Errorf("%s.Overlaps(%s) = %v, want %v", tt.r, tt.r2, got, tt.wantOverlap)
   438  			}
   439  			if got := tt.r.Intersect(tt.r2); !reflect.DeepEqual(got, tt.wantIntersect) {
   440  				t.Errorf("%s.Intersect(%s) = %v, want %v", tt.r, tt.r2, got, tt.wantIntersect)
   441  			}
   442  		})
   443  	}
   444  }
   445  
   446  func TestMinusRange(t *testing.T) {
   447  	for i, tt := range []struct {
   448  		r    Range
   449  		r2   Range
   450  		want []Range
   451  	}{
   452  		{
   453  			// r2 contained completely within r.
   454  			r:  Range{Start: 0x100, Size: 0x200},
   455  			r2: Range{Start: 0x150, Size: 0x50},
   456  			want: []Range{
   457  				{Start: 0x100, Size: 0x50},
   458  				{Start: 0x1a0, Size: 0x160},
   459  			},
   460  		},
   461  		{
   462  			// r contained completely within r2.
   463  			r:    Range{Start: 0x100, Size: 0x50},
   464  			r2:   Range{Start: 0x90, Size: 0x100},
   465  			want: nil,
   466  		},
   467  		{
   468  			r:    Range{Start: 0x100, Size: 0x50},
   469  			r2:   Range{Start: 0x100, Size: 0x100},
   470  			want: nil,
   471  		},
   472  		{
   473  			r:    Range{Start: 0x100, Size: 0x50},
   474  			r2:   Range{Start: 0xf0, Size: 0x60},
   475  			want: nil,
   476  		},
   477  		{
   478  			// Overlaps to the right.
   479  			r:  Range{Start: 0x100, Size: 0x100},
   480  			r2: Range{Start: 0x150, Size: 0x100},
   481  			want: []Range{
   482  				{Start: 0x100, Size: 0x50},
   483  			},
   484  		},
   485  		{
   486  			// Overlaps to the left.
   487  			r:  Range{Start: 0x100, Size: 0x100},
   488  			r2: Range{Start: 0x50, Size: 0x100},
   489  			want: []Range{
   490  				{Start: 0x150, Size: 0xb0},
   491  			},
   492  		},
   493  		{
   494  			// Doesn't overlap at all.
   495  			r:  Range{Start: 0x100, Size: 0x100},
   496  			r2: Range{Start: 0x200, Size: 0x100},
   497  			want: []Range{
   498  				{Start: 0x100, Size: 0x100},
   499  			},
   500  		},
   501  	} {
   502  		t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
   503  			if got := tt.r.Minus(tt.r2); !reflect.DeepEqual(got, tt.want) {
   504  				t.Errorf("%s minus %s = %v, want %v", tt.r, tt.r2, got, tt.want)
   505  			}
   506  		})
   507  	}
   508  }
   509  
   510  func TestContains(t *testing.T) {
   511  	for i, tt := range []struct {
   512  		r    Range
   513  		p    uintptr
   514  		want bool
   515  	}{
   516  		{
   517  			r:    Range{Start: 0, Size: 50},
   518  			p:    50,
   519  			want: false,
   520  		},
   521  		{
   522  			r:    Range{Start: 0, Size: 50},
   523  			p:    49,
   524  			want: true,
   525  		},
   526  		{
   527  			r:    Range{Start: 50, Size: 50},
   528  			p:    49,
   529  			want: false,
   530  		},
   531  	} {
   532  		t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
   533  			if got := tt.r.Contains(tt.p); got != tt.want {
   534  				t.Errorf("%s.Contains(%#x) = %v, want %v", tt.r, tt.p, got, tt.want)
   535  			}
   536  		})
   537  	}
   538  }
   539  
   540  func TestAdjacent(t *testing.T) {
   541  	for i, tt := range []struct {
   542  		r1   Range
   543  		r2   Range
   544  		want bool
   545  	}{
   546  		{
   547  			r1:   Range{Start: 0, Size: 50},
   548  			r2:   Range{Start: 50, Size: 50},
   549  			want: true,
   550  		},
   551  		{
   552  			r1:   Range{Start: 0, Size: 40},
   553  			r2:   Range{Start: 41, Size: 50},
   554  			want: false,
   555  		},
   556  		{
   557  			r1:   Range{Start: 10, Size: 40},
   558  			r2:   Range{Start: 0, Size: 10},
   559  			want: true,
   560  		},
   561  		{
   562  			r1:   Range{Start: 10, Size: 39},
   563  			r2:   Range{Start: 40, Size: 50},
   564  			want: false,
   565  		},
   566  	} {
   567  		t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
   568  			got1 := tt.r1.Adjacent(tt.r2)
   569  			got2 := tt.r2.Adjacent(tt.r1)
   570  			if got1 != tt.want {
   571  				t.Errorf("%s.Adjacent(%s) = %v, want %v", tt.r1, tt.r2, got1, tt.want)
   572  			}
   573  			if got2 != tt.want {
   574  				t.Errorf("%s.Adjacent(%s) = %v, want %v", tt.r2, tt.r1, got2, tt.want)
   575  			}
   576  		})
   577  	}
   578  }
   579  
   580  func TestMemoryMapInsert(t *testing.T) {
   581  	for i, tt := range []struct {
   582  		m    MemoryMap
   583  		r    TypedRange
   584  		want MemoryMap
   585  	}{
   586  		{
   587  			// r is entirely within m's one range.
   588  			m: MemoryMap{
   589  				TypedRange{Range: Range{Start: 0, Size: 0x2000}, Type: RangeRAM},
   590  			},
   591  			r: TypedRange{Range: Range{Start: 0x100, Size: 0x100}, Type: RangeReserved},
   592  			want: MemoryMap{
   593  				TypedRange{Range: Range{Start: 0, Size: 0x100}, Type: RangeRAM},
   594  				TypedRange{Range: Range{Start: 0x100, Size: 0x100}, Type: RangeReserved},
   595  				TypedRange{Range: Range{Start: 0x200, Size: 0x2000 - 0x200}, Type: RangeRAM},
   596  			},
   597  		},
   598  		{
   599  			// r sits across three RAM ranges.
   600  			m: MemoryMap{
   601  				TypedRange{Range: Range{Start: 0, Size: 0x150}, Type: RangeRAM},
   602  				TypedRange{Range: Range{Start: 0x150, Size: 0x50}, Type: RangeRAM},
   603  				TypedRange{Range: Range{Start: 0x1a0, Size: 0x100}, Type: RangeRAM},
   604  			},
   605  			r: TypedRange{Range: Range{Start: 0x100, Size: 0x100}, Type: RangeReserved},
   606  			want: MemoryMap{
   607  				TypedRange{Range: Range{Start: 0, Size: 0x100}, Type: RangeRAM},
   608  				TypedRange{Range: Range{Start: 0x100, Size: 0x100}, Type: RangeReserved},
   609  				TypedRange{Range: Range{Start: 0x200, Size: 0xa0}, Type: RangeRAM},
   610  			},
   611  		},
   612  		{
   613  			// r is a superset of the ranges in m.
   614  			m: MemoryMap{
   615  				TypedRange{Range: Range{Start: 0x100, Size: 0x50}, Type: RangeRAM},
   616  			},
   617  			r: TypedRange{Range: Range{Start: 0x100, Size: 0x100}, Type: RangeReserved},
   618  			want: MemoryMap{
   619  				TypedRange{Range: Range{Start: 0x100, Size: 0x100}, Type: RangeReserved},
   620  			},
   621  		},
   622  		{
   623  			// r is the first range in the map.
   624  			m: MemoryMap{},
   625  			r: TypedRange{Range: Range{Start: 0x100, Size: 0x100}, Type: RangeReserved},
   626  			want: MemoryMap{
   627  				TypedRange{Range: Range{Start: 0x100, Size: 0x100}, Type: RangeReserved},
   628  			},
   629  		},
   630  	} {
   631  		t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
   632  			// Make a copy for the Errorf print.
   633  			m := tt.m
   634  			tt.m.Insert(tt.r)
   635  
   636  			if !reflect.DeepEqual(tt.m, tt.want) {
   637  				t.Errorf("\n%v.Insert(%s) =\n%v, want\n%v", m, tt.r, tt.m, tt.want)
   638  			}
   639  		})
   640  	}
   641  }
   642  
   643  func TestSegmentsInsert(t *testing.T) {
   644  	for i, tt := range []struct {
   645  		segs Segments
   646  		s    Segment
   647  		want Segments
   648  	}{
   649  		{
   650  			segs: Segments{
   651  				Segment{Phys: Range{Start: 0x2000, Size: 0x20}},
   652  				Segment{Phys: Range{Start: 0x4000, Size: 0x20}},
   653  			},
   654  			s: Segment{Phys: Range{Start: 0x3000, Size: 0x20}},
   655  			want: Segments{
   656  				Segment{Phys: Range{Start: 0x2000, Size: 0x20}},
   657  				Segment{Phys: Range{Start: 0x3000, Size: 0x20}},
   658  				Segment{Phys: Range{Start: 0x4000, Size: 0x20}},
   659  			},
   660  		},
   661  		{
   662  			segs: Segments{},
   663  			s:    Segment{Phys: Range{Start: 0x3000, Size: 0x20}},
   664  			want: Segments{
   665  				Segment{Phys: Range{Start: 0x3000, Size: 0x20}},
   666  			},
   667  		},
   668  	} {
   669  		t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
   670  			before := tt.segs
   671  			tt.segs.Insert(tt.s)
   672  
   673  			if !reflect.DeepEqual(tt.segs, tt.want) {
   674  				t.Errorf("\n%v.Insert(%v) = \n%v, want \n%v", before, tt.s, tt.segs, tt.want)
   675  			}
   676  		})
   677  	}
   678  }