github.com/google/cadvisor@v0.49.1/devicemapper/thin_pool_watcher_test.go (about)

     1  // Copyright 2016 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package devicemapper
    16  
    17  import (
    18  	"fmt"
    19  	"sync"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/google/cadvisor/devicemapper/fake"
    24  )
    25  
    26  func TestRefresh(t *testing.T) {
    27  	usage := map[string]uint64{
    28  		"1": 12345,
    29  		"2": 23456,
    30  		"3": 34567,
    31  	}
    32  
    33  	cases := []struct {
    34  		name            string
    35  		dmsetupCommands []fake.DmsetupCommand
    36  		thinLsOutput    map[string]uint64
    37  		thinLsErr       error
    38  		expectedError   bool
    39  		deviceID        string
    40  		expectedUsage   uint64
    41  	}{
    42  		{
    43  			name: "check reservation fails",
    44  			dmsetupCommands: []fake.DmsetupCommand{
    45  				{Name: "status", Result: "", Err: fmt.Errorf("not gonna work")},
    46  			},
    47  			expectedError: true,
    48  		},
    49  		{
    50  			name: "no existing reservation - ok with minimum # of fields",
    51  			dmsetupCommands: []fake.DmsetupCommand{
    52  				{Name: "status", Result: "0 75497472 thin-pool 65 327/524288 14092/589824 -", Err: nil}, // status check
    53  				{Name: "message", Result: "", Err: nil},                                                 // make reservation
    54  				{Name: "message", Result: "", Err: nil},                                                 // release reservation
    55  			},
    56  			thinLsOutput:  usage,
    57  			expectedError: false,
    58  			deviceID:      "2",
    59  			expectedUsage: 23456,
    60  		},
    61  		{
    62  			name: "no existing reservation - ok",
    63  			dmsetupCommands: []fake.DmsetupCommand{
    64  				{Name: "status", Result: "0 75497472 thin-pool 65 327/524288 14092/589824 - rw no_discard_passdown error_if_no_space - ", Err: nil}, // status check
    65  				{Name: "message", Result: "", Err: nil}, // make reservation
    66  				{Name: "message", Result: "", Err: nil}, // release reservation
    67  			},
    68  			thinLsOutput:  usage,
    69  			expectedError: false,
    70  			deviceID:      "2",
    71  			expectedUsage: 23456,
    72  		},
    73  		{
    74  			name: "existing reservation - ok",
    75  			dmsetupCommands: []fake.DmsetupCommand{
    76  				// status check
    77  				{Name: "status", Result: "0 75497472 thin-pool 65 327/524288 14092/589824 39 rw no_discard_passdown error_if_no_space - ", Err: nil},
    78  				// release reservation
    79  				{Name: "message", Result: "", Err: nil},
    80  				// make reservation
    81  				{Name: "message", Result: "", Err: nil},
    82  				// release reservation
    83  				{Name: "message", Result: "", Err: nil},
    84  			},
    85  			thinLsOutput:  usage,
    86  			expectedError: false,
    87  			deviceID:      "3",
    88  			expectedUsage: 34567,
    89  		},
    90  		{
    91  			name: "failure releasing existing reservation",
    92  			dmsetupCommands: []fake.DmsetupCommand{
    93  				// status check
    94  				{Name: "status", Result: "0 75497472 thin-pool 65 327/524288 14092/589824 39 rw no_discard_passdown error_if_no_space - ", Err: nil},
    95  				// release reservation
    96  				{Name: "message", Result: "", Err: fmt.Errorf("not gonna work")},
    97  			},
    98  			expectedError: true,
    99  		},
   100  		{
   101  			name: "failure making reservation",
   102  			dmsetupCommands: []fake.DmsetupCommand{
   103  				// status check
   104  				{Name: "status", Result: "0 75497472 thin-pool 65 327/524288 14092/589824 39 rw no_discard_passdown error_if_no_space - ", Err: nil},
   105  				// release reservation
   106  				{Name: "message", Result: "", Err: nil},
   107  				// make reservation
   108  				{Name: "message", Result: "", Err: fmt.Errorf("not gonna work")},
   109  			},
   110  			expectedError: true,
   111  		},
   112  		{
   113  			name: "failure running thin_ls",
   114  			dmsetupCommands: []fake.DmsetupCommand{
   115  				// status check
   116  				{Name: "status", Result: "0 75497472 thin-pool 65 327/524288 14092/589824 39 rw no_discard_passdown error_if_no_space - ", Err: nil},
   117  				// release reservation
   118  				{Name: "message", Result: "", Err: nil},
   119  				// make reservation
   120  				{Name: "message", Result: "", Err: nil},
   121  				// release reservation
   122  				{Name: "message", Result: "", Err: nil},
   123  			},
   124  			thinLsErr:     fmt.Errorf("not gonna work"),
   125  			expectedError: true,
   126  		},
   127  	}
   128  
   129  	for _, tc := range cases {
   130  		dmsetup := fake.NewFakeDmsetupClient(t, tc.dmsetupCommands...)
   131  		thinLsClient := fake.NewFakeThinLsClient(tc.thinLsOutput, tc.thinLsErr)
   132  		watcher := &ThinPoolWatcher{
   133  			poolName:       "test pool name",
   134  			metadataDevice: "/dev/mapper/metadata-device",
   135  			lock:           &sync.RWMutex{},
   136  			period:         15 * time.Second,
   137  			stopChan:       make(chan struct{}),
   138  			dmsetup:        dmsetup,
   139  			thinLsClient:   thinLsClient,
   140  		}
   141  
   142  		err := watcher.Refresh()
   143  		if err != nil {
   144  			if !tc.expectedError {
   145  				t.Errorf("%v: unexpected error: %v", tc.name, err)
   146  			}
   147  			continue
   148  		} else if tc.expectedError {
   149  			t.Errorf("%v: unexpected success", tc.name)
   150  			continue
   151  		}
   152  
   153  		actualUsage, err := watcher.GetUsage(tc.deviceID)
   154  		if err != nil {
   155  			t.Errorf("%v: device ID not found: %v", tc.deviceID, err)
   156  			continue
   157  		}
   158  
   159  		if e, a := tc.expectedUsage, actualUsage; e != a {
   160  			t.Errorf("%v: actual usage did not match expected usage: expected: %v got: %v", tc.name, e, a)
   161  		}
   162  	}
   163  }
   164  
   165  func TestCheckReservation(t *testing.T) {
   166  	cases := []struct {
   167  		name           string
   168  		statusResult   string
   169  		statusErr      error
   170  		expectedResult bool
   171  		expectedErr    error
   172  	}{
   173  		{
   174  			name:           "existing reservation 1",
   175  			statusResult:   "0 75497472 thin-pool 65 327/524288 14092/589824 36 rw no_discard_passdown queue_if_no_space - ",
   176  			expectedResult: true,
   177  		},
   178  		{
   179  			name:           "existing reservation 2",
   180  			statusResult:   "0 12345 thin-pool 65 327/45678 14092/45678 36 rw discard_passdown error_if_no_space needs_check ",
   181  			expectedResult: true,
   182  		},
   183  		{
   184  			name:           "no reservation 1",
   185  			statusResult:   "0 75497472 thin-pool 65 327/524288 14092/589824 - rw no_discard_passdown error_if_no_space - ",
   186  			expectedResult: false,
   187  		},
   188  		{
   189  			name:           "no reservation 2",
   190  			statusResult:   "0 75 thin-pool 65 327/12345 14092/589824 - rw no_discard_passdown queue_if_no_space - ",
   191  			expectedResult: false,
   192  		},
   193  		{
   194  			name:           "no reservation 2",
   195  			statusResult:   "0 75 thin-pool 65 327/12345 14092/589824 - rw no_discard_passdown queue_if_no_space - ",
   196  			expectedResult: false,
   197  		},
   198  	}
   199  
   200  	for _, tc := range cases {
   201  		fakeDmsetupClient := fake.NewFakeDmsetupClient(t)
   202  		fakeDmsetupClient.AddCommand("status", tc.statusResult, tc.statusErr)
   203  		watcher := &ThinPoolWatcher{dmsetup: fakeDmsetupClient}
   204  		actualResult, err := watcher.checkReservation("test pool")
   205  		if err != nil {
   206  			if tc.expectedErr == nil {
   207  				t.Errorf("%v: unexpected error running checkReservation: %v", tc.name, err)
   208  			}
   209  		} else if tc.expectedErr != nil {
   210  			t.Errorf("%v: unexpected success running checkReservation", tc.name)
   211  		}
   212  
   213  		if e, a := tc.expectedResult, actualResult; e != a {
   214  			t.Errorf("%v: unexpected result from checkReservation: expected: %v got: %v", tc.name, e, a)
   215  		}
   216  	}
   217  }