\set ECHO none
\pset format unaligned
SET search_path TO provsql_test, provsql;

-- Regression: a long-running / hanging external compiler must be
-- interruptible by statement_timeout (and pg_cancel_backend).  ProvSQL
-- runs external tools in their own process group and SIGKILLs that group
-- on a pending cancel, so a tool that ignores SIGINT or forks a worker
-- into another process group (as KCBox/Panini does) is still stopped;
-- before that fix such a tool ran to completion and the timeout was
-- silently ignored.
--
-- We plant a fake "d4" that just sleeps and point
-- provsql.tool_search_path at it, so the compile reliably hangs and the
-- 2s statement_timeout always fires -- a deterministic cancel,
-- independent of machine speed and of whether a real d4 is installed.
--
-- Portability: the fake tool lives under /tmp and is chmod 755 so the
-- backend (possibly a separate `postgres` user) can exec it.  On a
-- runner where /tmp is mounted noexec (some WSL setups), exec fails
-- before the tool runs, so the cancellation path cannot be exercised;
-- we probe for that and skip (matching the expected_1 output).

\! rm -rf /tmp/provsql_extcancel && mkdir -p /tmp/provsql_extcancel && printf '#!/bin/sh\ncase "$1" in --provsql-probe) exit 0 ;; *) exec sleep 30 ;; esac\n' > /tmp/provsql_extcancel/d4 && chmod 755 /tmp/provsql_extcancel /tmp/provsql_extcancel/d4

-- Can the backend actually execute the fake tool here?  (Runs it as the
-- same OS user the backend uses; fails on a noexec /tmp.)
\set CANEXEC `/tmp/provsql_extcancel/d4 --provsql-probe >/dev/null 2>&1 && echo true || echo false`

\if :CANEXEC
CREATE TABLE extc (x int);
INSERT INTO extc VALUES (1), (2), (3), (4);
SELECT add_provenance('extc');
DO $$ BEGIN PERFORM set_prob(provenance(), 0.5) FROM extc; END $$;

SET provsql.tool_search_path = '/tmp/provsql_extcancel';
SET statement_timeout = '2s';

-- The self-join shares each extc(x) leaf across the OR over the other
-- rows, so the per-group circuit is not read-once and 'compilation'
-- genuinely invokes the (fake, hanging) d4.
DO $$
DECLARE st text;
BEGIN
  BEGIN
    PERFORM probability_evaluate(provenance(), 'compilation', 'd4')
      FROM (SELECT a.x FROM extc a, extc b WHERE a.x <> b.x GROUP BY a.x) q;
  EXCEPTION
    WHEN query_canceled THEN
      RAISE NOTICE 'hanging external tool interrupted by statement_timeout';
      RETURN;
    WHEN OTHERS THEN
      GET STACKED DIAGNOSTICS st = RETURNED_SQLSTATE;
      RAISE EXCEPTION 'expected query_canceled, got SQLSTATE %', st;
  END;
  RAISE EXCEPTION 'expected the hanging external tool to be cancelled, but the query completed';
END $$;

RESET statement_timeout;
RESET provsql.tool_search_path;
SELECT remove_provenance('extc');
DROP TABLE extc;
\else
\echo 'SKIPPING external_tool_timeout: fake compiler not executable here (noexec /tmp?)'
\endif

\! rm -rf /tmp/provsql_extcancel
