mirror of
https://github.com/rclone/rclone.git
synced 2024-11-22 16:34:30 +01:00
cmd/gitannex: Replace e2e test script with Go test
This commit implements milestone 2.1 for the gitannex subcommand: https://github.com/rclone/rclone/issues/7625#issuecomment-1951403856 This rewrite makes a few improvements over the old shell script: (1) It no longer uses the system's rclone.conf. Now, it writes the rclone.conf file in an ephemeral directory. (2) It no longer makes any assumptions about the contents of /tmp. However, it now assumes that an rclone built from the HEAD commit is on the PATH. It makes a best-effort attempt to verify this assumption, but I'm not sure it's bulletproof. I'm hoping that writing this in Go will enable more cross-platform support in the future, but for now we're still restricted to Unixy systems due to reliance on the HOME environment variable. Issue #7625
This commit is contained in:
parent
6a5c0065ef
commit
ef42c32cc6
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@ -124,7 +124,7 @@ jobs:
|
|||||||
sudo modprobe fuse
|
sudo modprobe fuse
|
||||||
sudo chmod 666 /dev/fuse
|
sudo chmod 666 /dev/fuse
|
||||||
sudo chown root:$USER /etc/fuse.conf
|
sudo chown root:$USER /etc/fuse.conf
|
||||||
sudo apt-get install fuse3 libfuse-dev rpm pkg-config
|
sudo apt-get install fuse3 libfuse-dev rpm pkg-config git-annex
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
|
|
||||||
- name: Install Libraries on macOS
|
- name: Install Libraries on macOS
|
||||||
@ -137,6 +137,7 @@ jobs:
|
|||||||
brew untap --force homebrew/cask
|
brew untap --force homebrew/cask
|
||||||
brew update
|
brew update
|
||||||
brew install --cask macfuse
|
brew install --cask macfuse
|
||||||
|
brew install git-annex
|
||||||
if: matrix.os == 'macos-11'
|
if: matrix.os == 'macos-11'
|
||||||
|
|
||||||
- name: Install Libraries on Windows
|
- name: Install Libraries on Windows
|
||||||
|
159
cmd/gitannex/e2e_test.go
Normal file
159
cmd/gitannex/e2e_test.go
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
package gitannex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/rclone/rclone/fs"
|
||||||
|
"github.com/rclone/rclone/lib/buildinfo"
|
||||||
|
)
|
||||||
|
|
||||||
|
// checkRcloneBinaryVersion runs whichever rclone is on the PATH and checks
|
||||||
|
// whether it reports a version that matches the test's expectations. Returns
|
||||||
|
// nil when the version is the expected version, otherwise returns an error.
|
||||||
|
func checkRcloneBinaryVersion() error {
|
||||||
|
// versionInfo is a subset of information produced by "core/version".
|
||||||
|
type versionInfo struct {
|
||||||
|
Version string
|
||||||
|
IsGit bool
|
||||||
|
GoTags string
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command("rclone", "rc", "--loopback", "core/version")
|
||||||
|
stdout, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get rclone version: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsed versionInfo
|
||||||
|
if err := json.Unmarshal(stdout, &parsed); err != nil {
|
||||||
|
return fmt.Errorf("failed to parse rclone version: %w", err)
|
||||||
|
}
|
||||||
|
if parsed.Version != fs.Version {
|
||||||
|
return fmt.Errorf("expected version %q, but got %q", fs.Version, parsed.Version)
|
||||||
|
}
|
||||||
|
if !parsed.IsGit {
|
||||||
|
return errors.New("expected rclone to be a dev build")
|
||||||
|
}
|
||||||
|
_, tagString := buildinfo.GetLinkingAndTags()
|
||||||
|
if parsed.GoTags != tagString {
|
||||||
|
return fmt.Errorf("expected tag string %q, but got %q", tagString, parsed.GoTags)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// This end-to-end test runs `git annex testremote` in a temporary git repo.
|
||||||
|
// This test will be skipped unless the `rclone` binary on PATH reports the
|
||||||
|
// expected version.
|
||||||
|
//
|
||||||
|
// When run on CI, an rclone binary built from HEAD will be on the PATH. When
|
||||||
|
// running locally, you will likely need to ensure the current binary is on the
|
||||||
|
// PATH like so:
|
||||||
|
//
|
||||||
|
// go build && PATH="$(realpath .):$PATH" go test -v ./cmd/gitannex/...
|
||||||
|
//
|
||||||
|
// In the future, this test will probably be extended to test a number of
|
||||||
|
// parameters like repo layouts, and runtime may suffer from a combinatorial
|
||||||
|
// explosion.
|
||||||
|
func TestEndToEnd(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping due to short mode.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Support this test on Windows. Need to evaluate the semantics of the
|
||||||
|
// HOME and PATH environment variables.
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin",
|
||||||
|
"freebsd",
|
||||||
|
"linux",
|
||||||
|
"netbsd",
|
||||||
|
"openbsd",
|
||||||
|
"plan9",
|
||||||
|
"solaris":
|
||||||
|
default:
|
||||||
|
t.Skipf("GOOS %q is not supported.", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := checkRcloneBinaryVersion(); err != nil {
|
||||||
|
t.Skipf("Skipping due to rclone version: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := exec.LookPath("git-annex"); err != nil {
|
||||||
|
t.Skipf("Skipping because git-annex was not found: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temp directory and chdir there, just in case.
|
||||||
|
originalWd, err := os.Getwd()
|
||||||
|
require.NoError(t, err)
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
require.NoError(t, os.Chdir(tempDir))
|
||||||
|
defer func() { require.NoError(t, os.Chdir(originalWd)) }()
|
||||||
|
|
||||||
|
// Flesh out subdirectories of the temp directory:
|
||||||
|
//
|
||||||
|
// .
|
||||||
|
// |-- bin
|
||||||
|
// | `-- git-annex-remote-rclone-builtin -> ${PATH_TO_RCLONE_BINARY}
|
||||||
|
// |-- ephemeralRepo
|
||||||
|
// `-- user
|
||||||
|
// `-- .config
|
||||||
|
// `-- rclone
|
||||||
|
// `-- rclone.conf
|
||||||
|
|
||||||
|
binDir := filepath.Join(tempDir, "bin")
|
||||||
|
homeDir := filepath.Join(tempDir, "user")
|
||||||
|
configDir := filepath.Join(homeDir, ".config")
|
||||||
|
rcloneConfigDir := filepath.Join(configDir, "rclone")
|
||||||
|
ephemeralRepoDir := filepath.Join(tempDir, "ephemeralRepo")
|
||||||
|
for _, dir := range []string{binDir, homeDir, configDir, rcloneConfigDir, ephemeralRepoDir} {
|
||||||
|
require.NoError(t, os.Mkdir(dir, 0700))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Install the symlink that enables git-annex to invoke "rclone gitannex"
|
||||||
|
// without explicitly specifying the subcommand.
|
||||||
|
rcloneBinaryPath, err := exec.LookPath("rclone")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, os.Symlink(
|
||||||
|
rcloneBinaryPath,
|
||||||
|
filepath.Join(binDir, "git-annex-remote-rclone-builtin")))
|
||||||
|
|
||||||
|
// Install the rclone.conf file that defines the remote.
|
||||||
|
rcloneConfigPath := filepath.Join(rcloneConfigDir, "rclone.conf")
|
||||||
|
rcloneConfigContents := "[MyRcloneRemote]\ntype = local"
|
||||||
|
require.NoError(t, os.WriteFile(rcloneConfigPath, []byte(rcloneConfigContents), 0600))
|
||||||
|
|
||||||
|
// NOTE: These commands must be run with HOME pointing at an ephemeral
|
||||||
|
// directory, rather than the real home directory.
|
||||||
|
cmds := [][]string{
|
||||||
|
{"git", "annex", "version"},
|
||||||
|
{"git", "config", "--global", "user.name", "User Name"},
|
||||||
|
{"git", "config", "--global", "user.email", "user@example.com"},
|
||||||
|
{"git", "init"},
|
||||||
|
{"git", "annex", "init"},
|
||||||
|
{"git", "annex", "initremote", "MyTestRemote",
|
||||||
|
"type=external", "externaltype=rclone-builtin", "encryption=none",
|
||||||
|
"rcloneremotename=MyRcloneRemote", "rcloneprefix=" + ephemeralRepoDir},
|
||||||
|
{"git", "annex", "testremote", "MyTestRemote"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, args := range cmds {
|
||||||
|
fmt.Printf("+ %v\n", args)
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.Dir = ephemeralRepoDir
|
||||||
|
cmd.Env = []string{
|
||||||
|
"HOME=" + homeDir,
|
||||||
|
"PATH=" + os.Getenv("PATH") + ":" + binDir,
|
||||||
|
}
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
require.NoError(t, cmd.Run())
|
||||||
|
}
|
||||||
|
}
|
@ -1,52 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# End-to-end tests for "rclone gitannex". This script runs the `git-annex
|
|
||||||
# testremote` suite against "rclone gitannex" in an ephemeral git-annex repo.
|
|
||||||
#
|
|
||||||
# Assumptions:
|
|
||||||
#
|
|
||||||
# * This system has an rclone remote configured named "git-annex-builtin-test-remote".
|
|
||||||
#
|
|
||||||
# * If it uses rclone's "local" backend, /tmp/git-annex-builtin-test-remote exists.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
TEST_DIR="$(realpath "$(mktemp -d)")"
|
|
||||||
mkdir "$TEST_DIR/bin"
|
|
||||||
|
|
||||||
function cleanup()
|
|
||||||
{
|
|
||||||
rm -rf "$TEST_DIR"
|
|
||||||
}
|
|
||||||
|
|
||||||
trap cleanup EXIT
|
|
||||||
|
|
||||||
RCLONE_DIR="$(git rev-parse --show-toplevel)"
|
|
||||||
|
|
||||||
rm -rf /tmp/git-annex-builtin-test-remote/*
|
|
||||||
|
|
||||||
set -x
|
|
||||||
|
|
||||||
pushd "$RCLONE_DIR"
|
|
||||||
go build -o "$TEST_DIR/bin" ./
|
|
||||||
|
|
||||||
ln -s "$(realpath "$TEST_DIR/bin/rclone")" "$TEST_DIR/bin/git-annex-remote-rclone-builtin"
|
|
||||||
popd
|
|
||||||
|
|
||||||
pushd "$TEST_DIR"
|
|
||||||
|
|
||||||
git init
|
|
||||||
git annex init
|
|
||||||
|
|
||||||
REMOTE_NAME=git-annex-builtin-test-remote
|
|
||||||
PREFIX=/tmp/git-annex-builtin-test-remote
|
|
||||||
|
|
||||||
PATH="$PATH:$TEST_DIR/bin" git annex initremote $REMOTE_NAME \
|
|
||||||
type=external externaltype=rclone-builtin encryption=none \
|
|
||||||
rcloneremotename=$REMOTE_NAME \
|
|
||||||
rcloneprefix="$PREFIX"
|
|
||||||
|
|
||||||
PATH="$PATH:$(realpath bin)" git annex testremote $REMOTE_NAME
|
|
||||||
|
|
||||||
popd
|
|
||||||
rm -rf "$TEST_DIR"
|
|
Loading…
Reference in New Issue
Block a user