# SPDX-License-Identifier: GPL-2.0-or-later

package Amavis::ZMQTest;

use v5.20;
use Test::Most;
use base 'Test::Class';

# Load whichever ZeroMQ backend is available, mirroring the selection logic in
# Amavis::ZMQ. This keeps the test working whether ZMQ::LibZMQ3 or ZMQ::FFI is
# installed and ensures the server socket uses the same backend as Amavis::ZMQ.
BEGIN {
  if (eval { require ZMQ::LibZMQ3 && require ZMQ::Constants }) {
    import ZMQ::LibZMQ3;
    import ZMQ::Constants qw(:all);
  } elsif (eval { require Amavis::ZMQ::FFICompat }) {
    import Amavis::ZMQ::FFICompat;
    import ZMQ::FFI::Constants qw(:all);
  } else {
    plan skip_all =>
      'No supported ZeroMQ backend (ZMQ::LibZMQ3 or ZMQ::FFI) found';
  }
}

sub class { 'Amavis::ZMQ' }

sub startup : Tests(startup => 1) {
  my $test = shift;
  use_ok $test->class;
}

sub messages : Tests(4) {
  my $class = shift->class;

  my $sockname = 'tcp://127.0.0.1:9999';
  my $teststring = 'ZMQ_Test_String';
  my ($server_ctx, $server_sock);
  my $received;
  if (eval {
    $server_ctx  = zmq_init(1) or die $!;
    $server_sock = zmq_socket( $server_ctx, ZMQ_SUB());
    zmq_setsockopt($server_sock, ZMQ_SUBSCRIBE(), '') != -1 or die $!;
    1;
  }){
    my $pid = open (my $from_child, '-|');
    if (defined $pid and $pid) {
      ok 1, 'test forked';
    }
    return unless defined($pid);
    if ($pid) {
      zmq_bind($server_sock, $sockname);
      is <$from_child>, 'client initialized', 'client initialized';
      zmq_poll([{
          socket   => $server_sock,
          events   => ZMQ_POLLIN(),
          callback => sub {
            $received = zmq_msg_data(zmq_recvmsg($server_sock));
          }
        }],
        -1,
      );
      ok $received =~ /$teststring/, 'server received teststring';
      ok waitpid($pid, 0), 'client terminated';
    } else {
      my $zmq = $class->new($sockname);
      print 'client initialized';
      close STDOUT;
      sleep 1;
      $zmq->register_proc(1, 0, $teststring);
      exit;
    }
  } else {
    is $@, undef, 'ZMQ initialized';
  }
}

1;
