From bbd8b3635306730ee1c557d4b347acad87440286 Mon Sep 17 00:00:00 2001 From: Volodymyr Katkalov Date: Tue, 14 Jan 2025 16:19:35 +0200 Subject: [PATCH] Redis7 conflict resolution --- tests/console/redis.pm | 232 ++++++++++++++++++++++++++++++++++------- 1 file changed, 193 insertions(+), 39 deletions(-) diff --git a/tests/console/redis.pm b/tests/console/redis.pm index 172d29778be6..cd9d78faea5b 100644 --- a/tests/console/redis.pm +++ b/tests/console/redis.pm @@ -20,65 +20,219 @@ use serial_terminal 'select_serial_terminal'; use utils qw(zypper_call script_retry validate_script_output_retry); use registration qw(add_suseconnect_product get_addon_fullname); -sub run { - my $self = shift; - select_serial_terminal; +my $default_redis_version = "redis"; +my @redis_versions = ($default_redis_version, "redis7"); +my $default_redis_port = "6379"; +my $default_redis_replica_port = "6380"; +my $killall_redis_server_cmd = "killall redis-server"; +my $remove_test_db_file_cmd = "rm -f movies.redis"; + +sub get_redis_version { + my $output = script_output('redis-server --version'); + my $version = ""; - # install redis package - zypper_call 'in redis'; - assert_script_run('redis-server --version'); + if ($output =~ /v=(.+?)\s/) { + $version = $1; # Capture the first match + } - # start redis server on port 6379 and test that it works - assert_script_run('redis-server --daemonize yes --logfile /var/log/redis/redis-server_6379.log'); - script_retry('redis-cli ping', delay => 5, retry => 12); - validate_script_output_retry('redis-cli ping', sub { m/PONG/ }, delay => 5, retry => 12); + die "Failed to extract Redis version!" if $version eq ""; - # test some redis cli commands - validate_script_output('redis-cli set foo bar', sub { m/OK/ }); - validate_script_output('redis-cli get foo', sub { m/bar/ }); - validate_script_output('redis-cli pfselftest', sub { m/OK/ }); - validate_script_output('redis-cli flushdb', sub { m/OK/ }); - validate_script_output('redis-cli get foo', sub { !m/bar/ }); + return $version; +} + +sub test_ping { + my (%args) = @_; + $args{port} //= $default_redis_port; + my $redis_cli_cmd = "redis-cli -p $args{port}"; + + script_retry("$redis_cli_cmd ping", delay => 5, retry => 12); + validate_script_output_retry("$redis_cli_cmd ping", sub { m/PONG/ }, delay => 5, retry => 12); +} +sub test_crud { + my (%args) = @_; + $args{port} //= $default_redis_port; + my $redis_cli_cmd = "redis-cli -p $args{port}"; + + # Perform CRUD operations + validate_script_output("$redis_cli_cmd set foo bar", sub { m/OK/ }); + validate_script_output("$redis_cli_cmd get foo", sub { m/bar/ }); + validate_script_output("$redis_cli_cmd pfselftest", sub { m/OK/ }); + validate_script_output("$redis_cli_cmd flushdb", sub { m/OK/ }); + validate_script_output("$redis_cli_cmd get foo", sub { !m/bar/ }); +} + +sub load_test_db_and_validate { + my (%args) = @_; + $args{port} //= $default_redis_port; + my $redis_cli_cmd = "redis-cli -p $args{port}"; + + # Load test DB and validate data assert_script_run 'curl -O ' . data_url('console/movies.redis'); - assert_script_run('redis-cli -h localhost -p 6379 < ./movies.redis'); + assert_script_run("$redis_cli_cmd < ./movies.redis"); + validate_script_output("$redis_cli_cmd HMGET \"movie:343\" title", sub { m/Spider-Man/ }); +} + +sub verify_replication_status { + my (%args) = @_; + $args{port} //= $default_redis_port; + $args{replica_port} //= $default_redis_replica_port; + + my $redis_cli_cmd = "redis-cli -p $args{port}"; + my $redis_replica_cli_cmd = "redis-cli -p $args{replica_port}"; + + # Verify replication status + validate_script_output_retry("$redis_cli_cmd info replication", sub { m/connected_slaves:1/ }, delay => 5, retry => 12); + validate_script_output("$redis_replica_cli_cmd info replication", sub { m/role:slave/ }); + validate_script_output_retry("$redis_replica_cli_cmd info replication", sub { m/master_link_status:up/ }, delay => 5, retry => 12); +} + +sub configure_and_test_master { + my (%args) = @_; + $args{port} //= $default_redis_port; + + test_ping(port => $args{port}); + test_crud(port => $args{port}); + load_test_db_and_validate(port => $args{port}); +} + +sub configure_and_test_replica { + my (%args) = @_; + $args{port} //= $default_redis_port; + $args{replica_port} //= $default_redis_replica_port; + + my $redis_replica_cli_cmd = "redis-cli -p $args{replica_port}"; + + test_ping(port => $args{replica_port}); + + # Configure replication + assert_script_run("$redis_replica_cli_cmd replicaof localhost $args{port}"); + + verify_replication_status(); + + # Validate data from the replica + validate_script_output("$redis_replica_cli_cmd HMGET \"movie:343\" title", sub { m/Spider-Man/ }); +} + +sub cleanup_redis { + my (%args) = @_; + $args{redis_version} //= $default_redis_version; + $args{port} //= $default_redis_port; + $args{replica_port} //= $default_redis_replica_port; + + my $redis_cli_cmd_prefix = "redis-cli -p "; + my $redis_cli_cmd_postfix = " flushall"; - validate_script_output('redis-cli HMGET "movie:343" title', sub { m/Spider-Man/ }); + my $redis_cli_cmd = $redis_cli_cmd_prefix . $args{port} . $redis_cli_cmd_postfix; + my $redis_replica_cli_cmd = $redis_cli_cmd_prefix . $args{replica_port} . $redis_cli_cmd_postfix; - # start redis server on port 6380 and test that it works - assert_script_run('redis-server --daemonize yes --port 6380 --logfile /var/log/redis/redis-server_6380.log'); - validate_script_output_retry('redis-cli -p 6380 ping', sub { m/PONG/ }, delay => 5, retry => 12); + # Clean up after testing + assert_script_run($redis_cli_cmd); + assert_script_run($redis_replica_cli_cmd); - # make 6380 instance a replica of redis instance running on port 6379 - assert_script_run('redis-cli -p 6380 replicaof localhost 6379'); + assert_script_run($killall_redis_server_cmd); + assert_script_run($remove_test_db_file_cmd); + assert_script_run("find / -type f -name 'dump.rdb' -print -exec rm -f {} + || true"); +} + +sub log_location { + my (%args) = @_; + $args{redis_version} //= $default_redis_version; + $args{port} //= $default_redis_port; + my $logfile_prefix = "/var/log/redis/redis-server_" . $args{redis_version} . "_"; + my $logfile_postfix = ".log"; + + return $logfile_prefix . $args{port} . $logfile_postfix; +} - # test master knows about the slave and vice versa - validate_script_output_retry('redis-cli info replication', sub { m/connected_slaves:1/ }, delay => 5, retry => 12); - validate_script_output('redis-cli -p 6380 info replication', sub { m/role:slave/ }); +sub upload_redis_logs { + my (%args) = @_; + $args{redis_version} //= $default_redis_version; + $args{port} //= $default_redis_port; + $args{replica_port} //= $default_redis_replica_port; - # test that the synchronization finished and the data are reachable from slave - validate_script_output_retry('redis-cli info replication', sub { m/state=online/ }, delay => 5, retry => 12); - validate_script_output('redis-cli -p 6380 HMGET "movie:343" title', sub { m/Spider-Man/ }); + my $logfile = log_location(redis_version => $args{redis_version}, port => $args{port}); + my $replica_logfile = log_location(redis_version => $args{redis_version}, port => $args{replica_port}); + + # Upload logs + upload_logs($logfile) if -e $logfile; + upload_logs($replica_logfile) if -e $replica_logfile; +} + +sub print_redis_logs { + my (%args) = @_; + $args{redis_version} //= $default_redis_version; + $args{port} //= $default_redis_port; + $args{replica_port} //= $default_redis_replica_port; + + my $logfile = log_location(redis_version => $args{redis_version}, port => $args{port}); + my $replica_logfile = log_location(redis_version => $args{redis_version}, port => $args{replica_port}); + + # Print logs + record_info("Redis version " . $args{redis_version}, script_output("cat " . $logfile)); + record_info("Redis version " . $args{redis_version}, script_output("cat " . $replica_logfile)); +} + +sub test_redis { + my (%args) = @_; + $args{redis_version} //= $default_redis_version; + $args{port} //= $default_redis_port; + $args{replica_port} //= $default_redis_replica_port; + + zypper_call('in --force-resolution --solver-focus Update ' . $args{redis_version}); + + my $version = get_redis_version(); + + record_info("Testing " . $args{redis_version} . " v=" . $version); + + my $logfile = log_location(redis_version => $args{redis_version}, port => $args{port}); + my $replica_logfile = log_location(redis_version => $args{redis_version}, port => $args{replica_port}); + + my $redis_server_cmd_prefix = "redis-server --daemonize yes --port "; + my $redis_server_cmd = $redis_server_cmd_prefix . $args{port} . " --logfile " . $logfile; + my $redis_server_replica_cmd = $redis_server_cmd_prefix . $args{replica_port} . " --logfile " . $replica_logfile; + + # Start the primary redis server + assert_script_run($redis_server_cmd); + configure_and_test_master(port => $args{port}); + + + # Start the replica redis server + assert_script_run($redis_server_replica_cmd); + configure_and_test_replica(port => $args{port}, replica_port => $args{replica_port}); + + cleanup_redis(redis_version => $args{redis_version}, port => $args{port}, replica_port => $args{replica_port}); + + upload_redis_logs(redis_version => $args{redis_version}, port => $args{port}, replica_port => $args{replica_port}); +} + +sub run { + my $self = shift; + select_serial_terminal; + + foreach my $redis_version (@redis_versions) { + test_redis(redis_version => $redis_version); + } } sub post_fail_hook { my $self = shift; - $self->cleanup(); + foreach my $redis_version (@redis_versions) { + print_redis_logs(redis_version => $redis_version, port => $default_redis_port, replica_port => $default_redis_replica_port); + } + my $proceed_on_fail_cmd = " || true"; + script_run($killall_redis_server_cmd . $proceed_on_fail_cmd); + script_run($remove_test_db_file_cmd . $proceed_on_fail_cmd); + foreach my $redis_version (@redis_versions) { + upload_redis_logs(redis_version => $redis_version, port => $default_redis_port, replica_port => $default_redis_replica_port); + } $self->SUPER::post_fail_hook; } sub post_run_hook { my $self = shift; - $self->cleanup(); + zypper_call('rm -u ' . $redis_versions[-1]); $self->SUPER::post_run_hook; } -sub cleanup { - upload_logs('/var/log/redis/redis-server_6379.log'); - upload_logs('/var/log/redis/redis-server_6380.log'); - assert_script_run('redis-cli -h localhost flushall'); - assert_script_run('killall redis-server'); - assert_script_run('rm -f movies.redis'); -} - 1;