#!/bin/bash # # Unit tests for branch.sh script # Run from project root: ./tools/test_branch.sh # # Don't exit on error - we want to run all tests set +e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Test counters TESTS_RUN=0 TESTS_PASSED=0 TESTS_FAILED=0 # Save current branch ORIGINAL_BRANCH=$(git branch --show-current) # Cleanup function cleanup() { # Remove test user cache files rm -f ~/.qtx_branch_last_user 2>/dev/null || true # Return to original branch git checkout "$ORIGINAL_BRANCH" 2>/dev/null || git checkout develop 2>/dev/null || true # Delete test branches git branch 2>/dev/null | grep -E "(testuser|cached_user|user123|typetest|nametest|secureuser|validationtest)" | xargs -r git branch -D 2>/dev/null || true } # Setup trap cleanup EXIT echo "========================================" echo " Branch Script Unit Tests" echo "========================================" echo "" # Test helper function - pass test pass_test() { local test_name="$1" TESTS_RUN=$((TESTS_RUN + 1)) TESTS_PASSED=$((TESTS_PASSED + 1)) echo -e "${GREEN}✓${NC} PASS: $test_name" } # Test helper function - fail test fail_test() { local test_name="$1" local reason="$2" TESTS_RUN=$((TESTS_RUN + 1)) TESTS_FAILED=$((TESTS_FAILED + 1)) echo -e "${RED}✗${NC} FAIL: $test_name${reason:+ - $reason}" } echo "Running tests..." echo "" # ==================== # Test 1: Valid branch creation # ==================== echo "Test Suite 1: Valid Branch Creation" echo "------------------------------------" cat << 'EOF' | timeout 10 ./tools/branch.sh &>/dev/null 1 testuser 123 valid branch EOF if git rev-parse --verify "feature/testuser/SKL-123/valid_branch" &>/dev/null; then pass_test "Create valid feature branch" else fail_test "Create valid feature branch" "Branch not found" fi if [[ "$(git branch --show-current)" == "feature/testuser/SKL-123/valid_branch" ]]; then pass_test "Checkout to created branch" else fail_test "Checkout to created branch" "Not on expected branch" fi git checkout develop &>/dev/null echo "" # ==================== # Test 2: User cache functionality # ==================== echo "Test Suite 2: User Cache Functionality" echo "---------------------------------------" # Create cache file rm -f ~/.qtx_branch_last_user cat << 'EOF' | timeout 10 ./tools/branch.sh &>/dev/null 6 cached_user 456 using cache EOF if [[ -f ~/.qtx_branch_last_user ]]; then pass_test "User cache file created" else fail_test "User cache file created" "File not found" fi # Check permissions PERMS=$(stat -f "%Lp" ~/.qtx_branch_last_user 2>/dev/null || stat -c "%a" ~/.qtx_branch_last_user 2>/dev/null) if [[ "$PERMS" == "600" ]]; then pass_test "User cache has secure permissions (600)" else fail_test "User cache has secure permissions (600)" "Got $PERMS" fi if grep -q "cached_user" ~/.qtx_branch_last_user; then pass_test "User cache contains correct value" else fail_test "User cache contains correct value" fi git checkout develop &>/dev/null echo "" # ==================== # Test 3: Input validation # ==================== echo "Test Suite 3: Input Validation" echo "-------------------------------" # Test invalid username with special characters OUTPUT=$(cat << 'EOF' 2>/dev/null | timeout 5 ./tools/branch.sh 2>&1 || true 1 user@invalid EOF ) if echo "$OUTPUT" | grep -q "Error: user must be alphanumeric"; then pass_test "Reject username with special characters" else fail_test "Reject username with special characters" fi # Test non-numeric issue number OUTPUT=$(cat << 'EOF' 2>/dev/null | timeout 5 ./tools/branch.sh 2>&1 || true 1 validationtest abc123 EOF ) if echo "$OUTPUT" | grep -q "Error: issue number must be numeric"; then pass_test "Reject non-numeric issue number" else fail_test "Reject non-numeric issue number" fi # Test empty summary OUTPUT=$(cat << 'EOF' 2>/dev/null | timeout 5 ./tools/branch.sh 2>&1 || true 1 validationtest 999 EOF ) if echo "$OUTPUT" | grep -q "Error: summary is required"; then pass_test "Reject empty summary" else fail_test "Reject empty summary" fi # Test summary too long (over 100 chars) LONG_SUMMARY="this is a very long summary that exceeds one hundred characters and should be rejected by the validation" OUTPUT=$(cat << EOF 2>/dev/null | timeout 5 ./tools/branch.sh 2>&1 || true 1 validationtest 999 $LONG_SUMMARY EOF ) if echo "$OUTPUT" | grep -q "Error: summary too long"; then pass_test "Reject summary over 100 characters" else fail_test "Reject summary over 100 characters" fi echo "" # ==================== # Test 4: ISSUE_PREFIX extraction # ==================== echo "Test Suite 4: ISSUE_PREFIX Extraction" echo "--------------------------------------" # Backup original Makefile.common cp Makefile.common Makefile.common.backup # Test with different prefix cat > Makefile.common << 'EOF' ISSUE_PREFIX := TEST GOPATH ?= $(shell go env GOPATH) EOF cat << 'EOF' | timeout 10 ./tools/branch.sh &>/dev/null 1 user123 789 different prefix EOF # Restore original mv Makefile.common.backup Makefile.common if git rev-parse --verify "feature/user123/TEST-789/different_prefix" &>/dev/null; then pass_test "Create branch with custom ISSUE_PREFIX" else fail_test "Create branch with custom ISSUE_PREFIX" "Branch not found with TEST prefix" fi git checkout develop &>/dev/null echo "" # ==================== # Test 5: Branch name formatting # ==================== echo "Test Suite 5: Branch Name Formatting" echo "-------------------------------------" # Spaces should become underscores BRANCH_OUTPUT=$(cat << 'EOF' | timeout 10 ./tools/branch.sh 2>&1 2 nametest 111 spaces in summary here EOF ) if echo "$BRANCH_OUTPUT" | grep -q "hotfix/nametest/SKL-111/spaces_in_summary_here"; then pass_test "Spaces converted to underscores in branch name" else fail_test "Spaces converted to underscores in branch name" fi git branch -D "hotfix/nametest/SKL-111/spaces_in_summary_here" &>/dev/null || true git checkout develop &>/dev/null echo "" # ==================== # Test 6: Different branch types # ==================== echo "Test Suite 6: All Branch Types" echo "-------------------------------" # Test feature type cat << 'EOF' | timeout 10 ./tools/branch.sh &>/dev/null 1 typetest 301 test feature EOF if git rev-parse --verify "feature/typetest/SKL-301/test_feature" &>/dev/null; then pass_test "Branch type 'feature' works" git branch -D "feature/typetest/SKL-301/test_feature" &>/dev/null else fail_test "Branch type 'feature' works" fi # Test hotfix type cat << 'EOF' | timeout 10 ./tools/branch.sh &>/dev/null 2 typetest 302 test hotfix EOF if git rev-parse --verify "hotfix/typetest/SKL-302/test_hotfix" &>/dev/null; then pass_test "Branch type 'hotfix' works" git branch -D "hotfix/typetest/SKL-302/test_hotfix" &>/dev/null else fail_test "Branch type 'hotfix' works" fi # Test fix type cat << 'EOF' | timeout 10 ./tools/branch.sh &>/dev/null 6 typetest 306 test fix EOF if git rev-parse --verify "fix/typetest/SKL-306/test_fix" &>/dev/null; then pass_test "Branch type 'fix' works" git branch -D "fix/typetest/SKL-306/test_fix" &>/dev/null else fail_test "Branch type 'fix' works" fi git checkout develop &>/dev/null echo "" # ==================== # Test 7: Symlink attack prevention # ==================== echo "Test Suite 7: Security - Symlink Prevention" echo "--------------------------------------------" # Create a symlink as the user file USER_CACHE=~/.qtx_branch_last_user TEMP_TARGET=$(mktemp) rm -f "$USER_CACHE" ln -s "$TEMP_TARGET" "$USER_CACHE" cat << 'EOF' | timeout 10 ./tools/branch.sh &>/dev/null 1 secureuser 999 security test EOF # Check if symlink was removed and replaced with regular file if [[ -L "$USER_CACHE" ]]; then fail_test "Symlink removed before writing" "Symlink still exists (security risk)" else pass_test "Symlink removed before writing (secure)" fi rm -f "$TEMP_TARGET" git branch -D "feature/secureuser/SKL-999/security_test" &>/dev/null || true git checkout develop &>/dev/null echo "" # ==================== # Summary # ==================== echo "========================================" echo " Test Summary" echo "========================================" echo -e "Total: $TESTS_RUN" echo -e "${GREEN}Passed: $TESTS_PASSED${NC}" if [[ $TESTS_FAILED -gt 0 ]]; then echo -e "${RED}Failed: $TESTS_FAILED${NC}" else echo -e "Failed: $TESTS_FAILED" fi echo "" if [[ $TESTS_FAILED -eq 0 ]]; then echo -e "${GREEN}✓ All tests passed!${NC}" exit 0 else echo -e "${RED}✗ Some tests failed!${NC}" exit 1 fi