summaryrefslogtreecommitdiff
path: root/test/run.sh
blob: db05ede7635995cdb6a3373af691c9ac772861f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/env bash
#
# This script runs a given test case and captures a screenshot. This script
# expects to run in the Docker image so it just captures the full screen rather
# than a specific window.
#
# This script also compares the output to the expected value. The expected
# value is the case file with ".png" appended. If the "--update" flag is
# appended, the test case is updated.

#--------------------------------------------------------------------
# Helpers

function has_func() {
    declare -f -F $1 > /dev/null
    return $?
}

# Colors
export BOLD="\\e[1m"
export RED="\\e[1;31m"
export GREEN="\\e[1;32m"
export YELLOW="\\e[1;33m"
export WHITE="\\e[1;37m"
export RESET="\\e[0;39m"

#--------------------------------------------------------------------
# Flag parsing

ARG_REWRITE=0
ARG_UPDATE=0
while [[ "$#" -gt 0 ]]; do
    case $1 in
        -e|--exec) ARG_EXEC="$2"; shift ;;
        -c|--case) ARG_CASE="$2"; shift ;;
        -o|--output) ARG_OUT="$2"; shift ;;
        -u|--update) ARG_UPDATE=1 ;;
        --rewrite-abs-path) ARG_REWRITE=1 ;;
        *) echo "Unknown parameter passed: $1"; exit 1 ;;
    esac
    shift
done

# Rewrite the path to be valid for us. This regex can be fooled in many ways
# but its good enough for my PC (mitchellh) and CI. Contributors feel free
# to harden it.
if [ "$ARG_REWRITE" -eq 1 ]; then
  ARG_CASE=$(echo $ARG_CASE | sed -e 's/.*cases/\/src\/cases/')
fi

# If we're updating, then just update the file in-place
GOLDEN_OUT="${ARG_CASE}.${ARG_EXEC}.png"
ARG_OUT="${ARG_CASE}.${ARG_EXEC}.actual.png"
if [ "$ARG_UPDATE" -eq 1 ]; then ARG_OUT=$GOLDEN_OUT; fi

bad=0
if [ -z "$ARG_EXEC" ]; then bad=1; fi
if [ -z "$ARG_CASE" ]; then bad=1; fi
if [ -z "$ARG_OUT" ]; then bad=1; fi
if [ $bad -ne 0 ]; then
  echo "Usage: run.sh --exec <terminal> --case <path to case> --output <path to png>"
  exit 1
fi

# Load our test case
# shellcheck disable=SC1090
source ${ARG_CASE}
if ! has_func "test_do"; then
  echo "Test case is invalid."
  exit 1
fi

# NOTE: This is a huge hack right now.
if [ "$ARG_EXEC" = "ghostty" ]; then
  ARG_EXEC="/tmp/ghostty";

  # Copy so we don't read/write race when running in parallel
  cp /src/ghostty ${ARG_EXEC}

  # We build in Nix (maybe). To be sure, we replace the interpreter so
  # it doesn't point to a Nix path. If we don't build in Nix, this should
  # still be safe.
  patchelf --set-interpreter /lib/ld-linux-"$(uname -m)".so.1 ${ARG_EXEC}
fi

#--------------------------------------------------------------------
# Some terminals require XDG be properly setup. We create a new
# set of XDG directories for this.
export XDG_BASE_DIR="/work/xdg"
export XDG_RUNTIME_DIR="${XDG_BASE_DIR}/runtime"
mkdir -p ${XDG_BASE_DIR} ${XDG_RUNTIME_DIR}
chmod 0700 $XDG_RUNTIME_DIR

# Configure i3
cat <<EOF >${XDG_BASE_DIR}/i3.cfg
# i3 config file (v4)

exec ${ARG_EXEC}

bar {
    mode invisible
}
EOF

#--------------------------------------------------------------------

printf "${RESET}${BOLD}[$(basename $ARG_EXEC)]${RESET} $ARG_CASE ... ${RESET}"

# Start up the program under test by launching i3. We use i3 so we can
# more carefully control the window settings, test resizing, etc.
WM_LOG="${XDG_BASE_DIR}/wm.log"
i3 -c ${XDG_BASE_DIR}/i3.cfg >${WM_LOG} 2>&1 &

# Wait for startup
# TODO: we can probably use xdotool or wmctrl or something to detect if any
# windows actually launched and make error handling here better.
sleep 2

# Run our test case (should be defined in test case file)
test_do

# Sleep a second to let it render
sleep 1

# Uncomment this and use run-host.sh to get logs of the terminal emulator
# cat $WM_LOG

import -window root ${ARG_OUT}

DIFF=$(compare -metric AE ${ARG_OUT} ${GOLDEN_OUT} null: 2>&1)
if [ $? -eq 2 ] ; then
  printf "${RED}ERROR${RESET}\n"
  exit 1
else
  if [ $DIFF -gt 0 ]; then
    printf "${RED}Fail (Diff: ${WHITE}${DIFF}${RED})${RESET}\n"
    exit 1
  else
    printf "${GREEN}Pass (Diff: ${WHITE}${DIFF}${GREEN})${RESET}\n"
  fi
fi