test: refactor integration tests to use daemon commands
Update integration_test.sh to use new daemon management commands instead of manual background processes and PIDs: - Replace `kvs config.yaml &` with `kvs start config.yaml` - Replace `kill $pid` with `kvs stop config.yaml` - Update log file paths to use ~/.kvs/logs/ - Add integration_test/ directory to gitignore All tests now use clean daemon lifecycle management. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -2,6 +2,7 @@
 | 
			
		||||
.kvs/
 | 
			
		||||
data/
 | 
			
		||||
data*/
 | 
			
		||||
integration_test/
 | 
			
		||||
*.yaml
 | 
			
		||||
!config.yaml
 | 
			
		||||
kvs
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,7 @@ cleanup() {
 | 
			
		||||
    log_info "Cleaning up test environment..."
 | 
			
		||||
    pkill -f "$BINARY" 2>/dev/null || true
 | 
			
		||||
    rm -rf "$TEST_DIR" 2>/dev/null || true
 | 
			
		||||
    rm -rf "$HOME/.kvs" 2>/dev/null || true  # Clean up PID and log files from home dir
 | 
			
		||||
    sleep 2  # Allow processes to fully terminate
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -53,7 +54,7 @@ wait_for_service() {
 | 
			
		||||
    local port=$1
 | 
			
		||||
    local timeout=${2:-30}
 | 
			
		||||
    local count=0
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    while [ $count -lt $timeout ]; do
 | 
			
		||||
        if curl -s "http://localhost:$port/health" >/dev/null 2>&1; then
 | 
			
		||||
            return 0
 | 
			
		||||
@@ -64,6 +65,15 @@ wait_for_service() {
 | 
			
		||||
    return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Get log file path for a config file (matches daemon naming convention)
 | 
			
		||||
get_log_file() {
 | 
			
		||||
    local config=$1
 | 
			
		||||
    local abs_path=$(realpath "$config")
 | 
			
		||||
    local basename=$(basename "$config")
 | 
			
		||||
    local dirname=$(basename $(dirname "$abs_path"))
 | 
			
		||||
    echo "$HOME/.kvs/logs/${dirname}_${basename}.log"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Test 1: Build verification
 | 
			
		||||
test_build() {
 | 
			
		||||
    test_start "Binary build verification"
 | 
			
		||||
@@ -82,7 +92,7 @@ test_build() {
 | 
			
		||||
# Test 2: Basic functionality
 | 
			
		||||
test_basic_functionality() {
 | 
			
		||||
    test_start "Basic functionality test"
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    # Create basic config
 | 
			
		||||
    cat > basic.yaml <<EOF
 | 
			
		||||
node_id: "basic-test"
 | 
			
		||||
@@ -94,20 +104,20 @@ log_level: "error"
 | 
			
		||||
allow_anonymous_read: true
 | 
			
		||||
allow_anonymous_write: true
 | 
			
		||||
EOF
 | 
			
		||||
    
 | 
			
		||||
    # Start node
 | 
			
		||||
    $BINARY basic.yaml >/dev/null 2>&1 &
 | 
			
		||||
    local pid=$!
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    # Start node using daemon command
 | 
			
		||||
    $BINARY start basic.yaml >/dev/null 2>&1
 | 
			
		||||
    sleep 2
 | 
			
		||||
 | 
			
		||||
    if wait_for_service 8090; then
 | 
			
		||||
        # Test basic CRUD
 | 
			
		||||
        local put_result=$(curl -s -X PUT http://localhost:8090/kv/test/basic \
 | 
			
		||||
            -H "Content-Type: application/json" \
 | 
			
		||||
            -d '{"message":"hello world"}')
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        local get_result=$(curl -s http://localhost:8090/kv/test/basic)
 | 
			
		||||
        local message=$(echo "$get_result" | jq -r '.data.message' 2>/dev/null) # Adjusted jq path
 | 
			
		||||
        
 | 
			
		||||
        local message=$(echo "$get_result" | jq -r '.data.message' 2>/dev/null)
 | 
			
		||||
 | 
			
		||||
        if [ "$message" = "hello world" ]; then
 | 
			
		||||
            log_success "Basic CRUD operations work"
 | 
			
		||||
        else
 | 
			
		||||
@@ -116,9 +126,9 @@ EOF
 | 
			
		||||
    else
 | 
			
		||||
        log_error "Basic test node failed to start"
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    kill $pid 2>/dev/null || true
 | 
			
		||||
    sleep 2
 | 
			
		||||
 | 
			
		||||
    $BINARY stop basic.yaml >/dev/null 2>&1
 | 
			
		||||
    sleep 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Test 3: Cluster formation
 | 
			
		||||
@@ -160,23 +170,22 @@ allow_anonymous_write: true
 | 
			
		||||
cluster_secret: "$CLUSTER_SECRET"
 | 
			
		||||
EOF
 | 
			
		||||
    
 | 
			
		||||
    # Start nodes
 | 
			
		||||
    $BINARY cluster1.yaml >/dev/null 2>&1 &
 | 
			
		||||
    local pid1=$!
 | 
			
		||||
    
 | 
			
		||||
    # Start nodes using daemon commands
 | 
			
		||||
    $BINARY start cluster1.yaml >/dev/null 2>&1
 | 
			
		||||
    sleep 2
 | 
			
		||||
 | 
			
		||||
    if ! wait_for_service 8101; then
 | 
			
		||||
        log_error "Cluster node 1 failed to start"
 | 
			
		||||
        kill $pid1 2>/dev/null || true
 | 
			
		||||
        $BINARY stop cluster1.yaml >/dev/null 2>&1
 | 
			
		||||
        return 1
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    sleep 2 # Give node 1 a moment to fully initialize
 | 
			
		||||
    $BINARY cluster2.yaml >/dev/null 2>&1 &
 | 
			
		||||
    local pid2=$!
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    $BINARY start cluster2.yaml >/dev/null 2>&1
 | 
			
		||||
    sleep 2
 | 
			
		||||
 | 
			
		||||
    if ! wait_for_service 8102; then
 | 
			
		||||
        log_error "Cluster node 2 failed to start"
 | 
			
		||||
        kill $pid1 $pid2 2>/dev/null || true
 | 
			
		||||
        $BINARY stop cluster1.yaml cluster2.yaml >/dev/null 2>&1
 | 
			
		||||
        return 1
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
@@ -224,9 +233,9 @@ EOF
 | 
			
		||||
    else
 | 
			
		||||
        log_error "Cluster formation failed (N1 members: $node1_members, N2 members: $node2_members)"
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    kill $pid1 $pid2 2>/dev/null || true
 | 
			
		||||
    sleep 2
 | 
			
		||||
 | 
			
		||||
    $BINARY stop cluster1.yaml cluster2.yaml >/dev/null 2>&1
 | 
			
		||||
    sleep 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Test 4: Conflict resolution (Merkle Tree based)
 | 
			
		||||
@@ -274,16 +283,15 @@ allow_anonymous_write: true
 | 
			
		||||
cluster_secret: "$CLUSTER_SECRET"
 | 
			
		||||
EOF
 | 
			
		||||
        
 | 
			
		||||
        # Start nodes
 | 
			
		||||
        # Start nodes using daemon commands
 | 
			
		||||
        # Node 1 started first, making it "older" for tie-breaker if timestamps are equal
 | 
			
		||||
        "$BINARY" conflict1.yaml >conflict1.log 2>&1 &
 | 
			
		||||
        local pid1=$!
 | 
			
		||||
        
 | 
			
		||||
        $BINARY start conflict1.yaml >/dev/null 2>&1
 | 
			
		||||
        sleep 2
 | 
			
		||||
 | 
			
		||||
        if wait_for_service 8111; then
 | 
			
		||||
            $BINARY start conflict2.yaml >/dev/null 2>&1
 | 
			
		||||
            sleep 2
 | 
			
		||||
            $BINARY conflict2.yaml >conflict2.log 2>&1 &
 | 
			
		||||
            local pid2=$!
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            if wait_for_service 8112; then
 | 
			
		||||
                # Get initial data (full StoredValue)
 | 
			
		||||
                local node1_initial_full=$(curl -s http://localhost:8111/kv/test/conflict/data)
 | 
			
		||||
@@ -344,8 +352,10 @@ EOF
 | 
			
		||||
                        log_error "Resolved data has inconsistent UUID/Timestamp: N1_UUID=$node1_final_uuid, N1_TS=$node1_final_timestamp, N2_UUID=$node2_final_uuid, N2_TS=$node2_final_timestamp"
 | 
			
		||||
                    fi
 | 
			
		||||
 | 
			
		||||
                    # Optionally, check logs for conflict resolution messages
 | 
			
		||||
                    if grep -q "Conflict resolved" conflict1.log conflict2.log 2>/dev/null; then
 | 
			
		||||
                    # Check logs for conflict resolution messages
 | 
			
		||||
                    local log1=$(get_log_file conflict1.yaml)
 | 
			
		||||
                    local log2=$(get_log_file conflict2.yaml)
 | 
			
		||||
                    if grep -q "Conflict resolved" "$log1" "$log2" 2>/dev/null; then
 | 
			
		||||
                        log_success "Conflict resolution messages found in logs"
 | 
			
		||||
                    else
 | 
			
		||||
                        log_error "No 'Conflict resolved' messages found in logs, but data converged."
 | 
			
		||||
@@ -357,14 +367,14 @@ EOF
 | 
			
		||||
            else
 | 
			
		||||
                log_error "Conflict node 2 failed to start"
 | 
			
		||||
            fi
 | 
			
		||||
            
 | 
			
		||||
            kill $pid2 2>/dev/null || true
 | 
			
		||||
 | 
			
		||||
            $BINARY stop conflict2.yaml >/dev/null 2>&1
 | 
			
		||||
        else
 | 
			
		||||
            log_error "Conflict node 1 failed to start"
 | 
			
		||||
        fi
 | 
			
		||||
        
 | 
			
		||||
        kill $pid1 2>/dev/null || true
 | 
			
		||||
        sleep 2
 | 
			
		||||
 | 
			
		||||
        $BINARY stop conflict1.yaml >/dev/null 2>&1
 | 
			
		||||
        sleep 1
 | 
			
		||||
    else
 | 
			
		||||
        cd "$TEST_DIR"
 | 
			
		||||
        log_error "Failed to create conflict test data. Ensure test_conflict.go is correct."
 | 
			
		||||
@@ -388,22 +398,21 @@ allow_anonymous_read: false
 | 
			
		||||
allow_anonymous_write: false
 | 
			
		||||
EOF
 | 
			
		||||
    
 | 
			
		||||
    # Start node
 | 
			
		||||
    $BINARY auth_test.yaml >auth_test.log 2>&1 &
 | 
			
		||||
    local pid=$!
 | 
			
		||||
    
 | 
			
		||||
    # Start node using daemon command
 | 
			
		||||
    $BINARY start auth_test.yaml >/dev/null 2>&1
 | 
			
		||||
    sleep 3  # Allow daemon to start and root account creation
 | 
			
		||||
 | 
			
		||||
    if wait_for_service 8095; then
 | 
			
		||||
        sleep 2  # Allow root account creation
 | 
			
		||||
        
 | 
			
		||||
        # Extract the token from logs
 | 
			
		||||
        local token=$(grep "Token:" auth_test.log | sed 's/.*Token: //' | tr -d '\n\r')
 | 
			
		||||
        
 | 
			
		||||
        local log_file=$(get_log_file auth_test.yaml)
 | 
			
		||||
        local token=$(grep "Token:" "$log_file" | sed 's/.*Token: //' | tr -d '\n\r')
 | 
			
		||||
 | 
			
		||||
        if [ -z "$token" ]; then
 | 
			
		||||
            log_error "Failed to extract authentication token from logs"
 | 
			
		||||
            kill $pid 2>/dev/null || true
 | 
			
		||||
            $BINARY stop auth_test.yaml >/dev/null 2>&1
 | 
			
		||||
            return
 | 
			
		||||
        fi
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        # Test 1: Admin endpoints should fail without authentication
 | 
			
		||||
        local no_auth_response=$(curl -s -X POST http://localhost:8095/api/users -H "Content-Type: application/json" -d '{"nickname":"test","password":"test"}')
 | 
			
		||||
        if echo "$no_auth_response" | grep -q "Unauthorized"; then
 | 
			
		||||
@@ -411,7 +420,7 @@ EOF
 | 
			
		||||
        else
 | 
			
		||||
            log_error "Admin endpoints should reject unauthenticated requests, got: $no_auth_response"
 | 
			
		||||
        fi
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        # Test 2: Admin endpoints should work with valid authentication
 | 
			
		||||
        local auth_response=$(curl -s -X POST http://localhost:8095/api/users -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d '{"nickname":"authtest","password":"authtest"}')
 | 
			
		||||
        if echo "$auth_response" | grep -q "uuid"; then
 | 
			
		||||
@@ -419,7 +428,7 @@ EOF
 | 
			
		||||
        else
 | 
			
		||||
            log_error "Admin endpoints should work with authentication, got: $auth_response"
 | 
			
		||||
        fi
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        # Test 3: KV endpoints should require auth when anonymous access is disabled
 | 
			
		||||
        local kv_no_auth=$(curl -s -X PUT http://localhost:8095/kv/test/auth -H "Content-Type: application/json" -d '{"test":"auth"}')
 | 
			
		||||
        if echo "$kv_no_auth" | grep -q "Unauthorized"; then
 | 
			
		||||
@@ -427,7 +436,7 @@ EOF
 | 
			
		||||
        else
 | 
			
		||||
            log_error "KV endpoints should require auth when anonymous access disabled, got: $kv_no_auth"
 | 
			
		||||
        fi
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        # Test 4: KV endpoints should work with valid authentication
 | 
			
		||||
        local kv_auth=$(curl -s -X PUT http://localhost:8095/kv/test/auth -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d '{"test":"auth"}')
 | 
			
		||||
        if echo "$kv_auth" | grep -q "uuid\|timestamp" || [ -z "$kv_auth" ]; then
 | 
			
		||||
@@ -435,12 +444,12 @@ EOF
 | 
			
		||||
        else
 | 
			
		||||
            log_error "KV endpoints should work with authentication, got: $kv_auth"
 | 
			
		||||
        fi
 | 
			
		||||
        
 | 
			
		||||
        kill $pid 2>/dev/null || true
 | 
			
		||||
        sleep 2
 | 
			
		||||
 | 
			
		||||
        $BINARY stop auth_test.yaml >/dev/null 2>&1
 | 
			
		||||
        sleep 1
 | 
			
		||||
    else
 | 
			
		||||
        log_error "Auth test node failed to start"
 | 
			
		||||
        kill $pid 2>/dev/null || true
 | 
			
		||||
        $BINARY stop auth_test.yaml >/dev/null 2>&1
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -461,19 +470,18 @@ allow_anonymous_read: false
 | 
			
		||||
allow_anonymous_write: false
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
    # Start node
 | 
			
		||||
    $BINARY metadata_test.yaml >metadata_test.log 2>&1 &
 | 
			
		||||
    local pid=$!
 | 
			
		||||
    # Start node using daemon command
 | 
			
		||||
    $BINARY start metadata_test.yaml >/dev/null 2>&1
 | 
			
		||||
    sleep 3  # Allow daemon to start and root account creation
 | 
			
		||||
 | 
			
		||||
    if wait_for_service 8096; then
 | 
			
		||||
        sleep 2  # Allow root account creation
 | 
			
		||||
 | 
			
		||||
        # Extract the token from logs
 | 
			
		||||
        local token=$(grep "Token:" metadata_test.log | sed 's/.*Token: //' | tr -d '\n\r')
 | 
			
		||||
        local log_file=$(get_log_file metadata_test.yaml)
 | 
			
		||||
        local token=$(grep "Token:" "$log_file" | sed 's/.*Token: //' | tr -d '\n\r')
 | 
			
		||||
 | 
			
		||||
        if [ -z "$token" ]; then
 | 
			
		||||
            log_error "Failed to extract authentication token from logs"
 | 
			
		||||
            kill $pid 2>/dev/null || true
 | 
			
		||||
            $BINARY stop metadata_test.yaml >/dev/null 2>&1
 | 
			
		||||
            return
 | 
			
		||||
        fi
 | 
			
		||||
 | 
			
		||||
@@ -525,14 +533,78 @@ EOF
 | 
			
		||||
            log_error "Metadata endpoints should require authentication, got code: $no_auth_code"
 | 
			
		||||
        fi
 | 
			
		||||
 | 
			
		||||
        kill $pid 2>/dev/null || true
 | 
			
		||||
        sleep 2
 | 
			
		||||
        $BINARY stop metadata_test.yaml >/dev/null 2>&1
 | 
			
		||||
        sleep 1
 | 
			
		||||
    else
 | 
			
		||||
        log_error "Metadata test node failed to start"
 | 
			
		||||
        kill $pid 2>/dev/null || true
 | 
			
		||||
        $BINARY stop metadata_test.yaml >/dev/null 2>&1
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Test 7: Daemon commands (start, stop, status, restart)
 | 
			
		||||
test_daemon_commands() {
 | 
			
		||||
    test_start "Daemon command tests (start, stop, status, restart)"
 | 
			
		||||
 | 
			
		||||
    # Create daemon test config
 | 
			
		||||
    cat > daemon_test.yaml <<EOF
 | 
			
		||||
node_id: "daemon-test"
 | 
			
		||||
bind_address: "127.0.0.1"
 | 
			
		||||
port: 8097
 | 
			
		||||
data_dir: "./daemon_test_data"
 | 
			
		||||
seed_nodes: []
 | 
			
		||||
log_level: "error"
 | 
			
		||||
allow_anonymous_read: true
 | 
			
		||||
allow_anonymous_write: true
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
    # Test 1: Start command
 | 
			
		||||
    $BINARY start daemon_test.yaml >/dev/null 2>&1
 | 
			
		||||
    sleep 3  # Allow daemon to start
 | 
			
		||||
 | 
			
		||||
    if wait_for_service 8097 5; then
 | 
			
		||||
        log_success "Daemon 'start' command works"
 | 
			
		||||
 | 
			
		||||
        # Test 2: Status command shows running
 | 
			
		||||
        local status_output=$($BINARY status daemon_test.yaml 2>&1)
 | 
			
		||||
        if echo "$status_output" | grep -q "RUNNING"; then
 | 
			
		||||
            log_success "Daemon 'status' command shows RUNNING"
 | 
			
		||||
        else
 | 
			
		||||
            log_error "Daemon 'status' should show RUNNING, got: $status_output"
 | 
			
		||||
        fi
 | 
			
		||||
 | 
			
		||||
        # Test 3: Stop command
 | 
			
		||||
        $BINARY stop daemon_test.yaml >/dev/null 2>&1
 | 
			
		||||
        sleep 2
 | 
			
		||||
 | 
			
		||||
        # Check that service is actually stopped
 | 
			
		||||
        if ! curl -s "http://localhost:8097/health" >/dev/null 2>&1; then
 | 
			
		||||
            log_success "Daemon 'stop' command works"
 | 
			
		||||
        else
 | 
			
		||||
            log_error "Daemon should be stopped but is still responding"
 | 
			
		||||
        fi
 | 
			
		||||
 | 
			
		||||
        # Test 4: Restart command
 | 
			
		||||
        $BINARY restart daemon_test.yaml >/dev/null 2>&1
 | 
			
		||||
        sleep 3
 | 
			
		||||
 | 
			
		||||
        if wait_for_service 8097 5; then
 | 
			
		||||
            log_success "Daemon 'restart' command works"
 | 
			
		||||
 | 
			
		||||
            # Clean up
 | 
			
		||||
            $BINARY stop daemon_test.yaml >/dev/null 2>&1
 | 
			
		||||
            sleep 1
 | 
			
		||||
        else
 | 
			
		||||
            log_error "Daemon 'restart' failed to start service"
 | 
			
		||||
        fi
 | 
			
		||||
    else
 | 
			
		||||
        log_error "Daemon 'start' command failed"
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    # Ensure cleanup
 | 
			
		||||
    pkill -f "daemon_test.yaml" 2>/dev/null || true
 | 
			
		||||
    sleep 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Main test execution
 | 
			
		||||
main() {
 | 
			
		||||
    echo "=================================================="
 | 
			
		||||
@@ -552,6 +624,7 @@ main() {
 | 
			
		||||
    test_conflict_resolution
 | 
			
		||||
    test_authentication_middleware
 | 
			
		||||
    test_metadata_management
 | 
			
		||||
    test_daemon_commands
 | 
			
		||||
 | 
			
		||||
    # Results
 | 
			
		||||
    echo "=================================================="
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user