AnyEvent-MCP

 view release on metacpan or  search on metacpan

t/12_vim_startup.t  view on Meta::CPAN

use common::sense;
use Test::More;
use File::Temp ();
use File::Path ();
use AnyEvent::MCP::Config ();
use IPC::Open3 ();
use Symbol ();

my $dir = File::Temp::tempdir (CLEANUP => 1);
File::Path::mkpath (["$dir/home", "$dir/config"], 0, 0700);
local $ENV{HOME} = "$dir/home";
local $ENV{XDG_CONFIG_HOME} = "$dir/config";

sub run_vim {
   my @argv = @_;
   my $error = Symbol::gensym;
   my $pid = IPC::Open3::open3 (my $input, my $output, $error,
      $^X, "-Ilib", "bin/mcp-vim", @argv);
   close $input;
   local $/;
   my $out = <$output> // "";
   my $err = <$error> // "";
   waitpid $pid, 0;
   ($? >> 8, $out, $err)
}

my ($status, $url, $err) = run_vim ("--print-url");
is $status, 0, "print-url exits successfully";
like $url, qr{\Ahttp://127\.0\.0\.1:[0-9]+/[A-Za-z0-9_-]{43}/  \# user global:default \(connect\)\n\z},
   "print-url emits a cookie-bearing URL prefix";
is $err, "", "print-url has no diagnostics on success";

my $file = "$dir/config/anyevent-mcp/global.ini";
ok -f $file && !((stat $file)[2] & 077), "global master secret saved privately";
my $config = AnyEvent::MCP::Config->new (file => $file);
my ($default_port, $cookie);
{
   local $0 = "mcp-vim";
   $default_port = $config->server_port ("default");
   $cookie = $config->user_credentials ("default")->[0][2];
}
like $url, qr{\Ahttp://127\.0\.0\.1:$default_port/},
   "default port is derived from the service name";
# token is derived in the broker program domain above.
like $url, qr{\Q/$cookie/\E  \# user global:default \(connect\)\n\z}, "cookie derives from global master secret";

my ($again_status, $again_url) = run_vim ("--print-url");
is $again_status, 0, "second invocation exits successfully";
is $again_url, $url, "cookie and URL are stable across processes";
($status, $url) = run_vim ("--print-url", "--token", "cli-first", "--token", "cli-second");
is $status, 0, "repeated --token options accepted";
like $url, qr{/cli-first/\n\z}, "first CLI token is advertised";
ok !-e "$dir/home/.xpcse-broker", "startup no longer generates old cookie config";

open my $legacy, ">>", $file or die $!;
print {$legacy} "\n[instance default]\nbind = 127.0.0.1:31749\n";
close $legacy or die $!;
($status, $url, $err) = run_vim ("--print-url");
is $status, 0, "named bind setting accepted";
is $url, "http://127.0.0.1:31749/$cookie/  # user global:default (connect)\n",
   "named bind overrides derived port";

open my $fh, ">>", $file or die $!;
print {$fh} "tokens = explicit-cookie,secondary-token\n";
close $fh or die $!;
($status, $url) = run_vim ("--print-url");
is $status, 0, "explicit configured tokens accepted";
like $url, qr{\Ahttp://[^:/\s]+:31749/explicit-cookie/\n\z},
   "first configured token overrides derived default";

($status, $url) = run_vim ("--print-url", "--bind", "127.0.0.1:41859");
is $status, 0, "bind switch accepted";
is $url, "http://127.0.0.1:41859/explicit-cookie/\n",
   "explicit bind overrides named setting";

($status, $url) = run_vim ("--print-url", "--bind", "[::1]:41859");
is $status, 0, "IPv6 bind accepted";
is $url, "http://[::1]:41859/explicit-cookie/\n",
   "IPv6 URL host is bracketed";

($status, $url) = run_vim ("--print-url", "--bind", "[::]");
is $status, 0, "IPv6 wildcard accepted";
like $url, qr{\Ahttp://[^:/\s]+:31749/explicit-cookie/\n\z},
   "wildcard bind advertises concrete hostname";

($status, undef, $err) = run_vim ("--print-url", "--bind", ":0");
ok $status != 0 && $err =~ /port is not known/,
   "zero port rejected because a printable fixed URL is required";
($status, undef, $err) = run_vim ("--print-url", "--bind", ":65536");
ok $status != 0 && $err =~ /Invalid MCP bind/,
   "out-of-range port rejected";
($status, undef, $err) = run_vim ("--print-url", "--bind", "");
ok $status != 0 && $err =~ /Invalid MCP bind/,
   "empty host rejected";

{
   local $ENV{XDG_CONFIG_HOME} = "/proc/self/mcp-vim-no-persistent-secret-$$";
   ($status, $url, $err) = run_vim ("--print-url");
   ok $status != 0 && !length $url,
      "cannot print a URL backed only by unsaved, process-local entropy";



( run in 0.650 second using v1.01-cache-2.11-cpan-3f962061493 )