Notcurses-Native.git | xt/ | 15-context-exhaustive.rakutest edit


use Test;
use lib 'lib';
use lib 't/lib';
use TestHelper;
use NativeCall;
use Notcurses::Native;
use Notcurses::Native::Types;
use Notcurses::Native::Context;
use Notcurses::Native::Plane;

plan 13;


my $opts = NotcursesOptions.new(
	:loglevel(NCLOGLEVEL_SILENT),
	:flags(NCOPTION_SUPPRESS_BANNERS +| NCOPTION_NO_ALTERNATE_SCREEN +| NCOPTION_INHIBIT_SETLOCALE),
);
my ($nc, $) = test-init-nc($opts);
unless $nc.defined {
	skip 'No terminal available', 13;
	exit 0;
}
LEAVE { notcurses_stop($nc) if $nc.defined }
my $std = notcurses_stdplane($nc);

subtest 'ncstrwidth on ASCII string' => {
	plan 3;

	my int32 $validbytes = 0;
	my int32 $validwidth = 0;
	my $rc = ncstrwidth("Hello", $validbytes, $validwidth);

	is $rc, 5, 'ncstrwidth("Hello") returns 5 columns';
	is $validbytes, 5, '"Hello" is 5 valid bytes';
	is $validwidth, 5, '"Hello" is 5 valid columns wide';
};

subtest 'ncstrwidth on empty string' => {
	plan 3;

	my int32 $validbytes = 0;
	my int32 $validwidth = 0;
	my $rc = ncstrwidth("", $validbytes, $validwidth);

	is $rc, 0, 'ncstrwidth("") returns 0 columns';
	is $validbytes, 0, 'empty string is 0 valid bytes';
	is $validwidth, 0, 'empty string is 0 valid columns wide';
};

subtest 'Lex blitter roundtrip' => {
	plan 4;

	my int32 $blitter = -1;
	my $rc = notcurses_lex_blitter("default", $blitter);
	is $rc, 0, 'lex_blitter("default") returns 0';
	is $blitter, 0, 'lex_blitter("default") sets blitter to NCBLIT_DEFAULT (0)';

	my $str = notcurses_str_blitter(0);
	ok $str.defined, 'str_blitter(0) returns a defined string';
	is $str, 'default', 'str_blitter(0) returns "default"';
};

subtest 'Lex scalemode roundtrip' => {
	plan 4;

	my int32 $scale = -1;
	my $rc = notcurses_lex_scalemode("none", $scale);
	is $rc, 0, 'lex_scalemode("none") returns 0';
	is $scale, 0, 'lex_scalemode("none") sets scale to NCSCALE_NONE (0)';

	my $str = notcurses_str_scalemode(0);
	ok $str.defined, 'str_scalemode(0) returns a defined string';
	is $str, 'none', 'str_scalemode(0) returns "none"';
};

subtest 'Alignment calculations' => {
	plan 4;

	my $center = notcurses_align(80, NCALIGN_CENTER, 10);
	is $center, 35, 'CENTER: 10 in 80 => offset 35';

	my $right = notcurses_align(80, NCALIGN_RIGHT, 10);
	is $right, 70, 'RIGHT: 10 in 80 => offset 70';

	my $left = notcurses_align(80, NCALIGN_LEFT, 10);
	is $left, 0, 'LEFT: 10 in 80 => offset 0';

	# Edge case: content fills entire width
	my $full = notcurses_align(80, NCALIGN_CENTER, 80);
	is $full, 0, 'CENTER: 80 in 80 => offset 0';
};

subtest 'notcurses_at_yx reads back rendered content' => {
	plan 2;

	# Write text to stdplane and render
	ncplane_putstr_yx($std, 0, 0, "X");
	notcurses_render($nc);

	my uint16 $style = 0;
	my uint64 $channels = 0;
	my $ch = notcurses_at_yx($nc, 0, 0, $style, $channels);
	ok $ch.defined, 'notcurses_at_yx returns a defined value';
	is $ch, 'X', 'notcurses_at_yx reads back "X" from (0,0)';
};

subtest 'Stats alloc, query, and reset' => {
	plan 6;

	my $stats = notcurses_stats_alloc($nc);
	ok $stats.defined, 'Stats struct allocated';

	# Do a render to ensure there is at least one
	notcurses_render($nc);

	notcurses_stats($nc, $stats);
	ok $stats.renders >= 1, "After render: renders >= 1 (got {$stats.renders})";
	ok $stats.planes > 0, "Planes count > 0 (got {$stats.planes})";

	# Reset and verify the cumulative counters are cleared
	my $stats2 = notcurses_stats_alloc($nc);
	notcurses_stats_reset($nc, $stats2);

	# After reset, a fresh stats query should show renders reset to 0
	my $stats3 = notcurses_stats_alloc($nc);
	notcurses_stats($nc, $stats3);
	ok $stats3.defined, 'Stats after reset are defined';
	ok $stats3.renders == 0, "Renders reset to 0 after stats_reset (got {$stats3.renders})";
	ok $stats3.planes > 0, "Planes still > 0 after reset (got {$stats3.planes})";
};

subtest 'Default colors query' => {
	plan 2;

	my uint32 $fg = 0;
	my uint32 $bg = 0;
	my $rc-fg = notcurses_default_foreground($nc, $fg);
	my $rc-bg = notcurses_default_background($nc, $bg);

	# These may return 0 (success) or -1 (terminal does not report defaults)
	ok $rc-fg.defined, "default_foreground returned $rc-fg (fg=$fg)";
	ok $rc-bg.defined, "default_background returned $rc-bg (bg=$bg)";
};

subtest 'Pixel support check' => {
	plan 1;

	my $pixel = notcurses_check_pixel_support($nc);
	ok $pixel.defined, "check_pixel_support returned $pixel";
};

subtest 'Can octant' => {
	plan 1;

	my $octant = notcurses_canoctant($nc);
	ok $octant.defined, "canoctant returned $octant";
};

subtest 'Linesigs disable and enable' => {
	plan 2;

	my $rc = notcurses_linesigs_disable($nc);
	is $rc, 0, 'linesigs_disable returns 0';

	$rc = notcurses_linesigs_enable($nc);
	is $rc, 0, 'linesigs_enable returns 0';
};

subtest 'Input ready file descriptor' => {
	plan 1;

	my $fd = notcurses_inputready_fd($nc);
	ok $fd >= 0, "inputready_fd returned valid fd ($fd)";
};

subtest 'Ncpile create and destroy' => {
	plan 3;

	my $pile-opts = NcplaneOptions.new(:rows(5), :cols(10));
	my $pile = ncpile_create($nc, $pile-opts);
	ok $pile.defined, 'ncpile_create returns a defined plane';

	# Verify we can query dimensions on the pile plane
	my uint32 ($rows, $cols);
	ncplane_dim_yx($pile, $rows, $cols);
	is $rows, 5, 'Pile plane has 5 rows';
	is $cols, 10, 'Pile plane has 10 cols';

	ncplane_destroy($pile);
};

done-testing;