func TestStats(t *testing.T) {
	Convey("Test stats of remote file system", t, func() {
		testData, err := testing_utils.NewTestDataContainer("testdata/copy-files", 6)
		So(err, ShouldBeNil)

		copiedDetails, err := copyTestDataToTempDir(testData, "")
		So(err, ShouldBeNil)
		defer copiedDetails.Cleanup()

		sessionFileSystem, err := testingGetNewSessionFileSystem()
		So(err, ShouldBeNil)

		testData.ForeachRelativePath(func(relPath string) {
			fullRemotePath := filepath.Join(copiedDetails.BaseTempDir, relPath)
			remoteStats, err := sessionFileSystem.Stats(fullRemotePath)
			So(err, ShouldBeNil)
			So(remoteStats, ShouldNotBeNil)

			localStats, err := copiedDetails.RemoteFS.Stat(filepath.Join(copiedDetails.BaseTempDir, relPath))
			So(err, ShouldBeNil)

			So(remoteStats.IsDir, ShouldEqual, localStats.IsDir())
			if !remoteStats.ModTime.Equal(localStats.ModTime()) {
				So(fmt.Errorf("Unexpected ModTime stamps remote '%s' vs local '%s'", remoteStats.ModTime.String(), localStats.ModTime().String()), ShouldBeNil)
			}
			So(remoteStats.Mode, ShouldEqual, localStats.Mode())
			So(remoteStats.Size, ShouldEqual, localStats.Size())
		})
	})
}
func TestFileSummary(t *testing.T) {
	Convey("Test file-summary of remote file system", t, func() {
		testData, err := testing_utils.NewTestDataContainer("testdata/copy-files", 6)
		So(err, ShouldBeNil)

		copiedDetails, err := copyTestDataToTempDir(testData, "")
		So(err, ShouldBeNil)
		defer copiedDetails.Cleanup()

		sessionFileSystem, err := testingGetNewSessionFileSystem()
		So(err, ShouldBeNil)
		checksumSvc := checksums.New()

		remoteOrigDir := copiedDetails.CopiedToTempDir
		testData.ForeachRelativeFile(func(relPath string) {
			actualFileSummary, err := sessionFileSystem.FileSummary(filepath.Join(remoteOrigDir, relPath))
			So(err, ShouldBeNil)
			So(actualFileSummary, ShouldNotBeNil)

			fullRemoteFilePath := filepath.Join(copiedDetails.CopiedToTempDir, relPath)
			expectedSummary, err := getFileSummaryForFile(checksumSvc, fullRemoteFilePath)
			So(err, ShouldBeNil)

			So(actualFileSummary.Checksum.HexString(), ShouldEqual, expectedSummary.Checksum.HexString())
			So(actualFileSummary.ModTime.Equal(expectedSummary.ModTime), ShouldBeTrue)
		})
	})
}
func TestUploadTarFile(t *testing.T) {
	Convey("Test Uploading a tar directory", t, func() {
		testData, err := testing_utils.NewTestDataContainer("testdata/copy-files", 6)
		So(err, ShouldBeNil)

		tempRemoteBasePath, err := ioutil.TempDir(os.TempDir(), "gopsexec-client-test-")
		So(err, ShouldBeNil)
		defer os.RemoveAll(tempRemoteBasePath)

		sessionFileSystem, err := testingGetNewSessionFileSystem()
		So(err, ShouldBeNil)

		testData.ForeachRelativeFile(func(relFile string) {
			localFullFilePath := filepath.Join(testData.FullDir, relFile)
			fullTempRemotePath := filepath.Join(tempRemoteBasePath, relFile)

			So(fullTempRemotePath, more_goconvey_assertions.AssertFileExistance, false)

			fileTarProvider := tar_io.Factories.TarProvider.File(localFullFilePath)
			err = sessionFileSystem.UploadTar(fileTarProvider, fullTempRemotePath, false)
			So(err, ShouldBeNil)

			So(fullTempRemotePath, more_goconvey_assertions.AssertFileExistance, true)
			So(testing_utils.CheckFilePropertiesEqual(localFullFilePath, fullTempRemotePath), ShouldBeNil)
		})

		err = os.RemoveAll(tempRemoteBasePath)
		So(err, ShouldBeNil)
		So(tempRemoteBasePath, more_goconvey_assertions.AssertDirectoryExistance, false)
		testData.ForeachRelativeFile(func(relFile string) {
			fullTempRemotePath := filepath.Join(tempRemoteBasePath, relFile)
			So(fullTempRemotePath, more_goconvey_assertions.AssertFileExistance, false)
		})
	})
}
func TestMoveFile(t *testing.T) {
	Convey("Test deletion of file", t, func() {
		testData, err := testing_utils.NewTestDataContainer("testdata/copy-files", 6)
		So(err, ShouldBeNil)

		copiedDetails, err := copyTestDataToTempDir(testData, "orig")
		So(err, ShouldBeNil)
		defer copiedDetails.Cleanup()

		remoteOrigDir := copiedDetails.CopiedToTempDir
		remoteNewDir := filepath.Join(copiedDetails.BaseTempDir, "new")

		sessionFileSystem, err := testingGetNewSessionFileSystem()
		So(err, ShouldBeNil)

		So(remoteOrigDir, more_goconvey_assertions.AssertDirectoryExistance, true)
		testData.ForeachRelativeFile(func(relFile string) {
			fullOldRemoteFilePath := filepath.Join(remoteOrigDir, relFile)
			So(fullOldRemoteFilePath, more_goconvey_assertions.AssertFileExistance, true)
			fullNewRemoteFilePath := filepath.Join(remoteNewDir, relFile)
			So(fullNewRemoteFilePath, more_goconvey_assertions.AssertFileExistance, false)
		})
		So(remoteNewDir, more_goconvey_assertions.AssertDirectoryExistance, false)

		testData.ForeachRelativeFile(func(relFile string) {
			fullOldRemoteFilePath := filepath.Join(remoteOrigDir, relFile)
			So(fullOldRemoteFilePath, more_goconvey_assertions.AssertFileExistance, true)
			fullNewRemoteFilePath := filepath.Join(remoteNewDir, relFile)
			So(fullNewRemoteFilePath, more_goconvey_assertions.AssertFileExistance, false)
			err = sessionFileSystem.Move(fullOldRemoteFilePath, fullNewRemoteFilePath)
			So(err, ShouldBeNil)
		})

		//The old dir must still exist, we only moved the files
		So(remoteOrigDir, more_goconvey_assertions.AssertDirectoryExistance, true)
		So(remoteNewDir, more_goconvey_assertions.AssertDirectoryExistance, true)

		testData.ForeachRelativeFile(func(relFile string) {
			fullOldRemoteFilePath := filepath.Join(remoteOrigDir, relFile)
			So(fullOldRemoteFilePath, more_goconvey_assertions.AssertFileExistance, false)
			parentOldDir := filepath.Dir(fullOldRemoteFilePath)
			So(parentOldDir, more_goconvey_assertions.AssertDirectoryExistance, true)
			fullNewRemoteFilePath := filepath.Join(remoteNewDir, relFile)
			So(fullNewRemoteFilePath, more_goconvey_assertions.AssertFileExistance, true)
		})
	})
}
func TestDirSummary(t *testing.T) {
	Convey("Test dir-summary of remote file system", t, func() {
		testData, err := testing_utils.NewTestDataContainer("testdata/copy-files", 6)
		So(err, ShouldBeNil)

		copiedDetails, err := copyTestDataToTempDir(testData, "")
		So(err, ShouldBeNil)
		defer copiedDetails.Cleanup()

		sessionFileSystem, err := testingGetNewSessionFileSystem()
		So(err, ShouldBeNil)
		checksumSvc := checksums.New()

		remoteOrigDir := copiedDetails.CopiedToTempDir
		summary, err := sessionFileSystem.DirSummary(remoteOrigDir)
		So(err, ShouldBeNil)
		So(summary, ShouldNotBeNil)

		So(summary.FlattenedFileSummaries, ShouldNotResemble, []*filepath_summary.FileSummary{})
		So(len(summary.FlattenedFileSummaries), ShouldNotEqual, 0)

		testData.ForeachRelativeFile(func(relPath string) {
			var actualFileSummary *filepath_summary.FileSummary
			for _, fileSummary := range summary.FlattenedFileSummaries {
				if fileSummary.RelativePath == relPath {
					actualFileSummary = fileSummary
					break
				}
			}
			if actualFileSummary == nil {
				So(fmt.Errorf("Did not find summary for file '%s'", relPath), ShouldBeNil)
			}

			fullRemoteFilePath := filepath.Join(copiedDetails.BaseTempDir, relPath)
			expectedSummary, err := getFileSummaryForFile(checksumSvc, fullRemoteFilePath)
			So(err, ShouldBeNil)

			So(actualFileSummary.Checksum.HexString(), ShouldEqual, expectedSummary.Checksum.HexString())
			So(actualFileSummary.ModTime.Equal(expectedSummary.ModTime), ShouldBeTrue)
		})

		So(len(summary.FlattenedFileSummaries), ShouldEqual, len(testData.RelativeFiles))
	})
}
func TestDeleteFile(t *testing.T) {
	Convey("Test deletion of file", t, func() {
		testData, err := testing_utils.NewTestDataContainer("testdata/copy-files", 6)
		So(err, ShouldBeNil)

		copiedDetails, err := copyTestDataToTempDir(testData, "")
		So(err, ShouldBeNil)
		defer copiedDetails.Cleanup()

		sessionFileSystem, err := testingGetNewSessionFileSystem()
		So(err, ShouldBeNil)

		testData.ForeachRelativeFile(func(relFile string) {
			fullRemoteFilePath := filepath.Join(copiedDetails.BaseTempDir, relFile)
			So(fullRemoteFilePath, more_goconvey_assertions.AssertFileExistance, true)
			err = sessionFileSystem.Delete(fullRemoteFilePath)
			So(err, ShouldBeNil)
			So(fullRemoteFilePath, more_goconvey_assertions.AssertFileExistance, false)
		})
	})
}
func TestDownloadTarDirectory(t *testing.T) {
	Convey("Test Downloading a tar directory", t, func() {
		testDataAsMockRemote, err := testing_utils.NewTestDataContainer("testdata/copy-files", 6)
		So(err, ShouldBeNil)

		tempLocalBasePath, err := ioutil.TempDir(os.TempDir(), "gopsexec-client-test-")
		So(err, ShouldBeNil)
		defer os.RemoveAll(tempLocalBasePath)

		//The dir already exists due to the TempDir method
		testDataAsMockRemote.ForeachRelativeFile(func(relFile string) {
			fullTempLocalPath := filepath.Join(tempLocalBasePath, relFile)
			So(fullTempLocalPath, more_goconvey_assertions.AssertFileExistance, false)
		})

		sessionFileSystem, err := testingGetNewSessionFileSystem()
		So(err, ShouldBeNil)

		tarReceiver := tar_io.Factories.TarReceiver.Dir(tempLocalBasePath)
		err = sessionFileSystem.DownloadTar(testDataAsMockRemote.FullDir, nil, tarReceiver)
		So(err, ShouldBeNil)

		So(tempLocalBasePath, more_goconvey_assertions.AssertDirectoryExistance, true)
		testDataAsMockRemote.ForeachRelativeFile(func(relFile string) {
			remoteFullFilePath := filepath.Join(testDataAsMockRemote.FullDir, relFile)
			fullTempLocalPath := filepath.Join(tempLocalBasePath, relFile)
			So(fullTempLocalPath, more_goconvey_assertions.AssertFileExistance, true)
			So(testing_utils.CheckFilePropertiesEqual(remoteFullFilePath, fullTempLocalPath), ShouldBeNil)
		})

		err = os.RemoveAll(tempLocalBasePath)
		So(err, ShouldBeNil)
		So(tempLocalBasePath, more_goconvey_assertions.AssertDirectoryExistance, false)
		testDataAsMockRemote.ForeachRelativeFile(func(relFile string) {
			fullTempLocalPath := filepath.Join(tempLocalBasePath, relFile)
			So(fullTempLocalPath, more_goconvey_assertions.AssertFileExistance, false)
		})
	})
}