#!/bin/bash
# Test D-Bus Communication for apt-ostree
# This script tests the communication between apt-ostree client and daemon

set -e

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Function to print colored output
print_status() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

print_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

print_header() {
    echo -e "${BLUE}[TEST]${NC} $1"
}

# Test counter
TESTS_PASSED=0
TESTS_FAILED=0

# Function to run a test
run_test() {
    local test_name="$1"
    local test_command="$2"
    
    print_header "Running: $test_name"
    echo "Command: $test_command"
    
    if eval "$test_command" > /dev/null 2>&1; then
        print_status "✓ PASSED: $test_name"
        ((TESTS_PASSED++))
    else
        print_error "✗ FAILED: $test_name"
        ((TESTS_FAILED++))
    fi
    echo
}

# Function to run a test with output capture
run_test_with_output() {
    local test_name="$1"
    local test_command="$2"
    
    print_header "Running: $test_name"
    echo "Command: $test_command"
    
    if output=$(eval "$test_command" 2>&1); then
        print_status "✓ PASSED: $test_name"
        echo "Output: $output"
        ((TESTS_PASSED++))
    else
        print_error "✗ FAILED: $test_name"
        echo "Error: $output"
        ((TESTS_FAILED++))
    fi
    echo
}

print_status "Starting D-Bus Communication Tests for apt-ostree"
echo "=================================================="
echo

# Test 1: Check if daemon binary exists
run_test "Daemon binary exists" "test -f /usr/libexec/apt-ostreed"

# Test 2: Check if daemon binary is executable
run_test "Daemon binary is executable" "test -x /usr/libexec/apt-ostreed"

# Test 3: Check if systemd service is loaded
run_test "Systemd service is loaded" "systemctl is-loaded apt-ostreed.service"

# Test 4: Check if systemd service is active
run_test "Systemd service is active" "systemctl is-active apt-ostreed.service"

# Test 5: Check if D-Bus service is registered
run_test "D-Bus service is registered" "gdbus list --system | grep -q org.aptostree.dev"

# Test 6: Test D-Bus introspection
run_test_with_output "D-Bus introspection" "gdbus introspect --system --dest org.aptostree.dev --object-path /org/aptostree/dev"

# Test 7: Test Ping method
run_test_with_output "D-Bus Ping method" "gdbus call --system --dest org.aptostree.dev --object-path /org/aptostree/dev --method org.aptostree.dev.Daemon.Ping"

# Test 8: Test GetStatus method
run_test_with_output "D-Bus GetStatus method" "gdbus call --system --dest org.aptostree.dev --object-path /org/aptostree/dev --method org.aptostree.dev.Daemon.GetStatus"

# Test 9: Test client-daemon communication via apt-ostree
run_test_with_output "Client daemon ping" "apt-ostree daemon-ping"

# Test 10: Test client-daemon status
run_test_with_output "Client daemon status" "apt-ostree daemon-status"

# Test 11: Check D-Bus policy file
run_test "D-Bus policy file exists" "test -f /etc/dbus-1/system.d/org.aptostree.dev.conf"

# Test 12: Check D-Bus service activation file
run_test "D-Bus service activation file exists" "test -f /usr/share/dbus-1/system-services/org.aptostree.dev.service"

# Test 13: Check Polkit policy file
run_test "Polkit policy file exists" "test -f /usr/share/polkit-1/actions/org.aptostree.dev.policy"

# Test 14: Test D-Bus method listing
run_test_with_output "D-Bus method listing" "gdbus introspect --system --dest org.aptostree.dev --object-path /org/aptostree/dev | grep -A 5 'method'"

# Test 15: Test D-Bus property listing
run_test_with_output "D-Bus property listing" "gdbus introspect --system --dest org.aptostree.dev --object-path /org/aptostree/dev | grep -A 5 'property'"

# Test 16: Check daemon logs
run_test_with_output "Daemon logs" "journalctl -u apt-ostreed.service --no-pager -n 5"

# Test 17: Test D-Bus signal monitoring (timeout after 3 seconds)
print_header "Testing D-Bus signal monitoring (3 second timeout)"
timeout 3s gdbus monitor --system --dest org.aptostree.dev || true
echo

# Test 18: Test client fallback (when daemon is not available)
print_header "Testing client fallback behavior"
# Temporarily stop the daemon
systemctl stop apt-ostreed.service 2>/dev/null || true
sleep 1

# Test if client can handle daemon unavailability
if apt-ostree daemon-ping 2>&1 | grep -q "daemon.*unavailable\|connection.*failed"; then
    print_status "✓ PASSED: Client handles daemon unavailability gracefully"
    ((TESTS_PASSED++))
else
    print_warning "⚠ Client behavior with unavailable daemon needs verification"
fi

# Restart the daemon
systemctl start apt-ostreed.service 2>/dev/null || true
sleep 2
echo

# Test 19: Test D-Bus connection with authentication
run_test_with_output "D-Bus connection with authentication" "pkexec gdbus call --system --dest org.aptostree.dev --object-path /org/aptostree/dev --method org.aptostree.dev.Daemon.Ping"

# Test 20: Test D-Bus service activation
print_header "Testing D-Bus service activation"
# Kill the daemon process
pkill -f apt-ostreed || true
sleep 1

# Try to call a D-Bus method (should trigger service activation)
if gdbus call --system --dest org.aptostree.dev --object-path /org/aptostree/dev --method org.aptostree.dev.Daemon.Ping > /dev/null 2>&1; then
    print_status "✓ PASSED: D-Bus service activation works"
    ((TESTS_PASSED++))
else
    print_error "✗ FAILED: D-Bus service activation"
    ((TESTS_FAILED++))
fi
echo

# Summary
echo "=================================================="
print_status "D-Bus Communication Test Summary"
echo "=================================================="
print_status "Tests Passed: $TESTS_PASSED"
if [ $TESTS_FAILED -gt 0 ]; then
    print_error "Tests Failed: $TESTS_FAILED"
else
    print_status "Tests Failed: $TESTS_FAILED"
fi

if [ $TESTS_FAILED -eq 0 ]; then
    print_status "🎉 All D-Bus communication tests passed!"
    exit 0
else
    print_error "❌ Some D-Bus communication tests failed"
    exit 1
fi 