### ----------------------------------------------------
### -- MongoDB
### -- Licenses: Artistic-2.0
### -- Authors: Marcel Timmerman, Paweł Pabian
### -- File: xt/Tests/Basic/070-uri.rakutest
### ----------------------------------------------------
use Test;
use MongoDB;
use MongoDB::Uri;

#-------------------------------------------------------------------------------
my Str $log-path = @*ARGS[0];
my Version $version .= new(@*ARGS[1]);
my @server-ports = @*ARGS[2..*];
#note "args: $log-path, $version, @server-ports";

#-------------------------------------------------------------------------------
drop-send-to('mongodb');
drop-send-to('screen');
#modify-send-to( 'screen', :level(MongoDB::MdbLoglevels::Trace));
my $handle = $log-path.IO.open( :mode<wo>, :append);
add-send-to( 'mdb', :to($handle), :min-level(MongoDB::MdbLoglevels::Debug));
#set-filter(|<ObserverEmitter Timer Socket>);

#------------------------------------------------------------------------------
subtest "Uri parsing", {

  my MongoDB::Uri $uri;

  $uri .= new(:uri<mongodb://>);
  ok $uri ~~ MongoDB::Uri , "is url type";
  ok $uri.defined , "url initialized";
#  is $uri.protocol, 'mongodb', 'mongodb:// --> protocol ok';
  is $uri.auth-source, 'admin', 'mongodb:// --> auth database = admin';
  is $uri.username, '', 'mongodb:// --> no username';
  is $uri.password, '', 'mongodb:// --> no password';
  is $uri.servers[0]<host>, 'localhost', 'mongodb:// --> server = localhost';
  is $uri.servers[0]<port>, 27017, 'mongodb:// --> port = 27017';
  ok $uri.options.elems > 1, 'mongodb:// --> there are some default options set';
  is $uri.options<serverSelectionTimeoutMS>, MongoDB::C-SERVERSELECTIONTIMEOUTMS,
     "e.g. serverSelectionTimeoutMS is set to {MongoDB::C-SERVERSELECTIONTIMEOUTMS}";

  $uri .= new(:uri<mongodb://localhost>);
  is $uri.auth-source, 'admin', 'mongodb://localhost --> auth database = admin';
  is $uri.servers[0]<host>, 'localhost', 'mongodb://localhost --> server = localhost';
  is $uri.servers[0]<port>, 27017, 'mongodb://localhost --> port = 27017';

  $uri .= new(:uri<mongodb:///>);
  is $uri.auth-source, 'admin', 'mongodb:/// ->> auth database = admin';
  is $uri.servers[0]<host>, 'localhost', 'mongodb:/// ->> server = localhost';
  is $uri.servers[0]<port>, 27017, 'mongodb:/// ->> port = 27017';

  $uri .= new(:uri<mongodb:///users>);
  is $uri.auth-source, 'users', 'mongodb:///users --> auth database = users';
  is $uri.servers[0]<host>, 'localhost', 'mongodb:///users --> server = localhost';
  is $uri.servers[0]<port>, 27017, 'mongodb:///users --> port = 27017';

  $uri .= new(:uri<mongodb://h2:2345>);
  is $uri.auth-source, 'admin', 'mongodb://h2:2345 --> auth database = admin';
  is $uri.servers[0]<host>, 'h2', 'mongodb://h2:2345 --> server = h2';
  is $uri.servers[0]<port>, 2345, 'mongodb://h2:2345 --> port = 2345';

  $uri .= new(:uri<mongodb://:2345>);
  is $uri.servers[0]<host>, 'localhost', 'mongodb://:2345 --> server = localhost';
  is $uri.servers[0]<port>, 2345, 'mongodb://:2345 --> port = 2345';

  $uri .= new(:uri<mongodb://:9875,:456>);
  is $uri.servers[0]<host>, 'localhost', 'mongodb://:9875,:456 --> server1 = localhost';
  is $uri.servers[0]<port>, 9875, 'mongodb://:9875,:456 --> port1 = 9875';
  is $uri.servers[1]<host>, 'localhost', 'mongodb://:9875,:456 --> server2 = localhost';
  is $uri.servers[1]<port>, 456, 'mongodb://:9875,:456 --> port2 = 456';

  $uri .= new(:uri<mongodb://h2:2345/users>);
  is $uri.auth-source, 'users', 'mongodb://h2:2345/users --> auth database = users';
  is $uri.servers[0]<host>, 'h2', 'mongodb://h2:2345/users --> server = h2';
  is $uri.servers[0]<port>, 2345, 'mongodb://h2:2345/users --> port = 2345';

  $uri .= new(:uri<mongodb://h1,h2,localhost:2000/>);
  is $uri.servers[0]<host>, 'h1', 'mongodb://h1,h2,localhost:2000/ --> server1 = h1';
  is $uri.servers[0]<port>, 27017, 'mongodb://h1,h2,localhost:2000/ --> port1 = 27017';
  is $uri.servers[1]<host>, 'h2', 'mongodb://h1,h2,localhost:2000/ --> server2 = h2';
  is $uri.servers[1]<port>, 27017, 'mongodb://h1,h2,localhost:2000/ --> port2 = 27017';
  is $uri.servers[2]<host>, 'localhost', 'mongodb://h1,h2,localhost:2000/ --> server3 = localhost';
  is $uri.servers[2]<port>, 2000, 'mongodb://h1,h2,localhost:2000/ --> port3 = 2000';

  $uri .= new(:uri<mongodb:///?a=b>);
  is $uri.servers[0]<host>, 'localhost', 'mongodb:///?a=b --> server = localhost';
  is $uri.servers[0]<port>, 27017, 'mongodb:///?a=b --> port = 27017';
  is $uri.auth-source, 'admin', 'mongodb:///?a=b --> auth database = admin';
  is $uri.options<a>, 'b', 'mongodb:///?a=b --> option a => b';

  $uri .= new(:uri<mongodb:///users?test=2&list=jhg3>);
  is $uri.servers[0]<host>, 'localhost', 'mongodb:///users?test=2&list=jhg3 --> server = localhost';
  is $uri.servers[0]<port>, 27017, 'mongodb:///users?test=2&list=jhg3 --> port = 27017';
  is $uri.auth-source, 'users', 'mongodb:///users?test=2&list=jhg3 --> auth database = users';
  is $uri.options<test>, '2', 'mongodb:///users?test=2&list=jhg3 --> option test = 2';
  is $uri.options<list>, 'jhg3', 'mongodb:///users?test=2&list=jhg3 --> option list = jhg3';

  $uri .= new(:uri<mongodb://mt%40tm:p%3Aw@>);
  is $uri.servers[0]<host>, 'localhost', 'mongodb://mt%40tm:p%3Aw@ --> server = localhost';
  is $uri.servers[0]<port>, 27017, 'mongodb://mt%40tm:p%3Aw@ --> port = 27017';
  is $uri.auth-source, 'admin', 'mongodb://mt%40tm:p%3Aw@ --> auth database = admin';
  is $uri.username, 'mt@tm', 'mongodb://mt%40tm:p%3Aw@ --> username = mt@tm';
  is $uri.password, 'p:w', 'mongodb://mt%40tm:p%3Aw@ --> password = p:w';

  $uri .= new(:uri<mongodb://mt:pw@h2:9876/users>);
  is $uri.servers[0]<host>, 'h2', 'mongodb://mt:pw@h2:9876/users --> server = h2';
  is $uri.servers[0]<port>, 9876, 'mongodb://mt:pw@h2:9876/users --> port = 9876';
  is $uri.auth-source, 'users', 'mongodb://mt:pw@h2:9876/users --> auth database = users';
  is $uri.username, 'mt', 'mongodb://mt:pw@h2:9876/users --> username = mt';
  is $uri.password, 'pw', 'mongodb://mt:pw@h2:9876/users --> password = pw';

  $uri .= new(:uri<mongodb://Dondersteen:w%40tD8jeDan@h2:9876/users>);
  is $uri.auth-source, 'users', 'mongodb://Dondersteen:w%40tD8jeDan@h2:9876/users --> auth database = users';
  is $uri.username, 'Dondersteen', 'mongodb://Dondersteen:w%40tD8jeDan@h2:9876/users --> username = Dondersteen';
  is $uri.password, 'w@tD8jeDan', 'mongodb://Dondersteen:w%40tD8jeDan@h2:9876/users --> password = w@tD8jeDan';
};

#------------------------------------------------------------------------------
subtest "Uri parsing errors", {

  my MongoDB::Uri $uri;

  throws-like {$uri .= new(:uri<http://>);},
              X::MongoDB, 'It is not a http protocol',
              :message("Parsing error in url 'http://'");

  throws-like {$uri .= new(:uri<mongo://>)},
              X::MongoDB, 'Nor a mongo protocol',
              :message("Parsing error in url 'mongo://'");

  throws-like {$uri .= new(:uri<mongodb://?a=b>)},
              X::MongoDB, "Missing a '/'",
              :message("Parsing error in url 'mongodb://?a=b'");

  throws-like {$uri .= new(
      :uri<mongodb://?tlsInsecure=true&tlsAllowInvalidCertificates=true>
    )},
    X::MongoDB,
    "tlsInsecure and tlsAllowInvalidCertificates cannot be used together",
    :message(
      "Parsing error in url 'mongodb://?tlsInsecure=true&tlsAllowInvalidCertificates=true'"
    );

  throws-like {$uri .= new(
    :uri<mongodb://?tlsAllowInvalidCertificates=true&tlsDisableCertificateRevocationCheck=true>
    )},
    X::MongoDB,
    "tlsAllowInvalidCertificates and tlsDisableCertificateRevocationCheck cannot be used together",
    :message(
      "Parsing error in url 'mongodb://?tlsAllowInvalidCertificates=true&tlsDisableCertificateRevocationCheck=true'"
    );

  throws-like {$uri .= new(
      :uri<mongodb+srv://server.example.com?directConnection=true>)
    },
    X::MongoDB,
    "Cannot ask for a direct connection if you want DNS SRV record polling",
    :message(
      "Parsing error in url 'mongodb+srv://server.example.com?directConnection=true'"
    );

  throws-like {$uri .= new(
      :uri<mongodb+srv://s1.example.com,s2.example.com>)
    },
    X::MongoDB,
    "Cannot provide multiple FQDN if you want DNS SRV record polling",
    :message(
      "Parsing error in url 'mongodb+srv://s1.example.com,s2.example.com'"
    );

  throws-like {
      $uri .= new(:uri<mongodb+srv://s1.example.com:20000>)
    },
    X::MongoDB,
    "You may not define a port number when polling for DNS SRV records",
    :message(
      "Parsing error in url 'mongodb+srv://s1.example.com:20000'"
    );

  throws-like {
      $uri .= new(
        :uri<mongodb+srv://Dondersteen:w%40tD8jeDan@h2.example.com/users>
      )
    },
    X::MongoDB,
    "No servers found after search on domain h2.example.com",
    :message(
      "No servers found after search on domain 'h2.example.com'"
    );


}

#------------------------------------------------------------------------------
# Cleanup
info-message("Test $?FILE stop");
done-testing();




=finish

#------------------------------------------------------------------------------
subtest {

}, '';

say "\nReq: ", $req.perl, "\n";
say "\nDoc: ", $doc.perl, "\n";


