345 lines
9.1 KiB
Bash
Executable File
345 lines
9.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# Don't exit on first error - we want to run all tests and report results
|
|
set +e
|
|
|
|
# Onyx Milestone 2 Integration Test
|
|
# This script tests all core functionality of transparent versioning and save/undo commands
|
|
|
|
# Color codes for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Test counters
|
|
TESTS_PASSED=0
|
|
TESTS_FAILED=0
|
|
TESTS_TOTAL=0
|
|
|
|
# Logging functions
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[PASS]${NC} $1"
|
|
((TESTS_PASSED++))
|
|
((TESTS_TOTAL++))
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[FAIL]${NC} $1"
|
|
((TESTS_FAILED++))
|
|
((TESTS_TOTAL++))
|
|
}
|
|
|
|
log_section() {
|
|
echo ""
|
|
echo -e "${YELLOW}=====================================${NC}"
|
|
echo -e "${YELLOW}$1${NC}"
|
|
echo -e "${YELLOW}=====================================${NC}"
|
|
}
|
|
|
|
# Assertion functions
|
|
assert_file_exists() {
|
|
if [ -f "$1" ]; then
|
|
log_success "File exists: $1"
|
|
else
|
|
log_error "File does not exist: $1"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
assert_dir_exists() {
|
|
if [ -d "$1" ]; then
|
|
log_success "Directory exists: $1"
|
|
else
|
|
log_error "Directory does not exist: $1"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
assert_file_contains() {
|
|
if grep -q "$2" "$1" 2>/dev/null; then
|
|
log_success "File $1 contains '$2'"
|
|
else
|
|
log_error "File $1 does not contain '$2'"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
assert_command_success() {
|
|
if eval "$1" >/dev/null 2>&1; then
|
|
log_success "Command succeeded: $1"
|
|
else
|
|
log_error "Command failed: $1"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
assert_ref_exists() {
|
|
if git show-ref "$1" >/dev/null 2>&1; then
|
|
log_success "Git ref exists: $1"
|
|
else
|
|
log_error "Git ref does not exist: $1"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
assert_ref_not_exists() {
|
|
if ! git show-ref "$1" >/dev/null 2>&1; then
|
|
log_success "Git ref does not exist (as expected): $1"
|
|
else
|
|
log_error "Git ref exists (should be deleted): $1"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Get the absolute path to onx and onxd binaries
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
ONX_BIN="$PROJECT_ROOT/bin/onx"
|
|
ONXD_BIN="$PROJECT_ROOT/bin/onxd"
|
|
|
|
# Verify binaries exist
|
|
if [ ! -f "$ONX_BIN" ]; then
|
|
echo -e "${RED}Error: onx binary not found at $ONX_BIN${NC}"
|
|
echo "Please run 'make build' first"
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f "$ONXD_BIN" ]; then
|
|
echo -e "${RED}Error: onxd binary not found at $ONXD_BIN${NC}"
|
|
echo "Please run 'make build' first"
|
|
exit 1
|
|
fi
|
|
|
|
# Create test directory in /tmp
|
|
TIMESTAMP=$(date +%s)
|
|
TEST_DIR="/tmp/onyx-repo-test-$TIMESTAMP"
|
|
|
|
log_section "Setting up test environment"
|
|
log_info "Test directory: $TEST_DIR"
|
|
log_info "Onyx binary: $ONX_BIN"
|
|
log_info "Daemon binary: $ONXD_BIN"
|
|
|
|
# Create test directory
|
|
mkdir -p "$TEST_DIR"
|
|
cd "$TEST_DIR"
|
|
|
|
# Cleanup function
|
|
cleanup() {
|
|
log_section "Cleaning up"
|
|
cd /tmp
|
|
|
|
# Stop daemon if running
|
|
if [ -f "$TEST_DIR/.onx/daemon.pid" ]; then
|
|
log_info "Stopping daemon..."
|
|
"$ONX_BIN" daemon stop 2>/dev/null || true
|
|
fi
|
|
|
|
# Remove test directory
|
|
if [ -d "$TEST_DIR" ]; then
|
|
log_info "Removing test directory: $TEST_DIR"
|
|
rm -rf "$TEST_DIR"
|
|
fi
|
|
}
|
|
|
|
# Set trap for cleanup
|
|
trap cleanup EXIT
|
|
|
|
# ============================================
|
|
# Test 1: Repository Initialization
|
|
# ============================================
|
|
log_section "Test 1: Repository Initialization"
|
|
|
|
log_info "Initializing Onyx repository..."
|
|
"$ONX_BIN" init
|
|
|
|
assert_dir_exists ".git"
|
|
assert_dir_exists ".onx"
|
|
assert_file_exists ".onx/oplog"
|
|
assert_file_exists ".onx/workstreams.json"
|
|
assert_file_exists ".gitignore"
|
|
assert_file_contains ".onx/workstreams.json" '{"workstreams":{}}'
|
|
|
|
# ============================================
|
|
# Test 2: Daemon Startup
|
|
# ============================================
|
|
log_section "Test 2: Daemon Startup"
|
|
|
|
log_info "Starting daemon..."
|
|
"$ONX_BIN" daemon start
|
|
|
|
sleep 1
|
|
|
|
assert_file_exists ".onx/daemon.pid"
|
|
assert_command_success "$ONX_BIN daemon status | grep -q 'is running'"
|
|
|
|
PID=$(cat .onx/daemon.pid)
|
|
log_info "Daemon running with PID: $PID"
|
|
|
|
# ============================================
|
|
# Test 3: Automatic Snapshot Creation
|
|
# ============================================
|
|
log_section "Test 3: Automatic Snapshot Creation"
|
|
|
|
log_info "Creating test file..."
|
|
echo 'print("hello world")' > main.py
|
|
|
|
log_info "Waiting for automatic snapshot (3 seconds)..."
|
|
sleep 3
|
|
|
|
assert_file_exists ".onx/workspace"
|
|
assert_file_contains ".onx/workspace" "current_commit_sha"
|
|
assert_ref_exists "refs/onyx/workspaces/current"
|
|
|
|
SNAPSHOT_SHA=$(git show-ref refs/onyx/workspaces/current | awk '{print $1}')
|
|
log_info "Snapshot created: $SNAPSHOT_SHA"
|
|
|
|
# ============================================
|
|
# Test 4: Save Command (requires workstream)
|
|
# ============================================
|
|
log_section "Test 4: Save Command"
|
|
|
|
# First, we need to create an initial Git commit for the base branch
|
|
log_info "Creating initial Git commit..."
|
|
git config user.email "test@example.com"
|
|
git config user.name "Test User"
|
|
git add main.py
|
|
git commit -m "Initial commit" >/dev/null 2>&1
|
|
|
|
log_info "Creating workstream using onx new..."
|
|
"$ONX_BIN" new test-feature
|
|
|
|
log_info "Saving first commit..."
|
|
"$ONX_BIN" save -m "Add hello world program"
|
|
|
|
assert_file_contains ".onx/workstreams.json" "Add hello world program"
|
|
assert_ref_exists "refs/onyx/workstreams/test-feature/commit-1"
|
|
|
|
COMMIT1_SHA=$(git show-ref refs/onyx/workstreams/test-feature/commit-1 | awk '{print $1}')
|
|
log_info "First commit created: $COMMIT1_SHA"
|
|
|
|
# ============================================
|
|
# Test 5: Second Save (test commit chain)
|
|
# ============================================
|
|
log_section "Test 5: Second Save and Commit Chain"
|
|
|
|
log_info "Modifying file..."
|
|
echo 'print("goodbye")' >> main.py
|
|
|
|
log_info "Waiting for automatic snapshot..."
|
|
sleep 3
|
|
|
|
log_info "Saving second commit..."
|
|
"$ONX_BIN" save -m "Add goodbye message"
|
|
|
|
assert_file_contains ".onx/workstreams.json" "Add goodbye message"
|
|
assert_ref_exists "refs/onyx/workstreams/test-feature/commit-2"
|
|
|
|
# Verify parent-child relationship in workstreams.json
|
|
if grep -q "parent_sha" .onx/workstreams.json; then
|
|
log_success "Parent-child relationship established in commits"
|
|
((TESTS_PASSED++))
|
|
((TESTS_TOTAL++))
|
|
else
|
|
log_error "No parent_sha found in workstreams.json"
|
|
((TESTS_FAILED++))
|
|
((TESTS_TOTAL++))
|
|
fi
|
|
|
|
COMMIT2_SHA=$(git show-ref refs/onyx/workstreams/test-feature/commit-2 | awk '{print $1}')
|
|
log_info "Second commit created: $COMMIT2_SHA"
|
|
|
|
# ============================================
|
|
# Test 6: Undo Command
|
|
# ============================================
|
|
log_section "Test 6: Undo Command"
|
|
|
|
log_info "Checking state before undo..."
|
|
log_info "File content: $(cat main.py | wc -l) lines"
|
|
log_info "Commits in workstream: $(grep -o "commit-" .onx/workstreams.json | wc -l)"
|
|
|
|
log_info "Executing undo..."
|
|
"$ONX_BIN" undo
|
|
|
|
# Verify commit-2 ref was removed (Git state reverted)
|
|
# Note: workstreams.json may still have the entry, undo only reverts Git state
|
|
log_info "Verifying undo operation..."
|
|
|
|
# Check that oplog has the undo entry
|
|
assert_file_contains ".onx/oplog" "undo"
|
|
|
|
# Verify oplog has state_before (the fix we implemented)
|
|
if xxd .onx/oplog | grep -q "state_before"; then
|
|
# Check for non-null state_before
|
|
if xxd .onx/oplog | grep -A 5 "state_before" | grep -v "state_before\":null" | grep -q "state_before"; then
|
|
log_success "Oplog contains non-null state_before (undo fix working)"
|
|
((TESTS_PASSED++))
|
|
((TESTS_TOTAL++))
|
|
else
|
|
log_error "Oplog has null state_before"
|
|
((TESTS_FAILED++))
|
|
((TESTS_TOTAL++))
|
|
fi
|
|
else
|
|
log_error "Oplog missing state_before"
|
|
((TESTS_FAILED++))
|
|
((TESTS_TOTAL++))
|
|
fi
|
|
|
|
# ============================================
|
|
# Test 7: Daemon Stop
|
|
# ============================================
|
|
log_section "Test 7: Daemon Cleanup"
|
|
|
|
log_info "Stopping daemon..."
|
|
"$ONX_BIN" daemon stop
|
|
|
|
sleep 1
|
|
|
|
if [ -f ".onx/daemon.pid" ]; then
|
|
log_error "PID file still exists after daemon stop"
|
|
((TESTS_FAILED++))
|
|
((TESTS_TOTAL++))
|
|
else
|
|
log_success "PID file removed after daemon stop"
|
|
((TESTS_PASSED++))
|
|
((TESTS_TOTAL++))
|
|
fi
|
|
|
|
if "$ONX_BIN" daemon status 2>&1 | grep -q "not running"; then
|
|
log_success "Daemon status shows not running"
|
|
((TESTS_PASSED++))
|
|
((TESTS_TOTAL++))
|
|
else
|
|
log_error "Daemon status does not show not running"
|
|
((TESTS_FAILED++))
|
|
((TESTS_TOTAL++))
|
|
fi
|
|
|
|
# ============================================
|
|
# Final Report
|
|
# ============================================
|
|
log_section "Integration Test Results"
|
|
|
|
echo ""
|
|
echo -e "${BLUE}Total Tests:${NC} $TESTS_TOTAL"
|
|
echo -e "${GREEN}Passed:${NC} $TESTS_PASSED"
|
|
echo -e "${RED}Failed:${NC} $TESTS_FAILED"
|
|
echo ""
|
|
|
|
if [ $TESTS_FAILED -eq 0 ]; then
|
|
echo -e "${GREEN}========================================${NC}"
|
|
echo -e "${GREEN} ALL TESTS PASSED! ✓${NC}"
|
|
echo -e "${GREEN}========================================${NC}"
|
|
exit 0
|
|
else
|
|
echo -e "${RED}========================================${NC}"
|
|
echo -e "${RED} SOME TESTS FAILED! ✗${NC}"
|
|
echo -e "${RED}========================================${NC}"
|
|
exit 1
|
|
fi
|