AmberDB
view release on metacpan or search on metacpan
t/amberdb_cli.t view on Meta::CPAN
ok(-f $cli_path, "amberdb_cli.pl exists at $cli_path");
my $test_tmpdir = tempdir(CLEANUP => 1);
my $test_dbdir = File::Spec->catdir($test_tmpdir, "dbstore");
mkdir $test_dbdir unless -d $test_dbdir;
$test_dbdir = eval { abs_path($test_dbdir) } // $test_dbdir;
sub norm_path {
my ($p) = @_;
return '' unless defined $p;
$p = eval { abs_path($p) } // $p;
$p = File::Spec->canonpath($p);
$p =~ s{\\}{/}g;
$p =~ s{/+$}{};
return lc($p);
}
# ---------------------------------------------------------------------------
subtest '1. Help screen & default table overview' => sub {
plan tests => 4;
my $out_help = `"$perl_bin" -Ilib "$cli_path" usage`;
like($out_help, qr/AmberDB CLI/, "Help screen shows CLI title");
like($out_help, qr/Usage:/, "Usage screen shows English usage section");
my $out_tr = `"$perl_bin" -Ilib "$cli_path" usage.tr`;
like($out_tr, qr/Kullanım:/, "usage.tr shows Turkish usage section");
my $out_list = `"$perl_bin" -Ilib "$cli_path" path-dbase_dir="$test_dbdir" format=json`;
my $data = eval { decode_json($out_list) };
is(ref $data, 'HASH', "Default action outputs valid JSON with format=json");
};
# ---------------------------------------------------------------------------
subtest '2. Connect lifecycle & token generation' => sub {
plan tests => 5;
my $out_conn = `"$perl_bin" -Ilib "$cli_path" connect path-dbase_dir="$test_dbdir" cfg-language=tr format=json`;
my $conn = eval { decode_json($out_conn) };
is(ref $conn, 'HASH', "Connect returned valid JSON");
is($conn->{status}, 'connected', "Status is connected");
ok(defined $conn->{token} && $conn->{token} =~ /^\d{4}$/, "4-digit token generated: $conn->{token}");
my $token = $conn->{token};
# Verify session file exists
my $sess_file = $conn->{session_file} || File::Spec->catfile($test_dbdir, "session", "cli_$token");
ok(-f $sess_file, "Session file exists on disk: $sess_file");
# Read session file content
open my $fh, '<', $sess_file;
local $/;
my $sess_json = <$fh>;
close $fh;
my $sess_data = decode_json($sess_json);
is($sess_data->{cfg}->{language}, 'tr', "Config language 'tr' saved in session");
};
# ---------------------------------------------------------------------------
subtest '3. Dash tolerance & global config update' => sub {
plan tests => 4;
# Connect to get token
my $out_conn = `"$perl_bin" -Ilib "$cli_path" connect path-dbase_dir="$test_dbdir" format=json`;
my $conn = eval { decode_json($out_conn) };
my $token = $conn ? $conn->{token} : '';
# Update with --cfg-no_write=1 (double dash)
my $upd1 = `"$perl_bin" -Ilib "$cli_path" --token=$token --cfg-no_write=1 format=json 2>&1`;
my $data1 = eval { decode_json($upd1) };
is(eval { $data1->{cfg}->{no_write} }, 1, "Double dash --cfg-no_write=1 updated") or diag("upd1 output: $upd1");
# Update with -cfg-no_write=0 (single dash)
my $upd2 = `"$perl_bin" -Ilib "$cli_path" -token=$token -cfg-no_write=0 format=json 2>&1`;
my $data2 = eval { decode_json($upd2) };
is(eval { $data2->{cfg}->{no_write} }, 0, "Single dash -cfg-no_write=0 updated") or diag("upd2 output: $upd2");
# Update with cfg-no_write=1 (no dash)
my $upd3 = `"$perl_bin" -Ilib "$cli_path" token=$token cfg-no_write=1 format=json 2>&1`;
my $data3 = eval { decode_json($upd3) };
is(eval { $data3->{cfg}->{no_write} }, 1, "No dash cfg-no_write=1 updated") or diag("upd3 output: $upd3");
# Clean disconnect
my $disc = `"$perl_bin" -Ilib "$cli_path" token=$token disconnect format=json 2>&1`;
my $ddata = eval { decode_json($disc) };
is(eval { $ddata->{status} }, 'disconnected', "Disconnected successfully") or diag("disc output: $disc");
};
# ---------------------------------------------------------------------------
subtest '4. Table attributes with deep nested parsing and session persistence' => sub {
plan tests => 6;
my $out_conn = `"$perl_bin" -Ilib "$cli_path" connect path-dbase_dir="$test_dbdir" format=json`;
my $token = decode_json($out_conn)->{token};
# table_attr with deep keys: blocks-1-rdbm and search_block=[1]
my $cmd = qq{"$perl_bin" -Ilib "$cli_path" token=$token action=table_attr table=cli_test_prod search_block=[1] keep_deleted=1 blocks-1-rdbm=cat,1 format=json};
my $out_attr = `$cmd`;
my $attr_data = decode_json($out_attr);
is($attr_data->{status}, 'ok', "table_attr executed successfully");
is($attr_data->{attributes}->{keep_deleted}, 1, "keep_deleted attribute set to 1");
is_deeply($attr_data->{attributes}->{search_block}, [1], "search_block parsed as JSON array [1]");
is(ref $attr_data->{attributes}->{blocks}->{1}->{rdbm}, 'HASH', "rdbm normalized to HASH");
is($attr_data->{attributes}->{blocks}->{1}->{rdbm}->{table}, 'cat', "Deep nested blocks-1-rdbm table parsed");
# Disconnect
`"$perl_bin" -Ilib "$cli_path" token=$token disconnect`;
my $sess_file = File::Spec->catfile($test_dbdir, "session", "cli_$token");
ok(!-f $sess_file, "Session file deleted on disconnect");
};
# ---------------------------------------------------------------------------
subtest '5. CRUD operations & no_write protection' => sub {
plan tests => 8;
my $out_conn = `"$perl_bin" -Ilib "$cli_path" connect path-dbase_dir="$test_dbdir" cfg-no_write=1 format=json`;
my $token = decode_json($out_conn)->{token};
# Attempt insert when no_write is 1
my $ins_blocked = `"$perl_bin" -Ilib "$cli_path" token=$token action=insert_id table=cli_items id=1 data='["Book",15]' 2>&1`;
( run in 0.474 second using v1.01-cache-2.11-cpan-4716db65a44 )