Repository: rclone/rclone
File: cmd/test/info/info.go (Go)

Code before:

	hashes := hashIn.Sums()
	types := objR.Fs().Hashes().Array()
	for _, Hash := range types {
		sum, err := objR.Hash(r.ctx, Hash)
		if err != nil {
			fs.Infof(r.f, "Streamed file failed when getting hash %v (%v)", Hash, err)
			r.canStream = false
			return
		}
		if !hash.Equals(hashes[Hash], sum) {
			fs.Infof(r.f, "Streamed file has incorrect hash %v: expecting %q got %q", Hash, hashes[Hash], sum)
			r.canStream = false
			return
		}
	}
	if int64(len(contents)) != objR.Size() {
		fs.Infof(r.f, "Streamed file has incorrect file size: expecting %d got %d", len(contents), objR.Size())
		r.canStream = false
		return
	}
	r.canStream = true
}

func readInfo(ctx context.Context, f fs.Fs) error {
	// Generate a unique name for the temporary directory
	tempDirName := "rclone-test-info-" + random.String(8)
	tempDirPath := path.Join(f.Root(), tempDirName)

	// Attempt to create the temporary directory
	err := f.Mkdir(ctx, tempDirPath)
	if err != nil {
		return fmt.Errorf("couldn't create temporary directory: %w", err)
	}

	// Ensure cleanup unless --keep-test-files is specified
	if !keepTestFiles {
		defer func() {
			// Use Purge to recursively delete the temporary directory and its contents
			if doPurge, ok := f.(fs.Purger); ok {
				err := doPurge.Purge(ctx, tempDirPath)
				if err != nil {
					log.Printf("Failed to purge temporary directory: %v", err)
				}
			} else {
				// Fallback cleanup when Purge is not supported
				err := cleanupTempFiles(ctx, f, tempDirPath)
				if err != nil {
					log.Printf("Failed to clean up temporary files: %v", err)
				}
			}

Review comment (suggestion):
I think this code should go at the start - so adjust the remote passed in to `cmd.NewFsDir`

https://github.com/rclone/rclone/blob/f62e7b5b30be8357e53fe0134baafe25cf552238/cmd/test/info/info.go#L87

This means that we create the backend pointing to the correct place at the start and we don't need to create another backend later which can be quite time consuming.

The f.Mkdir still needs to be here though.

Code after:
	in := io.TeeReader(buf, hashIn)

	objIn := object.NewStaticObjectInfo("checkStreamingTest", time.Now(), -1, true, nil, r.f)
	objR, err := putter(r.ctx, in, objIn)
	if err != nil {
		fs.Infof(r.f, "Streamed file failed to upload (%v)", err)
		r.canStream = false
		return
	}

	hashes := hashIn.Sums()
	types := objR.Fs().Hashes().Array()
	for _, Hash := range types {
		sum, err := objR.Hash(r.ctx, Hash)
		if err != nil {
			fs.Infof(r.f, "Streamed file failed when getting hash %v (%v)", Hash, err)
			r.canStream = false
			return
		}
		if !hash.Equals(hashes[Hash], sum) {
			fs.Infof(r.f, "Streamed file has incorrect hash %v: expecting %q got %q", Hash, hashes[Hash], sum)
			r.canStream = false
			return
		}
	}
	if int64(len(contents)) != objR.Size() {
		fs.Infof(r.f, "Streamed file has incorrect file size: expecting %d got %d", len(contents), objR.Size())
		r.canStream = false
		return
	}
	r.canStream = true
}

func readInfo(ctx context.Context, f fs.Fs) error {
	// Ensure cleanup unless --keep-test-files is specified
	if !keepTestFiles {
		defer func() {
			err := operations.Purge(ctx, f, "")
			if err != nil {
				fs.Errorf(f, "Failed to purge temporary directory: %v", err)
			} else {
				fs.Infof(f, "Removed temporary directory for test files: %s", f.Root())
			}
		}()
	}

	r := newResults(ctx, f)
	if checkControl {
		r.checkControls()
	}
	if checkLength {