github.com/pkalwak/bagins@v0.0.0-20210317172317-694ac5ce2f54/bag_test.go (about)

     1  package bagins_test
     2  
     3  import (
     4  	//	"fmt"
     5  	"github.com/pkalwak/bagins"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"testing"
    10  )
    11  
    12  const (
    13  	FIXSTRING string = "The quick brown fox jumps over the lazy dog."
    14  	FIXVALUE  string = "e4d909c290d0fb1ca068ffaddf22cbd0" // md5 of string above
    15  )
    16  
    17  func setupTestBag(bagName string) (*bagins.Bag, error) {
    18  	bag, err := bagins.NewBag(os.TempDir(), bagName, []string{"md5"}, false)
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  	return bag, nil
    23  }
    24  
    25  // Setups up a bag with some custom tag files.
    26  func setupCustomBag(bagName string) (*bagins.Bag, error) {
    27  	bag, err := bagins.NewBag(os.TempDir(), bagName, []string{"md5", "sha256"}, true)
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  	bag.AddTagfile("bag-info.txt")
    32  	bagInfo, _ := bag.TagFile("bag-info.txt")
    33  	bagInfo.Data.SetFields([]bagins.TagField{
    34  		*bagins.NewTagField("Source-Organization", "APTrust"),
    35  		*bagins.NewTagField("Bagging-Date", "2016-06-01"),
    36  		*bagins.NewTagField("Bag-Count", "1"),
    37  		*bagins.NewTagField("Internal-Sender-Description", "This is a test bag with no content."),
    38  		*bagins.NewTagField("Internal-Sender-Identification", "Bag XYZ"),
    39  	})
    40  	bag.AddTagfile("aptrust-info.txt")
    41  	aptrustInfo, _ := bag.TagFile("aptrust-info.txt")
    42  	aptrustInfo.Data.SetFields([]bagins.TagField{
    43  		*bagins.NewTagField("Title", "APTrust Generic Test Bag"),
    44  		*bagins.NewTagField("Rights", "Consortia"),
    45  	})
    46  	errors := bag.Save()
    47  	if errors != nil && len(errors) > 0 {
    48  		return nil, errors[0]
    49  	}
    50  	return bag, nil
    51  }
    52  
    53  // Setups up a bag with custom tag files, a custom tag directory,
    54  // and a tag manifest.
    55  func setupTagfileBag(bagName string) (*bagins.Bag, error) {
    56  	bag, err := setupCustomBag(bagName)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	// Tag file in top-level directory
    62  	bag.AddTagfile("laser-tag.txt")
    63  	customTagFile1, _ := bag.TagFile("laser-tag.txt")
    64  	customTagFile1.Data.SetFields([]bagins.TagField{
    65  		*bagins.NewTagField("tic", "tac"),
    66  		*bagins.NewTagField("tick", "tock"),
    67  	})
    68  
    69  	// Tag files in custom directory
    70  	bag.AddTagfile("custom-tags/player-stats.txt")
    71  	customTagFile2, _ := bag.TagFile("custom-tags/player-stats.txt")
    72  	customTagFile2.Data.SetFields([]bagins.TagField{
    73  		*bagins.NewTagField("Batting-Average", ".340"),
    74  		*bagins.NewTagField("What-Time-Is-It", "2016-06-01T12:00:00Z"),
    75  		*bagins.NewTagField("ERA", "1.63"),
    76  		*bagins.NewTagField("Bats", "Left"),
    77  		*bagins.NewTagField("Throws", "Right"),
    78  	})
    79  	bag.AddTagfile("custom-tags/tv-schedule.txt")
    80  	customTagFile3, _ := bag.TagFile("custom-tags/tv-schedule.txt")
    81  	customTagFile3.Data.SetFields([]bagins.TagField{
    82  		*bagins.NewTagField("3:00PM", "House Party"),
    83  		*bagins.NewTagField("4:00PM", "Dexter"),
    84  	})
    85  
    86  	errors := bag.Save()
    87  	if errors != nil && len(errors) > 0 {
    88  		return nil, errors[0]
    89  	}
    90  	return bag, nil
    91  }
    92  
    93  func TestNewBag(t *testing.T) {
    94  
    95  	// It should raise an error if the destination dir does not exist.
    96  	badLocation := filepath.Join(os.TempDir(), "/GOTESTNOT_EXISTs/")
    97  	_, err := bagins.NewBag(badLocation, "_GOFAILBAG_", []string{"md5"}, false)
    98  	if err == nil {
    99  		t.Error("NewBag function does not recognize when a directory does not exist!")
   100  	}
   101  
   102  	// It should raise an error if the bag already exists.
   103  	os.MkdirAll(filepath.Join(badLocation, "_GOFAILBAG_"), 0766)
   104  	defer os.RemoveAll(badLocation)
   105  
   106  	_, err = bagins.NewBag(badLocation, "_GOFAILBAG_", []string{"md5"}, false)
   107  	if err == nil {
   108  		t.Error("Error not thrown when bag already exists as expected.")
   109  	}
   110  
   111  	// It should create a bag without any errors.
   112  	bagName := "_GOTEST_NEWBAG_"
   113  	bag, err := setupTestBag("_GOTEST_NEWBAG_")
   114  	defer os.RemoveAll(bag.Path())
   115  
   116  	// It should find all of the following files and directories.
   117  	if _, err = os.Stat(filepath.Join(os.TempDir(), bagName)); os.IsNotExist(err) {
   118  		t.Error("Bag directory does not exist!")
   119  	}
   120  	if data, err := os.Stat(filepath.Join(os.TempDir(), bagName, "data")); os.IsNotExist(err) || !data.IsDir() {
   121  		t.Error("Data directory does not exist or is not a directory!")
   122  	}
   123  	if _, err = os.Stat(filepath.Join(bag.Path(), "bagit.txt")); os.IsNotExist(err) {
   124  		bi, err := bag.BagInfo()
   125  		if err != nil {
   126  			t.Error(err)
   127  		}
   128  		t.Errorf("bagit.txt does not exist! %s", bi.Name())
   129  	}
   130  	if _, err = os.Stat(filepath.Join(os.TempDir(), bagName, "manifest-md5.txt")); os.IsNotExist(err) {
   131  		t.Error("manifest-md5.txt does not exist!")
   132  	}
   133  }
   134  
   135  func TestReadBag(t *testing.T) {
   136  
   137  	// It should return an error when passed a path that doesn't exist.
   138  	badPath := "/thispath/isbad"
   139  	if _, err := bagins.ReadBag(badPath, []string{}); err == nil {
   140  		t.Errorf("Path %s not detected as bad as expected.", badPath)
   141  	}
   142  
   143  	// It should return an error if it isn't passed a path to a directory.
   144  	fi, _ := ioutil.TempFile("", "TEST_GO_READBAG_")
   145  	fi.WriteString("Test file please delete.")
   146  	fi.Close()
   147  	defer os.Remove(fi.Name())
   148  
   149  	if _, err := bagins.ReadBag(fi.Name(), []string{}); err == nil {
   150  		t.Errorf("Readbag should thrown an error when trying to open a file: %s", fi.Name())
   151  	}
   152  
   153  	// It should return an error if the directory does not contain a data subdirectory.
   154  	pDir, _ := ioutil.TempDir("", "_GOTEST_ReadBag_Payload_")
   155  	defer os.RemoveAll(pDir)
   156  
   157  	if _, err := bagins.ReadBag(pDir, []string{}); err == nil {
   158  		t.Errorf("Not returning expected error when directory has no data subdirectory for %s", pDir)
   159  	}
   160  
   161  	os.Mkdir(filepath.Join(pDir, "data"), os.ModePerm) // Set up data directory for later tests.
   162  
   163  	// It should return an error if there is no manifest file.
   164  	if _, err := bagins.ReadBag(pDir, []string{}); err == nil {
   165  		t.Errorf("Not returning expected error when no manifest file is present in %s", pDir)
   166  	}
   167  
   168  	// It should return an error if it has a bad manifest name.
   169  	ioutil.WriteFile(filepath.Join(pDir, "manifest-sha404.txt"), []byte{}, os.ModePerm)
   170  	if _, err := bagins.ReadBag(pDir, []string{}); err == nil {
   171  		t.Errorf("Not returning expected error when a bad manifest filename is only option %s", pDir)
   172  	}
   173  	os.Remove(filepath.Join(pDir, "manifest-sha404.txt"))
   174  
   175  	// It should return a bag if a valid manifest and data directory exist.
   176  	ioutil.WriteFile(filepath.Join(pDir, "manifest-sha256.txt"), []byte{}, os.ModePerm)
   177  	if _, err := bagins.ReadBag(pDir, []string{}); err != nil {
   178  		t.Errorf("Unexpected error when trying to read raw bag with valid data and manifest: %s", err)
   179  	}
   180  
   181  	// It should read and return a valid bag object reading with a baginfo.txt tagfile.
   182  	bagName := "__GO_READBAG_TEST__"
   183  	bagPath := filepath.Join(os.TempDir(), bagName)
   184  	tb, err := setupTestBag(bagName)
   185  	defer os.RemoveAll(bagPath)
   186  	if err != nil {
   187  		t.Errorf("%s", err)
   188  	}
   189  	tb.Save()
   190  
   191  	testBag, err := bagins.ReadBag(bagPath, []string{"bagit.txt"})
   192  	if err != nil {
   193  		t.Errorf("Unexpected error reading test bag: %s", err)
   194  	}
   195  	baginfo, err := testBag.TagFile("bagit.txt")
   196  	if err != nil {
   197  		t.Errorf("Unexpected error reading bagit.txt file: %s", err)
   198  	}
   199  	if baginfo == nil {
   200  		t.Errorf("Baginfo unexpectedly nil.")
   201  	}
   202  }
   203  
   204  func TestReadCustomBag(t *testing.T) {
   205  	// Setup File to test.
   206  	fi, _ := ioutil.TempFile("", "TEST_READ_CUSTOM_BAG_FILE.txt")
   207  	fi.WriteString(FIXSTRING)
   208  	fi.Close()
   209  	defer os.Remove(fi.Name())
   210  
   211  	// Setup Custom Bag
   212  	bagName := "__GO_TEST_READ_CUSTOM_BAG__"
   213  	bagPath := filepath.Join(os.TempDir(), bagName)
   214  	defer os.RemoveAll(bagPath)
   215  	bag, err := setupCustomBag(bagName)
   216  	if err != nil {
   217  		t.Errorf("Unexpected error setting up custom bag: %s", err)
   218  	}
   219  	bag.AddFile(fi.Name(), fi.Name())
   220  	bag.Save()
   221  	defer os.RemoveAll(bagPath)
   222  
   223  	rBag, err := bagins.ReadBag(bag.Path(), []string{"bag-info.txt", "aptrust-info.txt"})
   224  	if err != nil {
   225  		t.Errorf("Unexpected error reading custom bag: %s", err)
   226  	}
   227  
   228  	bagInfo, err := rBag.TagFile("bag-info.txt")
   229  	if err != nil {
   230  		t.Errorf("Error finding bag-info.txt tag file: %s", err)
   231  	}
   232  	if len(bagInfo.Data.Fields()) != 5 {
   233  		t.Errorf("Expected 5 fields in bag-info.txt but returned %d", len(bagInfo.Data.Fields()))
   234  	}
   235  
   236  	aptrustInfo, err := rBag.TagFile("aptrust-info.txt")
   237  	if err != nil {
   238  		t.Errorf("Error finding aptrust-info.txt tag file: %s", err)
   239  	}
   240  	if len(aptrustInfo.Data.Fields()) != 2 {
   241  		t.Errorf("Expected 2 fields in aptrust-info.txt but returned %d", len(aptrustInfo.Data.Fields()))
   242  	}
   243  
   244  	// Check payload manifests
   245  	payloadManifests := rBag.GetManifests(bagins.PayloadManifest)
   246  	if len(payloadManifests) != 2 {
   247  		t.Errorf("Expected 2 payload manifests, got %d", len(payloadManifests))
   248  	} else {
   249  		if payloadManifests[0].Algorithm() != "md5" {
   250  			t.Errorf("Expected first manifest to be md5, got %s", payloadManifests[0].Algorithm())
   251  		}
   252  		// Payload md5 manifest should have one entry
   253  		if len(payloadManifests[0].Data) != 1 {
   254  			t.Errorf("Payload manifest should have one entry, found %s", len(payloadManifests[0].Data))
   255  		}
   256  		for key, value := range payloadManifests[0].Data {
   257  			dataFilePath := filepath.Join("data", fi.Name())
   258  			if key != dataFilePath {
   259  				t.Errorf("Missing expected manifest entry for %s. Got %s", dataFilePath, key)
   260  			}
   261  			if value != "e4d909c290d0fb1ca068ffaddf22cbd0" {
   262  				t.Errorf("Incorrect md5 checksum. Got %s", value)
   263  			}
   264  		}
   265  
   266  		if payloadManifests[1].Algorithm() != "sha256" {
   267  			t.Errorf("Expected first manifest to be sha256, got %s", payloadManifests[1].Algorithm())
   268  		}
   269  		// Payload sha256 manifest should have one entry
   270  		if len(payloadManifests[1].Data) != 1 {
   271  			t.Errorf("Payload manifest should have one entry, found %s", len(payloadManifests[1].Data))
   272  		}
   273  		for key, value := range payloadManifests[1].Data {
   274  			dataFilePath := filepath.Join("data", fi.Name())
   275  			if key != dataFilePath {
   276  				t.Errorf("Missing expected manifest entry for %s. Got %s", dataFilePath, key)
   277  			}
   278  			if value != "ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c" {
   279  				t.Errorf("Incorrect md5 checksum. Got %s", value)
   280  			}
   281  		}
   282  	}
   283  }
   284  
   285  func TestReadTagFileBag(t *testing.T) {
   286  	// Setup File to test.
   287  	testFileName := "TEST_READ_TAGFILE_BAG_FILE.txt"
   288  	fi, _ := ioutil.TempFile("", testFileName)
   289  	fi.WriteString(FIXSTRING)
   290  	fi.Close()
   291  	defer os.Remove(fi.Name())
   292  
   293  	// Setup bag with custom tag files
   294  	bagName := "__GO_TEST_READ_TAGFILE_BAG__"
   295  	bagPath := filepath.Join(os.TempDir(), bagName)
   296  	defer os.RemoveAll(bagPath)
   297  
   298  	bag, err := setupTagfileBag(bagName)
   299  	if err != nil {
   300  		t.Errorf("Unexpected error setting up tagfile bag: %s", err)
   301  	}
   302  	bag.AddFile(fi.Name(), testFileName)
   303  	bag.Save()
   304  
   305  	rBag, err := bagins.ReadBag(bag.Path(), []string{"bagit.txt", "bag-info.txt", "aptrust-info.txt"})
   306  	if err != nil {
   307  		t.Errorf("Unexpected error reading custom bag: %s", err)
   308  	}
   309  
   310  	bagInfo, err := rBag.TagFile("bag-info.txt")
   311  	if err != nil {
   312  		t.Errorf("Error finding bag-info.txt tag file: %s", err)
   313  	}
   314  	if len(bagInfo.Data.Fields()) != 5 {
   315  		t.Errorf("Expected 5 fields in bag-info.txt but returned %d", len(bagInfo.Data.Fields()))
   316  	}
   317  
   318  	aptrustInfo, err := rBag.TagFile("aptrust-info.txt")
   319  	if err != nil {
   320  		t.Errorf("Error finding aptrust-info.txt tag file: %s", err)
   321  	}
   322  	if len(aptrustInfo.Data.Fields()) != 2 {
   323  		t.Errorf("Expected 2 fields in aptrust-info.txt but returned %d", len(aptrustInfo.Data.Fields()))
   324  	}
   325  
   326  	// Check payload manifests
   327  	payloadManifests := rBag.GetManifests(bagins.PayloadManifest)
   328  	if len(payloadManifests) != 2 {
   329  		t.Errorf("Expected 2 payload manifests, got %d", len(payloadManifests))
   330  	} else {
   331  		if payloadManifests[0].Algorithm() != "md5" {
   332  			t.Errorf("Expected first manifest to be md5, got %s", payloadManifests[0].Algorithm())
   333  		}
   334  		// Payload md5 manifest should have one entry
   335  		if len(payloadManifests[0].Data) != 1 {
   336  			t.Errorf("Payload manifest should have one entry, found %s", len(payloadManifests[0].Data))
   337  		}
   338  		for key, value := range payloadManifests[0].Data {
   339  			dataFilePath := filepath.Join("data", testFileName)
   340  			if key != dataFilePath {
   341  				t.Errorf("Missing expected manifest entry for %s. Got %s", dataFilePath, key)
   342  			}
   343  			if value != "e4d909c290d0fb1ca068ffaddf22cbd0" {
   344  				t.Errorf("Incorrect md5 checksum. Got %s", value)
   345  			}
   346  		}
   347  
   348  		if payloadManifests[1].Algorithm() != "sha256" {
   349  			t.Errorf("Expected first manifest to be sha256, got %s", payloadManifests[1].Algorithm())
   350  		}
   351  		// Payload sha256 manifest should have one entry
   352  		if len(payloadManifests[1].Data) != 1 {
   353  			t.Errorf("Payload manifest should have one entry, found %s", len(payloadManifests[1].Data))
   354  		}
   355  		for key, value := range payloadManifests[1].Data {
   356  			dataFilePath := filepath.Join("data", testFileName)
   357  			if key != dataFilePath {
   358  				t.Errorf("Missing expected manifest entry for %s. Got %s", dataFilePath, key)
   359  			}
   360  			if value != "ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c" {
   361  				t.Errorf("Incorrect md5 checksum. Got %s", value)
   362  			}
   363  		}
   364  	}
   365  
   366  	// Check that tag files exist on disk
   367  	aptrustInfoFile := "aptrust-info.txt"
   368  	bagInfoFile := "bag-info.txt"
   369  	bagItFile := "bagit.txt"
   370  	laserTagFile := "laser-tag.txt"
   371  	playerStatsFile := filepath.Join("custom-tags", "player-stats.txt")
   372  	tvScheduleFile := filepath.Join("custom-tags", "tv-schedule.txt")
   373  	manifestMd5 := "manifest-md5.txt"
   374  	manifestSha256 := "manifest-sha256.txt"
   375  
   376  	tagFiles := []string{aptrustInfoFile, bagInfoFile, bagItFile,
   377  		laserTagFile, playerStatsFile, tvScheduleFile}
   378  	for _, tf := range tagFiles {
   379  		absPath := filepath.Join(bagPath, tf)
   380  		_, err = os.Stat(absPath)
   381  		if err != nil && os.IsNotExist(err) {
   382  			t.Errorf("Tag file is not written to disk at %s", tf)
   383  		}
   384  	}
   385  
   386  	// Make sure the bag knows they're there too
   387  	files, err := rBag.ListFiles()
   388  	if err != nil {
   389  		t.Errorf("ListFiles() returned error %v", err)
   390  	}
   391  	expectedFiles := []string{
   392  		"aptrust-info.txt",
   393  		"bag-info.txt",
   394  		"bagit.txt",
   395  		"custom-tags/player-stats.txt",
   396  		"custom-tags/tv-schedule.txt",
   397  		"data/TEST_READ_TAGFILE_BAG_FILE.txt",
   398  		"laser-tag.txt",
   399  		"manifest-md5.txt",
   400  		"manifest-sha256.txt",
   401  		"tagmanifest-md5.txt",
   402  		"tagmanifest-sha256.txt",
   403  	}
   404  	for _, expectedFile := range expectedFiles {
   405  		if !sliceContains(files, expectedFile) {
   406  			t.Errorf("ListFiles did not return file %s", expectedFile)
   407  		}
   408  	}
   409  
   410  	// Make sure the bag knows about the parsed tag files
   411  	expectedParsedFiles := []string{"bagit.txt", "bag-info.txt", "aptrust-info.txt"}
   412  	parsedTagFiles := rBag.ListTagFiles()
   413  	if len(parsedTagFiles) != len(expectedParsedFiles) {
   414  		t.Errorf("Expected %d parsed tag files, got %d",
   415  			len(parsedTagFiles), len(expectedParsedFiles))
   416  	}
   417  
   418  	for _, expected := range expectedParsedFiles {
   419  		if !sliceContains(parsedTagFiles, expected) {
   420  			t.Errorf("ListTagFiles() did not return file %s", expected)
   421  		}
   422  	}
   423  
   424  	// Make sure the bag knows about unparsed tag files
   425  	expectedUnparsed := []string{
   426  		"custom-tags/player-stats.txt",
   427  		"custom-tags/tv-schedule.txt",
   428  		"laser-tag.txt"}
   429  	unparsedTagFiles, err := rBag.UnparsedTagFiles()
   430  	if err != nil {
   431  		t.Errorf("UnparsedTagFiles() returned unexpected error: %v", err)
   432  	}
   433  
   434  	if len(unparsedTagFiles) != len(expectedUnparsed) {
   435  		t.Errorf("Expected %d parsed tag files, got %d",
   436  			len(unparsedTagFiles), len(expectedUnparsed))
   437  	}
   438  
   439  	for _, expected := range expectedUnparsed {
   440  		if !sliceContains(unparsedTagFiles, expected) {
   441  			t.Errorf("UnparsedTagFiles() did not return file %s", expected)
   442  		}
   443  	}
   444  
   445  	// Check tag manifests
   446  	tagManifests := rBag.GetManifests(bagins.TagManifest)
   447  	if len(tagManifests) != 2 {
   448  		t.Errorf("Expected 2 tag manifests, got %d", len(tagManifests))
   449  	} else {
   450  		if tagManifests[0].Algorithm() != "md5" {
   451  			t.Errorf("Expected first manifest to be md5, got %s", tagManifests[0].Algorithm())
   452  		}
   453  		// Tag md5 manifest should have six entries
   454  		if len(tagManifests[0].Data) != 8 {
   455  			t.Errorf("Tag manifest should have 8 entries, found %d", len(tagManifests[0].Data))
   456  		}
   457  
   458  		// Check the fixity values
   459  		md5Entries := make(map[string]string, 6)
   460  		md5Entries[aptrustInfoFile] = "6dd711392d4661322acc469a30565f68"
   461  		md5Entries[bagInfoFile] = "88190858fd93609ae51ca1f06ee575f1"
   462  		md5Entries[bagItFile] = "ada799b7e0f1b7a1dc86d4e99df4b1f4"
   463  		md5Entries[laserTagFile] = "29251712228b36927c43157fe5808552"
   464  		md5Entries[playerStatsFile] = "dfa872f6da2af8087bea5f7ab1dbc1fa"
   465  		md5Entries[tvScheduleFile] = "118df3be000eae34d6e6dbf7f56c649b"
   466  		md5Entries[manifestMd5] = "4c5a8c217cf51fb419e425ddc2f433ee"
   467  		md5Entries[manifestSha256] = "edbc9b8dabe4c894d22cc42d5268867b"
   468  
   469  		for key, expectedValue := range md5Entries {
   470  			actualValue := tagManifests[0].Data[key]
   471  			if actualValue != expectedValue {
   472  				t.Errorf("For tag file %s, expected md5 %s, but got %s",
   473  					key, expectedValue, actualValue)
   474  			}
   475  		}
   476  
   477  		if tagManifests[1].Algorithm() != "sha256" {
   478  			t.Errorf("Expected first manifest to be sha256, got %s", tagManifests[1].Algorithm())
   479  		}
   480  		// Tag sha256 manifest should have 8 entries (2 are for payload manifests)
   481  		if len(tagManifests[1].Data) != 8 {
   482  			t.Errorf("Tag manifest should have 8 entries, found %d", len(tagManifests[1].Data))
   483  		}
   484  
   485  		// Check fixity values
   486  		// Will these checksums break on Windows, where end-of-line is CRLF?
   487  		sha256Entries := make(map[string]string, 6)
   488  		sha256Entries[aptrustInfoFile] =
   489  			"ffe2ab04b87db85886fcfd013c9f09e094b636ca233cd0cbbd1ea300e7a5352c"
   490  		sha256Entries[bagInfoFile] =
   491  			"f0ce035c2ee789a7f8821d6f174a75619c575eea0311c47d03149807d252804d"
   492  		sha256Entries[bagItFile] =
   493  			"49b477e8662d591f49fce44ca5fc7bfe76c5a71f69c85c8d91952a538393e5f4"
   494  		sha256Entries[laserTagFile] =
   495  			"163be000df169eafd84fa0cef6028a4711e53bd3abf9e8c54603035bb92bda95"
   496  		sha256Entries[playerStatsFile] =
   497  			"83137fc6d88212250153bd713954da1d1c5a69c57a55ff97cac07ca6db7ec34d"
   498  		sha256Entries[tvScheduleFile] =
   499  			"fbf223502fe7f470363346283620401d04e77fe43a9a74faa682eebe28417e7c"
   500  		sha256Entries[manifestMd5] =
   501  			"9aab27bb0d2d75d7ac2c26908e2ca85e7121f106445318f7def024f4b520bec2"
   502  		sha256Entries[manifestSha256] =
   503  			"2a9e5d86070459a652fdc2ce13f5358ede42b10a3e0580e149b0d3df938ffe30"
   504  
   505  		for key, expectedValue := range sha256Entries {
   506  			actualValue := tagManifests[1].Data[key]
   507  			if actualValue != expectedValue {
   508  				t.Errorf("For tag file %s, expected sha256 %s, but got %s",
   509  					key, expectedValue, actualValue)
   510  			}
   511  		}
   512  	}
   513  }
   514  
   515  // It should place an appropriate file in the data directory and add the fixity to the manifest.
   516  func TestAddFile(t *testing.T) {
   517  	// Setup the test file to add for the test.
   518  	fi, _ := ioutil.TempFile("", "TEST_GO_ADDFILE_")
   519  	fi.WriteString("Test the checksum")
   520  	fi.Close()
   521  	defer os.Remove(fi.Name())
   522  
   523  	// Setup the Test Bag
   524  	bag, _ := setupTestBag("_GOTEST_BAG_ADDFILE_")
   525  	defer os.RemoveAll(bag.Path())
   526  
   527  	// It should return an error when trying to add a file that doesn't exist.
   528  	if err := bag.AddFile("idontexist.txt", "idontexist.txt"); err == nil {
   529  		t.Errorf("Adding a nonexistant file did not generate an error!")
   530  	}
   531  
   532  	// It should add a file to the data directory and generate a fixity value.
   533  	expFile := "my/nested/dir/mytestfile.txt"
   534  	if err := bag.AddFile(fi.Name(), expFile); err != nil {
   535  		t.Error(err)
   536  	}
   537  
   538  	// It should have created the file in the payload directory.
   539  	_, err := os.Stat(filepath.Join(bag.Path(), "data", expFile))
   540  	if err != nil {
   541  		t.Error("Testing if payload file created:", err)
   542  	}
   543  
   544  	// It should have calulated the fixity and put it in the manifest.
   545  	if bag.Manifests == nil || len(bag.Manifests) == 0 {
   546  		t.Error("Bag manifest is missing")
   547  		return
   548  	}
   549  	mf := bag.Manifests[0]
   550  	expKey := filepath.Join("data", expFile)
   551  	fx, ok := mf.Data[expKey]
   552  	if !ok {
   553  		t.Error("Unable to find entry in manfest: ", expKey)
   554  	}
   555  	if len(fx) != 32 {
   556  		t.Errorf("Expected %d character fixity but returned: %d", 32, len(fx))
   557  	}
   558  }
   559  
   560  func TestAddCustomTagfile(t *testing.T) {
   561  	// Setup File to test.
   562  	fi, _ := ioutil.TempFile("", "TEST_READ_CUSTOM_BAG_FILE.txt")
   563  	fi.WriteString(FIXSTRING)
   564  	fi.Close()
   565  	defer os.Remove(fi.Name())
   566  
   567  	// Setup Custom Bag
   568  	bagName := "__GO_TEST_ADD_CUSTOM_TAG_FILE__"
   569  	bagPath := filepath.Join(os.TempDir(), bagName)
   570  	defer os.RemoveAll(bagPath)
   571  	bag, err := setupCustomBag(bagName)
   572  	if err != nil {
   573  		t.Errorf("Unexpected error setting up custom bag: %s", err)
   574  	}
   575  	bag.AddCustomTagfile(fi.Name(), "custom-tags/in_manifest.txt", true)
   576  	bag.AddCustomTagfile(fi.Name(), "custom-tags/not_in_manifest.txt", false)
   577  	bag.Save()
   578  	defer os.RemoveAll(bagPath)
   579  
   580  	rBag, err := bagins.ReadBag(bag.Path(), []string{"bag-info.txt", "aptrust-info.txt"})
   581  	if err != nil {
   582  		t.Errorf("Unexpected error reading custom bag: %s", err)
   583  	}
   584  
   585  	files, err := rBag.ListFiles()
   586  	if err != nil {
   587  		t.Errorf("Error listing bag files: %v", err)
   588  	}
   589  
   590  	// Make sure the file exists
   591  	if !sliceContains(files, "custom-tags/in_manifest.txt") {
   592  		t.Errorf("Custom tag file 'custom-tags/in_manifest.txt' is not in the bag")
   593  	}
   594  	if !sliceContains(files, "custom-tags/not_in_manifest.txt") {
   595  		t.Errorf("Custom tag file 'custom-tags/not_in_manifest.txt' is not in the bag")
   596  	}
   597  
   598  	// First file should be in the tag manifests. Second file should not.
   599  	tagManifests := rBag.GetManifests(bagins.TagManifest)
   600  	for _, tagManifest := range tagManifests {
   601  		if _, exists := tagManifest.Data["custom-tags/in_manifest.txt"]; exists == false {
   602  			t.Errorf("File 'custom-tags/in_manifest.txt' is missing from tagmanifest-%s.txt",
   603  				tagManifest.Algorithm())
   604  		}
   605  		if _, exists := tagManifest.Data["custom-tags/not_in_manifest.txt"]; exists == true {
   606  			t.Errorf("File 'custom-tags/not_in_manifest.txt' is should not have an entry in "+
   607  				"tagmanifest-%s.txt, but it does", tagManifest.Algorithm())
   608  		}
   609  	}
   610  }
   611  
   612  func TestListTagFiles(t *testing.T) {
   613  	// Setup Custom Bag
   614  	bagName := "__GO_TEST_LIST_TAG_FILES__"
   615  	bagPath := filepath.Join(os.TempDir(), bagName)
   616  	defer os.RemoveAll(bagPath)
   617  	bag, err := setupCustomBag(bagName)
   618  	if err != nil {
   619  		t.Errorf("Unexpected error setting up custom bag: %s", err)
   620  	}
   621  
   622  	expected := []string{"bagit.txt", "bag-info.txt", "aptrust-info.txt"}
   623  	if len(bag.ListTagFiles()) != len(expected) {
   624  		t.Errorf("Expected %d tag files but returned %d", len(expected), len(bag.ListTagFiles()))
   625  	}
   626  	for _, name := range expected {
   627  		if _, err := bag.TagFile(name); err != nil {
   628  			t.Errorf("Error getting tag file %s: %s", name, err)
   629  		}
   630  	}
   631  }
   632  
   633  func TestAddDir(t *testing.T) {
   634  
   635  	// Setup source files to test
   636  	srcDir, _ := ioutil.TempDir("", "_GOTEST_PAYLOAD_SRC_")
   637  	for i := 0; i < 50; i++ {
   638  		fi, _ := ioutil.TempFile(srcDir, "TEST_GO_ADDFILE_")
   639  		fi.WriteString(FIXSTRING)
   640  		fi.Close()
   641  	}
   642  	defer os.RemoveAll(srcDir)
   643  
   644  	// Setup the test bag
   645  	bag, err := setupTestBag("_GOTEST_BAG_ADDDIR_")
   646  	if err != nil {
   647  		t.Error(err.Error())
   648  		return
   649  	}
   650  	defer os.RemoveAll(bag.Path())
   651  
   652  	// It should produce no errors
   653  	if errs := bag.AddDir(srcDir); len(errs) != 0 {
   654  		t.Error(errs)
   655  	}
   656  
   657  	// It should produce 50 manifest entries
   658  	if bag.Manifests == nil || len(bag.Manifests) == 0 {
   659  		t.Error("Bag manifest is missing")
   660  		return
   661  	}
   662  	manifest := bag.Manifests[0]
   663  	if len(manifest.Data) != 50 {
   664  		t.Error("Expected 50 manifest entries but returned", len(manifest.Data))
   665  	}
   666  	// It should contain the proper checksums for each file.
   667  	errs := manifest.RunChecksums()
   668  	for _, err := range errs {
   669  		t.Errorf("%s", err)
   670  	}
   671  }
   672  
   673  func TestManifest(t *testing.T) {
   674  
   675  	// Setup the test bag
   676  	bag, _ := setupTestBag("_GOTEST_BAG_MANIFEST_")
   677  	defer os.RemoveAll(bag.Path())
   678  
   679  	// It should have the expected name and return no error.
   680  	if bag.Manifests == nil || len(bag.Manifests) == 0 {
   681  		t.Error("Bag manifest is missing")
   682  		return
   683  	}
   684  	mf := bag.Manifests[0]
   685  	exp := "manifest-md5.txt"
   686  	if filepath.Base(mf.Name()) != exp {
   687  		t.Error("Expected manifest name", exp, "but returned", filepath.Base(mf.Name()))
   688  	}
   689  }
   690  
   691  func TestAddTagFile(t *testing.T) {
   692  
   693  	// Setup the test bag
   694  	bag, _ := setupTestBag("_GOTEST_BAG_ADDTAGFILE_")
   695  	defer os.RemoveAll(bag.Path())
   696  
   697  	// It should throw an error when a bag tagfilename is passed.
   698  	badTagName := "customtag/directory/tag"
   699  	if err := bag.AddTagfile(badTagName); err == nil {
   700  		t.Error("Did not generate an error when trying to add bag tagname:", badTagName)
   701  	}
   702  
   703  	// It should not throw an error.
   704  	newTagName := "customtag/directory/tag.txt"
   705  	if err := bag.AddTagfile(newTagName); err != nil {
   706  		t.Error(err)
   707  	}
   708  
   709  	// It should be able to lookup the tagfile by name.
   710  	if _, err := bag.TagFile(newTagName); err != nil {
   711  		t.Error(err)
   712  	}
   713  
   714  	// Even tagfiles passed as root should be put under the bag.
   715  	oddTagName := "/lookslikeroot/directory/tag.txt"
   716  	if err := bag.AddTagfile(oddTagName); err != nil {
   717  		t.Error(err)
   718  	}
   719  
   720  	// It should be able to lookup the tagfile by name.
   721  	if _, err := bag.TagFile(oddTagName); err != nil {
   722  		t.Error(err)
   723  	}
   724  
   725  	// It should find the file inside the bag.
   726  	if _, err := os.Stat(filepath.Join(bag.Path(), newTagName)); err != nil {
   727  		t.Error(err)
   728  	}
   729  }
   730  
   731  func TestTagFile(t *testing.T) {
   732  
   733  	// Setup the test bag
   734  	bag, _ := setupTestBag("_GOTEST_BAG_TAGFILE_")
   735  	defer os.RemoveAll(bag.Path())
   736  
   737  	// It should find the tag file by name
   738  	testTagName := "new/tag.txt"
   739  	bag.AddTagfile(testTagName)
   740  	if _, err := bag.TagFile(testTagName); err != nil {
   741  		t.Error(err)
   742  	}
   743  
   744  	// It should return an error if asking for a bad tag name.
   745  	badTagName := "/new/tag.txt"
   746  	if _, err := bag.TagFile(badTagName); err == nil {
   747  		t.Error("Bag.TagFile returned results for", badTagName, "when it should not exist.")
   748  	}
   749  }
   750  
   751  func TestPath(t *testing.T) {
   752  	// Stup the test bag
   753  	bagName := "_GOTEST_BAG_PATH_"
   754  	bag, _ := setupTestBag(bagName)
   755  	defer os.RemoveAll(bag.Path())
   756  
   757  	expPath := filepath.Join(os.TempDir(), bagName)
   758  	if bag.Path() != expPath {
   759  		t.Error("Excpected", bag.Path(), "and", expPath, "to be equal!")
   760  	}
   761  }
   762  
   763  func TestSave(t *testing.T) {
   764  	// Setup test bag
   765  	bag, _ := setupTestBag("_GOTEST_BAG_CLOSE_")
   766  	defer os.RemoveAll(bag.Path())
   767  
   768  	// Add some data to the manifest and make sure it writes it on close.
   769  	bag.Manifests[0].Data["data/fakefile.txt"] = "da909ba395016f2a64b04d706520db6afa74fc95"
   770  
   771  	// It should not throw an error.
   772  	if errs := bag.Save(); len(errs) != 0 {
   773  		for idx := range errs {
   774  			t.Error(errs[idx])
   775  		}
   776  	}
   777  
   778  	// The manifest file should contain data.
   779  	content, err := ioutil.ReadFile(bag.Manifests[0].Name())
   780  	if err != nil {
   781  		t.Error(err)
   782  	}
   783  	exp := 59 // Length of values entered above and newline.
   784  	if len(content) != 59 {
   785  		t.Error("Expected ", exp, "but found", len(content), "characters written")
   786  	}
   787  
   788  	// Add some tagfile data to make sure it writes it on close.
   789  	tfName := "extratagfile.txt"
   790  	bag.AddTagfile("extratagfile.txt")
   791  	tf, _ := bag.TagFile(tfName)
   792  	tf.Data.AddField(*bagins.NewTagField("MyNewField", "This is testdata."))
   793  
   794  	// it should not throw an error.
   795  	if errs := bag.Save(); len(errs) != 0 {
   796  		for idx := range errs {
   797  			t.Error(errs[idx])
   798  		}
   799  	}
   800  
   801  	// The TagFile should contain data.
   802  	content, err = ioutil.ReadFile(tf.Name())
   803  	if err != nil {
   804  		t.Error(err)
   805  	}
   806  	exp = 10 // Some length the string needs to be abovel
   807  	if len(content) < exp {
   808  		t.Error("Didn't find data in tagfile", tfName, "as expected!")
   809  	}
   810  }
   811  
   812  func TestListFiles(t *testing.T) {
   813  
   814  	// Setup the test bag.
   815  	bag, _ := setupTestBag("_GOTEST_BAG_LISTFILES_")
   816  	defer os.RemoveAll(bag.Path())
   817  
   818  	// Setup the test file to add for the test.
   819  	fi, _ := os.Create(filepath.Join(bag.Path(), "data", "TEST_GO_DATAFILE.txt"))
   820  	fi.WriteString("Test the checksum")
   821  	fi.Close()
   822  
   823  	expFiles := make(map[string]bool)
   824  	expFiles["manifest-md5.txt"] = true
   825  	expFiles["bagit.txt"] = true
   826  	expFiles[filepath.Join("data", "TEST_GO_DATAFILE.txt")] = true
   827  
   828  	cn, _ := bag.ListFiles()
   829  
   830  	for _, fName := range cn {
   831  		if _, ok := expFiles[fName]; !ok {
   832  			t.Error("Unexpected file:", fName)
   833  		}
   834  	}
   835  }
   836  
   837  func sliceContains(list []string, item string) bool {
   838  	for _, value := range list {
   839  		if value == item {
   840  			return true
   841  		}
   842  	}
   843  	return false
   844  }