github.com/demonoid81/containerd@v1.3.4/snapshots/devmapper/metadata_test.go (about)

     1  // +build linux
     2  
     3  /*
     4     Copyright The containerd Authors.
     5  
     6     Licensed under the Apache License, Version 2.0 (the "License");
     7     you may not use this file except in compliance with the License.
     8     You may obtain a copy of the License at
     9  
    10         http://www.apache.org/licenses/LICENSE-2.0
    11  
    12     Unless required by applicable law or agreed to in writing, software
    13     distributed under the License is distributed on an "AS IS" BASIS,
    14     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15     See the License for the specific language governing permissions and
    16     limitations under the License.
    17  */
    18  
    19  package devmapper
    20  
    21  import (
    22  	"context"
    23  	"io/ioutil"
    24  	"os"
    25  	"path/filepath"
    26  	"strconv"
    27  	"testing"
    28  
    29  	"github.com/pkg/errors"
    30  	"go.etcd.io/bbolt"
    31  	"gotest.tools/assert"
    32  	is "gotest.tools/assert/cmp"
    33  )
    34  
    35  var (
    36  	testCtx = context.Background()
    37  )
    38  
    39  func TestPoolMetadata_AddDevice(t *testing.T) {
    40  	tempDir, store := createStore(t)
    41  	defer cleanupStore(t, tempDir, store)
    42  
    43  	expected := &DeviceInfo{
    44  		Name:       "test2",
    45  		ParentName: "test1",
    46  		Size:       1,
    47  		State:      Activated,
    48  	}
    49  
    50  	err := store.AddDevice(testCtx, expected)
    51  	assert.NilError(t, err)
    52  
    53  	result, err := store.GetDevice(testCtx, "test2")
    54  	assert.NilError(t, err)
    55  
    56  	assert.Equal(t, expected.Name, result.Name)
    57  	assert.Equal(t, expected.ParentName, result.ParentName)
    58  	assert.Equal(t, expected.Size, result.Size)
    59  	assert.Equal(t, expected.State, result.State)
    60  	assert.Assert(t, result.DeviceID != 0)
    61  	assert.Equal(t, expected.DeviceID, result.DeviceID)
    62  }
    63  
    64  func TestPoolMetadata_AddDeviceRollback(t *testing.T) {
    65  	tempDir, store := createStore(t)
    66  	defer cleanupStore(t, tempDir, store)
    67  
    68  	err := store.AddDevice(testCtx, &DeviceInfo{Name: ""})
    69  	assert.Assert(t, err != nil)
    70  
    71  	_, err = store.GetDevice(testCtx, "")
    72  	assert.Equal(t, ErrNotFound, err)
    73  }
    74  
    75  func TestPoolMetadata_AddDeviceDuplicate(t *testing.T) {
    76  	tempDir, store := createStore(t)
    77  	defer cleanupStore(t, tempDir, store)
    78  
    79  	err := store.AddDevice(testCtx, &DeviceInfo{Name: "test"})
    80  	assert.NilError(t, err)
    81  
    82  	err = store.AddDevice(testCtx, &DeviceInfo{Name: "test"})
    83  	assert.Equal(t, ErrAlreadyExists, errors.Cause(err))
    84  }
    85  
    86  func TestPoolMetadata_ReuseDeviceID(t *testing.T) {
    87  	tempDir, store := createStore(t)
    88  	defer cleanupStore(t, tempDir, store)
    89  
    90  	info1 := &DeviceInfo{Name: "test1"}
    91  	err := store.AddDevice(testCtx, info1)
    92  	assert.NilError(t, err)
    93  
    94  	info2 := &DeviceInfo{Name: "test2"}
    95  	err = store.AddDevice(testCtx, info2)
    96  	assert.NilError(t, err)
    97  
    98  	assert.Assert(t, info1.DeviceID != info2.DeviceID)
    99  	assert.Assert(t, info1.DeviceID != 0)
   100  
   101  	err = store.RemoveDevice(testCtx, info2.Name)
   102  	assert.NilError(t, err)
   103  
   104  	info3 := &DeviceInfo{Name: "test3"}
   105  	err = store.AddDevice(testCtx, info3)
   106  	assert.NilError(t, err)
   107  
   108  	assert.Equal(t, info2.DeviceID, info3.DeviceID)
   109  }
   110  
   111  func TestPoolMetadata_RemoveDevice(t *testing.T) {
   112  	tempDir, store := createStore(t)
   113  	defer cleanupStore(t, tempDir, store)
   114  
   115  	err := store.AddDevice(testCtx, &DeviceInfo{Name: "test"})
   116  	assert.NilError(t, err)
   117  
   118  	err = store.RemoveDevice(testCtx, "test")
   119  	assert.NilError(t, err)
   120  
   121  	_, err = store.GetDevice(testCtx, "test")
   122  	assert.Equal(t, ErrNotFound, err)
   123  }
   124  
   125  func TestPoolMetadata_UpdateDevice(t *testing.T) {
   126  	tempDir, store := createStore(t)
   127  	defer cleanupStore(t, tempDir, store)
   128  
   129  	oldInfo := &DeviceInfo{
   130  		Name:       "test1",
   131  		ParentName: "test2",
   132  		Size:       3,
   133  		State:      Activated,
   134  	}
   135  
   136  	err := store.AddDevice(testCtx, oldInfo)
   137  	assert.NilError(t, err)
   138  
   139  	err = store.UpdateDevice(testCtx, oldInfo.Name, func(info *DeviceInfo) error {
   140  		info.ParentName = "test5"
   141  		info.Size = 6
   142  		info.State = Created
   143  		return nil
   144  	})
   145  
   146  	assert.NilError(t, err)
   147  
   148  	newInfo, err := store.GetDevice(testCtx, "test1")
   149  	assert.NilError(t, err)
   150  
   151  	assert.Equal(t, "test1", newInfo.Name)
   152  	assert.Equal(t, "test5", newInfo.ParentName)
   153  	assert.Assert(t, newInfo.Size == 6)
   154  	assert.Equal(t, Created, newInfo.State)
   155  }
   156  
   157  func TestPoolMetadata_MarkFaulty(t *testing.T) {
   158  	tempDir, store := createStore(t)
   159  	defer cleanupStore(t, tempDir, store)
   160  
   161  	info := &DeviceInfo{Name: "test"}
   162  	err := store.AddDevice(testCtx, info)
   163  	assert.NilError(t, err)
   164  
   165  	err = store.MarkFaulty(testCtx, "test")
   166  	assert.NilError(t, err)
   167  
   168  	saved, err := store.GetDevice(testCtx, info.Name)
   169  	assert.NilError(t, err)
   170  	assert.Equal(t, saved.State, Faulty)
   171  	assert.Assert(t, saved.DeviceID > 0)
   172  
   173  	// Make sure a device ID marked as faulty as well
   174  	err = store.db.View(func(tx *bbolt.Tx) error {
   175  		bucket := tx.Bucket(deviceIDBucketName)
   176  		key := strconv.FormatUint(uint64(saved.DeviceID), 10)
   177  		value := bucket.Get([]byte(key))
   178  		assert.Equal(t, value[0], byte(deviceFaulty))
   179  		return nil
   180  	})
   181  	assert.NilError(t, err)
   182  }
   183  
   184  func TestPoolMetadata_WalkDevices(t *testing.T) {
   185  	tempDir, store := createStore(t)
   186  	defer cleanupStore(t, tempDir, store)
   187  
   188  	err := store.AddDevice(testCtx, &DeviceInfo{Name: "device1", DeviceID: 1, State: Created})
   189  	assert.NilError(t, err)
   190  
   191  	err = store.AddDevice(testCtx, &DeviceInfo{Name: "device2", DeviceID: 2, State: Faulty})
   192  	assert.NilError(t, err)
   193  
   194  	called := 0
   195  	err = store.WalkDevices(testCtx, func(info *DeviceInfo) error {
   196  		called++
   197  		switch called {
   198  		case 1:
   199  			assert.Equal(t, "device1", info.Name)
   200  			assert.Equal(t, uint32(1), info.DeviceID)
   201  			assert.Equal(t, Created, info.State)
   202  		case 2:
   203  			assert.Equal(t, "device2", info.Name)
   204  			assert.Equal(t, uint32(2), info.DeviceID)
   205  			assert.Equal(t, Faulty, info.State)
   206  		default:
   207  			t.Error("unexpected walk call")
   208  		}
   209  
   210  		return nil
   211  	})
   212  	assert.NilError(t, err)
   213  	assert.Equal(t, called, 2)
   214  }
   215  
   216  func TestPoolMetadata_GetDeviceNames(t *testing.T) {
   217  	tempDir, store := createStore(t)
   218  	defer cleanupStore(t, tempDir, store)
   219  
   220  	err := store.AddDevice(testCtx, &DeviceInfo{Name: "test1"})
   221  	assert.NilError(t, err)
   222  
   223  	err = store.AddDevice(testCtx, &DeviceInfo{Name: "test2"})
   224  	assert.NilError(t, err)
   225  
   226  	names, err := store.GetDeviceNames(testCtx)
   227  	assert.NilError(t, err)
   228  	assert.Assert(t, is.Len(names, 2))
   229  
   230  	assert.Equal(t, "test1", names[0])
   231  	assert.Equal(t, "test2", names[1])
   232  }
   233  
   234  func createStore(t *testing.T) (tempDir string, store *PoolMetadata) {
   235  	tempDir, err := ioutil.TempDir("", "pool-metadata-")
   236  	assert.NilError(t, err, "couldn't create temp directory for metadata tests")
   237  
   238  	path := filepath.Join(tempDir, "test.db")
   239  	metadata, err := NewPoolMetadata(path)
   240  	assert.NilError(t, err)
   241  
   242  	return tempDir, metadata
   243  }
   244  
   245  func cleanupStore(t *testing.T, tempDir string, store *PoolMetadata) {
   246  	err := store.Close()
   247  	assert.NilError(t, err, "failed to close metadata store")
   248  
   249  	err = os.RemoveAll(tempDir)
   250  	assert.NilError(t, err, "failed to cleanup temp directory")
   251  }