github.com/stackdocker/rkt@v0.10.1-0.20151109095037-1aa827478248/tests/rkt_image_list_test.go (about)

     1  // Copyright 2015 The rkt Authors
     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 main
    16  
    17  import (
    18  	"fmt"
    19  	"os"
    20  	"strings"
    21  	"testing"
    22  
    23  	"github.com/coreos/rkt/tests/testutils"
    24  )
    25  
    26  type ImageId struct {
    27  	path string
    28  	hash string
    29  }
    30  
    31  func (imgId *ImageId) getShortHash(length int) (string, error) {
    32  	if length >= len(imgId.hash) {
    33  		return "", fmt.Errorf("getShortHash: Hash %s is shorter than %d chars", imgId.hash, length)
    34  	}
    35  
    36  	return imgId.hash[:length], nil
    37  }
    38  
    39  // containsConflictingHash returns an ImageId pair if a conflicting short hash is found. The minimum
    40  // hash of 2 chars is used for comparisons.
    41  func (imgId *ImageId) containsConflictingHash(imgIds []ImageId) (imgIdPair []ImageId, found bool) {
    42  	shortHash, err := imgId.getShortHash(2)
    43  	if err != nil {
    44  		panic(fmt.Sprintf("containsConflictingHash: %s", err))
    45  	}
    46  
    47  	for _, iId := range imgIds {
    48  		if strings.HasPrefix(iId.hash, shortHash) {
    49  			imgIdPair = []ImageId{*imgId, iId}
    50  			found = true
    51  			break
    52  		}
    53  	}
    54  	return
    55  }
    56  
    57  // TestShortHash tests that the short hash generated by the rkt image list
    58  // command is usable by the commands that accept image hashes.
    59  func TestShortHash(t *testing.T) {
    60  	var (
    61  		imageIds []ImageId
    62  		iter     int
    63  	)
    64  
    65  	// Generate unique images until we get a collision of the first 2 hash chars
    66  	for {
    67  		image := patchTestACI(fmt.Sprintf("rkt-shorthash-%d.aci", iter), fmt.Sprintf("--name=shorthash--%d", iter))
    68  		defer os.Remove(image)
    69  
    70  		imageHash := getHashOrPanic(image)
    71  		imageId := ImageId{image, imageHash}
    72  
    73  		imageIdPair, isMatch := imageId.containsConflictingHash(imageIds)
    74  		if isMatch {
    75  			imageIds = imageIdPair
    76  			break
    77  		}
    78  
    79  		imageIds = append(imageIds, imageId)
    80  		iter++
    81  	}
    82  	ctx := testutils.NewRktRunCtx()
    83  	defer ctx.Cleanup()
    84  
    85  	// Pull the 2 images with matching first 2 hash chars into cas
    86  	for _, imageId := range imageIds {
    87  		cmd := fmt.Sprintf("%s --insecure-skip-verify fetch %s", ctx.Cmd(), imageId.path)
    88  		t.Logf("Fetching %s: %v", imageId.path, cmd)
    89  		spawnAndWaitOrFail(t, cmd, true)
    90  	}
    91  
    92  	// Get hash from 'rkt image list'
    93  	hash0 := fmt.Sprintf("sha512-%s", imageIds[0].hash[:12])
    94  	hash1 := fmt.Sprintf("sha512-%s", imageIds[1].hash[:12])
    95  	for _, hash := range []string{hash0, hash1} {
    96  		imageListCmd := fmt.Sprintf("%s image list --fields=id --no-legend", ctx.Cmd())
    97  		runRktAndCheckOutput(t, imageListCmd, hash, false)
    98  	}
    99  
   100  	tmpDir := createTempDirOrPanic("rkt_image_list_test")
   101  	defer os.RemoveAll(tmpDir)
   102  
   103  	// Define tests
   104  	tests := []struct {
   105  		cmd        string
   106  		shouldFail bool
   107  		expect     string
   108  	}{
   109  		// Try invalid ID
   110  		{
   111  			"image cat-manifest sha512-12341234",
   112  			true,
   113  			"no image IDs found",
   114  		},
   115  		// Try using one char hash
   116  		{
   117  			fmt.Sprintf("image cat-manifest %s", hash0[:len("sha512-")+1]),
   118  			true,
   119  			"image ID too short",
   120  		},
   121  		// Try short hash that collides
   122  		{
   123  			fmt.Sprintf("image cat-manifest %s", hash0[:len("sha512-")+2]),
   124  			true,
   125  			"ambiguous image ID",
   126  		},
   127  		// Test that 12-char hash works with image cat-manifest
   128  		{
   129  			fmt.Sprintf("image cat-manifest %s", hash0),
   130  			false,
   131  			"ImageManifest",
   132  		},
   133  		// Test that 12-char hash works with image export
   134  		{
   135  			fmt.Sprintf("image export --overwrite %s %s/export.aci", hash0, tmpDir),
   136  			false,
   137  			"",
   138  		},
   139  		// Test that 12-char hash works with image render
   140  		{
   141  			fmt.Sprintf("image render --overwrite %s %s", hash0, tmpDir),
   142  			false,
   143  			"",
   144  		},
   145  		// Test that 12-char hash works with image extract
   146  		{
   147  			fmt.Sprintf("image extract --overwrite %s %s", hash0, tmpDir),
   148  			false,
   149  			"",
   150  		},
   151  		// Test that 12-char hash works with prepare
   152  		{
   153  			fmt.Sprintf("prepare --debug %s", hash0),
   154  			false,
   155  			"Writing pod manifest",
   156  		},
   157  		// Test that 12-char hash works with image rm
   158  		{
   159  			fmt.Sprintf("image rm %s", hash1),
   160  			false,
   161  			"successfully removed aci",
   162  		},
   163  	}
   164  
   165  	// Run tests
   166  	for i, tt := range tests {
   167  		runCmd := fmt.Sprintf("%s %s", ctx.Cmd(), tt.cmd)
   168  		t.Logf("Running test #%d", i)
   169  		runRktAndCheckOutput(t, runCmd, tt.expect, tt.shouldFail)
   170  	}
   171  }