From 34da4f06e1b6ff8a4166c95ca6b5b96fcd40d845 Mon Sep 17 00:00:00 2001 From: despiegk Date: Wed, 30 Jul 2025 23:00:49 +0200 Subject: [PATCH] ... --- examples/hero/db/psql.vsh | 49 ++-- .../postgresql_client_factory_.v | 4 + .../postgresql_client_model.v | 52 +--- .../postgres_client_decoder_test.v | 226 ++++++++++++++++++ 4 files changed, 268 insertions(+), 63 deletions(-) create mode 100644 lib/data/encoderhero/postgres_client_decoder_test.v diff --git a/examples/hero/db/psql.vsh b/examples/hero/db/psql.vsh index 6de99b2e..cfcc3a88 100755 --- a/examples/hero/db/psql.vsh +++ b/examples/hero/db/psql.vsh @@ -7,38 +7,39 @@ import freeflowuniverse.herolib.core.playbook // Configure PostgreSQL client heroscript := " -!!postgresql_client.configure - name:'test' - user: 'postgres' +!!postgresql_client.configure password: 'testpass' + name:'test2' + user: 'testuser' port: 5432 - host: 'localhost' - password: '1234' - dbname: 'postgres' + host: 'localhost' + dbname: 'testdb' " mut plbook := playbook.new(text: heroscript)! postgresql_client.play(mut plbook)! // Get the configured client -mut db_client := postgresql_client.get(name: 'test')! +mut db_client := postgresql_client.get(name: 'test2')! -// Check if test database exists, create if not -if !db_client.db_exists('test')! { - println('Creating database test...') - db_client.db_create('test')! -} +// println(db_client) -// Switch to test database -db_client.dbname = 'test' +// // Check if test database exists, create if not +// if !db_client.db_exists('test')! { +// println('Creating database test...') +// db_client.db_create('test')! +// } -// Create table if not exists -create_table_sql := 'CREATE TABLE IF NOT EXISTS users ( - id SERIAL PRIMARY KEY, - name VARCHAR(100) NOT NULL, - email VARCHAR(255) UNIQUE NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -)' +// // Switch to test database +// db_client.dbname = 'test' -println('Creating table users if not exists...') -db_client.exec(create_table_sql)! +// // Create table if not exists +// create_table_sql := 'CREATE TABLE IF NOT EXISTS users ( +// id SERIAL PRIMARY KEY, +// name VARCHAR(100) NOT NULL, +// email VARCHAR(255) UNIQUE NOT NULL, +// created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +// )' -println('Database and table setup completed successfully!') +// println('Creating table users if not exists...') +// db_client.exec(create_table_sql)! + +// println('Database and table setup completed successfully!') diff --git a/lib/clients/postgresql_client/postgresql_client_factory_.v b/lib/clients/postgresql_client/postgresql_client_factory_.v index 1de77ef5..0bfc9ad9 100644 --- a/lib/clients/postgresql_client/postgresql_client_factory_.v +++ b/lib/clients/postgresql_client/postgresql_client_factory_.v @@ -52,6 +52,7 @@ pub fn set(o PostgresClient) ! { set_in_mem(o)! mut context := base.context()! heroscript := heroscript_dumps(o)! + println(heroscript) context.hero_config_set('postgresql_client', o.name, heroscript)! } @@ -83,7 +84,10 @@ pub fn play(mut plbook PlayBook) ! { if install_actions.len > 0 { for install_action in install_actions { heroscript := install_action.heroscript() + println(heroscript) mut obj2 := heroscript_loads(heroscript)! + println('postgresql_client playbook action: ${obj2}') + if true{panic("TODO: implement playbook action for postgresql_client, currently not implemented yet.")} set(obj2)! } } diff --git a/lib/clients/postgresql_client/postgresql_client_model.v b/lib/clients/postgresql_client/postgresql_client_model.v index 14fb9333..38db43bc 100644 --- a/lib/clients/postgresql_client/postgresql_client_model.v +++ b/lib/clients/postgresql_client/postgresql_client_model.v @@ -9,34 +9,9 @@ pub const version = '0.0.0' const singleton = false const default = true -pub fn heroscript_default() !string { - heroscript := " - !!postgresql_client.configure - name:'default' - user: 'root' - port: 5432 - host: 'localhost' - password: '' - dbname: 'postgres' - " - return heroscript -} - -pub fn heroscript_dumps(obj PostgresClient) !string { - return encoderhero.encode[PostgresClient](obj)! -} - -pub fn heroscript_loads(heroscript string) !PostgresClient { - mut obj := encoderhero.decode[PostgresClient](heroscript)! - return obj -} - -// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED - -@[heap] pub struct PostgresClient { mut: - db_ ?pg.DB + db_ ?pg.DB @[skip] pub mut: name string = 'default' user string = 'root' @@ -46,19 +21,6 @@ pub mut: dbname string = 'postgres' } -fn cfg_play(p paramsparser.Params) !PostgresClient { - mut mycfg := PostgresClient{ - name: p.get_default('name', 'default')! - user: p.get_default('user', 'root')! - port: p.get_int_default('port', 5432)! - host: p.get_default('host', 'localhost')! - password: p.get_default('password', '')! - dbname: p.get_default('dbname', 'postgres')! - } - set(mycfg)! - return mycfg -} - fn obj_init(obj_ PostgresClient) !PostgresClient { // never call get here, only thing we can do here is work on object itself mut obj := obj_ @@ -80,3 +42,15 @@ pub fn (mut self PostgresClient) db() !pg.DB { return db } + + +/////////////NORMALLY NO NEED TO TOUCH + +pub fn heroscript_dumps(obj PostgresClient) !string { + return encoderhero.encode[PostgresClient](obj)! +} + +pub fn heroscript_loads(heroscript string) !PostgresClient { + mut obj := encoderhero.decode[PostgresClient](heroscript)! + return obj +} diff --git a/lib/data/encoderhero/postgres_client_decoder_test.v b/lib/data/encoderhero/postgres_client_decoder_test.v new file mode 100644 index 00000000..a2b36cc3 --- /dev/null +++ b/lib/data/encoderhero/postgres_client_decoder_test.v @@ -0,0 +1,226 @@ +module encoderhero + + +pub struct PostgresClient { +pub mut: + name string = 'default' + user string = 'root' + port int = 5432 + host string = 'localhost' + password string + dbname string = 'postgres' +} + + +const postgres_client_blank = '!!define.postgres_client' +const postgres_client_full = '!!define.postgres_client name:production user:app_user port:5433 host:db.example.com password:secret123 dbname:myapp' +const postgres_client_partial = '!!define.postgres_client name:dev host:localhost password:devpass' + +const postgres_client_complex = " +!!define.postgres_client name:staging user:stage_user port:5434 host:staging.db.com password:stagepass dbname:stagingdb +" + +fn test_postgres_client_decode_blank() ! { + mut client := decode[PostgresClient](postgres_client_blank)! + assert client.name == 'default' + assert client.user == 'root' + assert client.port == 5432 + assert client.host == 'localhost' + assert client.password == '' + assert client.dbname == 'postgres' +} + +fn test_postgres_client_decode_full() ! { + mut client := decode[PostgresClient](postgres_client_full)! + assert client.name == 'production' + assert client.user == 'app_user' + assert client.port == 5433 + assert client.host == 'db.example.com' + assert client.password == 'secret123' + assert client.dbname == 'myapp' +} + +fn test_postgres_client_decode_partial() ! { + mut client := decode[PostgresClient](postgres_client_partial)! + assert client.name == 'dev' + assert client.user == 'root' // default value + assert client.port == 5432 // default value + assert client.host == 'localhost' + assert client.password == 'devpass' + assert client.dbname == 'postgres' // default value +} + +fn test_postgres_client_decode_complex() ! { + mut client := decode[PostgresClient](postgres_client_complex)! + assert client.name == 'staging' + assert client.user == 'stage_user' + assert client.port == 5434 + assert client.host == 'staging.db.com' + assert client.password == 'stagepass' + assert client.dbname == 'stagingdb' +} + +fn test_postgres_client_encode_decode_roundtrip() ! { + // Test encoding and decoding roundtrip + original := PostgresClient{ + name: 'testdb' + user: 'testuser' + port: 5435 + host: 'test.host.com' + password: 'testpass123' + dbname: 'testdb' + } + + // Encode to heroscript + encoded := encode[PostgresClient](original)! + + // Decode back from heroscript + decoded := decode[PostgresClient](encoded)! + + // Verify roundtrip + assert decoded.name == original.name + assert decoded.user == original.user + assert decoded.port == original.port + assert decoded.host == original.host + assert decoded.password == original.password + assert decoded.dbname == original.dbname +} + +fn test_postgres_client_encode() ! { + // Test encoding with different configurations + test_cases := [ + PostgresClient{ + name: 'minimal' + user: 'root' + port: 5432 + host: 'localhost' + password: '' + dbname: 'postgres' + }, + PostgresClient{ + name: 'full_config' + user: 'admin' + port: 5433 + host: 'remote.server.com' + password: 'securepass' + dbname: 'production' + }, + PostgresClient{ + name: 'localhost_dev' + user: 'dev' + port: 5432 + host: '127.0.0.1' + password: 'devpassword' + dbname: 'devdb' + } + ] + + for client in test_cases { + encoded := encode[PostgresClient](client)! + decoded := decode[PostgresClient](encoded)! + + assert decoded.name == client.name + assert decoded.user == client.user + assert decoded.port == client.port + assert decoded.host == client.host + assert decoded.password == client.password + assert decoded.dbname == client.dbname + } +} + +// Play script for interactive testing +const play_script = " +# PostgresClient Encode/Decode Play Script +# This script demonstrates encoding and decoding PostgresClient configurations + +!!define.postgres_client name:playground user:play_user port:5432 host:localhost password:playpass dbname:playdb + +# You can also use partial configurations +!!define.postgres_client name:quick_test host:127.0.0.1 + +# Default configuration (all defaults) +!!define.postgres_client +" + +fn test_play_script() ! { + // Test the play script with multiple configurations + lines := play_script.split_into_lines().filter(fn (line string) bool { + return line.trim(' ') != '' && !line.starts_with('#') + }) + + mut clients := []PostgresClient{} + + for line in lines { + if line.starts_with('!!define.postgres_client') { + client := decode[PostgresClient](line)! + clients << client + } + } + + assert clients.len == 3 + + // First client: full configuration + assert clients[0].name == 'playground' + assert clients[0].user == 'play_user' + assert clients[0].port == 5432 + + // Second client: partial configuration + assert clients[1].name == 'quick_test' + assert clients[1].host == '127.0.0.1' + assert clients[1].user == 'root' // default + + // Third client: defaults only + assert clients[2].name == 'default' + assert clients[2].host == 'localhost' + assert clients[2].port == 5432 +} + +// Utility function for manual testing +pub fn run_play_script() ! { + println('=== PostgresClient Encode/Decode Play Script ===') + println('Testing encoding and decoding of PostgresClient configurations...') + + // Test 1: Basic encoding + println('\n1. Testing basic encoding...') + client := PostgresClient{ + name: 'example' + user: 'example_user' + port: 5432 + host: 'example.com' + password: 'example_pass' + dbname: 'example_db' + } + + encoded := encode[PostgresClient](client)! + println('Encoded: ${encoded}') + + decoded := decode[PostgresClient](encoded)! + println('Decoded name: ${decoded.name}') + println('Decoded host: ${decoded.host}') + + // Test 2: Play script + println('\n2. Testing play script...') + test_play_script()! + println('Play script test passed!') + + // Test 3: Edge cases + println('\n3. Testing edge cases...') + edge_client := PostgresClient{ + name: 'edge' + user: '' + port: 0 + host: '' + password: '' + dbname: '' + } + + edge_encoded := encode[PostgresClient](edge_client)! + edge_decoded := decode[PostgresClient](edge_encoded)! + + assert edge_decoded.name == 'edge' + assert edge_decoded.user == '' + assert edge_decoded.port == 0 + println('Edge cases test passed!') + + println('\n=== All tests completed successfully! ===') +} \ No newline at end of file