github.com/maier/nomad@v0.4.1-0.20161110003312-a9e3d0b8549d/nomad/structs/funcs_test.go (about)

     1  package structs
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"regexp"
     7  	"sort"
     8  	"testing"
     9  )
    10  
    11  func TestRemoveAllocs(t *testing.T) {
    12  	l := []*Allocation{
    13  		&Allocation{ID: "foo"},
    14  		&Allocation{ID: "bar"},
    15  		&Allocation{ID: "baz"},
    16  		&Allocation{ID: "zip"},
    17  	}
    18  
    19  	out := RemoveAllocs(l, []*Allocation{l[1], l[3]})
    20  	if len(out) != 2 {
    21  		t.Fatalf("bad: %#v", out)
    22  	}
    23  	if out[0].ID != "foo" && out[1].ID != "baz" {
    24  		t.Fatalf("bad: %#v", out)
    25  	}
    26  }
    27  
    28  func TestFilterTerminalAllocs(t *testing.T) {
    29  	l := []*Allocation{
    30  		&Allocation{
    31  			ID:            "bar",
    32  			Name:          "myname1",
    33  			DesiredStatus: AllocDesiredStatusEvict,
    34  		},
    35  		&Allocation{ID: "baz", DesiredStatus: AllocDesiredStatusStop},
    36  		&Allocation{
    37  			ID:            "foo",
    38  			DesiredStatus: AllocDesiredStatusRun,
    39  			ClientStatus:  AllocClientStatusPending,
    40  		},
    41  		&Allocation{
    42  			ID:            "bam",
    43  			Name:          "myname",
    44  			DesiredStatus: AllocDesiredStatusRun,
    45  			ClientStatus:  AllocClientStatusComplete,
    46  			CreateIndex:   5,
    47  		},
    48  		&Allocation{
    49  			ID:            "lol",
    50  			Name:          "myname",
    51  			DesiredStatus: AllocDesiredStatusRun,
    52  			ClientStatus:  AllocClientStatusComplete,
    53  			CreateIndex:   2,
    54  		},
    55  	}
    56  
    57  	out, terminalAllocs := FilterTerminalAllocs(l)
    58  	if len(out) != 1 {
    59  		t.Fatalf("bad: %#v", out)
    60  	}
    61  	if out[0].ID != "foo" {
    62  		t.Fatalf("bad: %#v", out)
    63  	}
    64  
    65  	if len(terminalAllocs) != 3 {
    66  		for _, o := range terminalAllocs {
    67  			fmt.Printf("%#v \n", o)
    68  		}
    69  
    70  		t.Fatalf("bad: %#v", terminalAllocs)
    71  	}
    72  
    73  	if terminalAllocs["myname"].ID != "bam" {
    74  		t.Fatalf("bad: %#v", terminalAllocs["myname"])
    75  	}
    76  }
    77  
    78  func TestAllocsFit_PortsOvercommitted(t *testing.T) {
    79  	n := &Node{
    80  		Resources: &Resources{
    81  			Networks: []*NetworkResource{
    82  				&NetworkResource{
    83  					Device: "eth0",
    84  					CIDR:   "10.0.0.0/8",
    85  					MBits:  100,
    86  				},
    87  			},
    88  		},
    89  	}
    90  
    91  	a1 := &Allocation{
    92  		Job: &Job{
    93  			TaskGroups: []*TaskGroup{
    94  				{
    95  					Name:          "web",
    96  					EphemeralDisk: DefaultEphemeralDisk(),
    97  				},
    98  			},
    99  		},
   100  		TaskResources: map[string]*Resources{
   101  			"web": &Resources{
   102  				Networks: []*NetworkResource{
   103  					&NetworkResource{
   104  						Device:        "eth0",
   105  						IP:            "10.0.0.1",
   106  						MBits:         50,
   107  						ReservedPorts: []Port{{"main", 8000}},
   108  					},
   109  				},
   110  			},
   111  		},
   112  	}
   113  
   114  	// Should fit one allocation
   115  	fit, dim, _, err := AllocsFit(n, []*Allocation{a1}, nil)
   116  	if err != nil {
   117  		t.Fatalf("err: %v", err)
   118  	}
   119  	if !fit {
   120  		t.Fatalf("Bad: %s", dim)
   121  	}
   122  
   123  	// Should not fit second allocation
   124  	fit, _, _, err = AllocsFit(n, []*Allocation{a1, a1}, nil)
   125  	if err != nil {
   126  		t.Fatalf("err: %v", err)
   127  	}
   128  	if fit {
   129  		t.Fatalf("Bad")
   130  	}
   131  }
   132  
   133  func TestAllocsFit(t *testing.T) {
   134  	n := &Node{
   135  		Resources: &Resources{
   136  			CPU:      2000,
   137  			MemoryMB: 2048,
   138  			DiskMB:   10000,
   139  			IOPS:     100,
   140  			Networks: []*NetworkResource{
   141  				&NetworkResource{
   142  					Device: "eth0",
   143  					CIDR:   "10.0.0.0/8",
   144  					MBits:  100,
   145  				},
   146  			},
   147  		},
   148  		Reserved: &Resources{
   149  			CPU:      1000,
   150  			MemoryMB: 1024,
   151  			DiskMB:   5000,
   152  			IOPS:     50,
   153  			Networks: []*NetworkResource{
   154  				&NetworkResource{
   155  					Device:        "eth0",
   156  					IP:            "10.0.0.1",
   157  					MBits:         50,
   158  					ReservedPorts: []Port{{"main", 80}},
   159  				},
   160  			},
   161  		},
   162  	}
   163  
   164  	a1 := &Allocation{
   165  		Resources: &Resources{
   166  			CPU:      1000,
   167  			MemoryMB: 1024,
   168  			DiskMB:   5000,
   169  			IOPS:     50,
   170  			Networks: []*NetworkResource{
   171  				&NetworkResource{
   172  					Device:        "eth0",
   173  					IP:            "10.0.0.1",
   174  					MBits:         50,
   175  					ReservedPorts: []Port{{"main", 8000}},
   176  				},
   177  			},
   178  		},
   179  	}
   180  
   181  	// Should fit one allocation
   182  	fit, _, used, err := AllocsFit(n, []*Allocation{a1}, nil)
   183  	if err != nil {
   184  		t.Fatalf("err: %v", err)
   185  	}
   186  	if !fit {
   187  		t.Fatalf("Bad")
   188  	}
   189  
   190  	// Sanity check the used resources
   191  	if used.CPU != 2000 {
   192  		t.Fatalf("bad: %#v", used)
   193  	}
   194  	if used.MemoryMB != 2048 {
   195  		t.Fatalf("bad: %#v", used)
   196  	}
   197  
   198  	// Should not fit second allocation
   199  	fit, _, used, err = AllocsFit(n, []*Allocation{a1, a1}, nil)
   200  	if err != nil {
   201  		t.Fatalf("err: %v", err)
   202  	}
   203  	if fit {
   204  		t.Fatalf("Bad")
   205  	}
   206  
   207  	// Sanity check the used resources
   208  	if used.CPU != 3000 {
   209  		t.Fatalf("bad: %#v", used)
   210  	}
   211  	if used.MemoryMB != 3072 {
   212  		t.Fatalf("bad: %#v", used)
   213  	}
   214  
   215  }
   216  
   217  func TestScoreFit(t *testing.T) {
   218  	node := &Node{}
   219  	node.Resources = &Resources{
   220  		CPU:      4096,
   221  		MemoryMB: 8192,
   222  	}
   223  	node.Reserved = &Resources{
   224  		CPU:      2048,
   225  		MemoryMB: 4096,
   226  	}
   227  
   228  	// Test a perfect fit
   229  	util := &Resources{
   230  		CPU:      2048,
   231  		MemoryMB: 4096,
   232  	}
   233  	score := ScoreFit(node, util)
   234  	if score != 18.0 {
   235  		t.Fatalf("bad: %v", score)
   236  	}
   237  
   238  	// Test the worst fit
   239  	util = &Resources{
   240  		CPU:      0,
   241  		MemoryMB: 0,
   242  	}
   243  	score = ScoreFit(node, util)
   244  	if score != 0.0 {
   245  		t.Fatalf("bad: %v", score)
   246  	}
   247  
   248  	// Test a mid-case scenario
   249  	util = &Resources{
   250  		CPU:      1024,
   251  		MemoryMB: 2048,
   252  	}
   253  	score = ScoreFit(node, util)
   254  	if score < 10.0 || score > 16.0 {
   255  		t.Fatalf("bad: %v", score)
   256  	}
   257  }
   258  
   259  func TestGenerateUUID(t *testing.T) {
   260  	prev := GenerateUUID()
   261  	for i := 0; i < 100; i++ {
   262  		id := GenerateUUID()
   263  		if prev == id {
   264  			t.Fatalf("Should get a new ID!")
   265  		}
   266  
   267  		matched, err := regexp.MatchString(
   268  			"[\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12}", id)
   269  		if !matched || err != nil {
   270  			t.Fatalf("expected match %s %v %s", id, matched, err)
   271  		}
   272  	}
   273  }
   274  
   275  func TestSliceStringIsSubset(t *testing.T) {
   276  	l := []string{"a", "b", "c"}
   277  	s := []string{"d"}
   278  
   279  	sub, offending := SliceStringIsSubset(l, l[:1])
   280  	if !sub || len(offending) != 0 {
   281  		t.Fatalf("bad %v %v", sub, offending)
   282  	}
   283  
   284  	sub, offending = SliceStringIsSubset(l, s)
   285  	if sub || len(offending) == 0 || offending[0] != "d" {
   286  		t.Fatalf("bad %v %v", sub, offending)
   287  	}
   288  }
   289  
   290  func TestMapStringStringSliceValueSet(t *testing.T) {
   291  	m := map[string][]string{
   292  		"foo": []string{"1", "2"},
   293  		"bar": []string{"3"},
   294  		"baz": nil,
   295  	}
   296  
   297  	act := MapStringStringSliceValueSet(m)
   298  	exp := []string{"1", "2", "3"}
   299  	sort.Strings(act)
   300  	if !reflect.DeepEqual(act, exp) {
   301  		t.Fatalf("Bad; got %v; want %v", act, exp)
   302  	}
   303  }