diff --git a/ext4/tar2ext4/tar2ext4_test.go b/ext4/tar2ext4/tar2ext4_test.go new file mode 100644 index 0000000000..cfbb3ec669 --- /dev/null +++ b/ext4/tar2ext4/tar2ext4_test.go @@ -0,0 +1,90 @@ +package tar2ext4 + +import ( + "path/filepath" + "testing" + + "archive/tar" + "os" + "strings" + "time" +) + +// Test_UnorderedTarExpansion tests that we are correctly able to expand a layer tar file +// which has one or many files in an unordered fashion. By unordered we mean that the +// entry of a file shows up during an expansion before the entry of one of the parent +// directories of that file. In such cases we create that parent directory with same +// permissions as its parent and then later on fix the permissions when we actually see +// the entry of that parent directory. +func Test_UnorderedTarExpansion(t *testing.T) { + tmpTarFilePath := filepath.Join(os.TempDir(), "test-layer.tar") + layerTar, err := os.Create(tmpTarFilePath) + if err != nil { + t.Fatalf("failed to create output file: %s", err) + } + defer os.Remove(tmpTarFilePath) + + tw := tar.NewWriter(layerTar) + var files = []struct { + path, body string + }{ + {"data/", ""}, + {"root.txt", "inside root.txt"}, + {"foo/bar.txt", "inside bar.txt"}, + {"foo/", ""}, + {"A/B/b.txt", "inside b.txt"}, + {"A/a.txt", "inside a.txt"}, + {"A/", ""}, + {"A/B/", ""}, + } + for _, file := range files { + var hdr *tar.Header + if strings.HasSuffix(file.path, "/") { + hdr = &tar.Header{ + Name: file.path, + Mode: 0777, + Size: 0, + ModTime: time.Now(), + AccessTime: time.Now(), + ChangeTime: time.Now(), + } + } else { + hdr = &tar.Header{ + Name: file.path, + Mode: 0777, + Size: int64(len(file.body)), + ModTime: time.Now(), + AccessTime: time.Now(), + ChangeTime: time.Now(), + } + } + if err := tw.WriteHeader(hdr); err != nil { + t.Fatal(err) + } + if !strings.HasSuffix(file.path, "/") { + if _, err := tw.Write([]byte(file.body)); err != nil { + t.Fatal(err) + } + } + } + if err := tw.Close(); err != nil { + t.Fatal(err) + } + + // Now try to import this tar and verify that there is no failure. + if _, err := layerTar.Seek(0, 0); err != nil { + t.Fatalf("failed to seek file: %s", err) + } + + opts := []Option{AppendVhdFooter, ConvertWhiteout} + tmpVhdPath := filepath.Join(os.TempDir(), "test-vhd.vhdx") + layerVhd, err := os.Create(tmpVhdPath) + if err != nil { + t.Fatalf("failed to create output VHD: %s", err) + } + defer os.Remove(tmpVhdPath) + + if err := Convert(layerTar, layerVhd, opts...); err != nil { + t.Fatalf("failed to convert tar to layer vhd: %s", err) + } +}