view tests/tests.md @ 970:f90d811e97eb default tip

Adjust getTableTypes() test for new table type: LOCAL TEMPORARY VIEW, added in 11.53.4 (Mar2025-SP1)
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Thu, 03 Apr 2025 15:01:33 +0200 (35 hours ago)
parents 9f6fe96c0ead
children
line wrap: on
line source
# Tests

This document contains a large number of test cases.
They are embedded in the Markdown source, in <code>```test</code>
. . .</code>```</code> blocks.


The tests are written in a mini language with the following
keywords:

* `PARSE url`: parse the URL, this should succeed. The validity checks need
  not be satisfied.

* `ACCEPT url`: parse the URL, this should succeed. The validity checks
  should pass.

* `REJECT url`: parse the URL, it should be rejected either in the parsing stage
  or by the validity checks.

* `SET key=value`: modify a parameter, can occur before or after parsing the URL.
  Used to model command line parameters, Java Properties objects, etc.

* `EXPECT key=value`: verify that the given parameter now has the given
  value. Fail the test case if the value is different.

* `ONLY pymonetdb`: only process the rest of the block when testing
  pymonetdb, ignore it for other implementations.

* `NOT pymonetdb`: ignore the rest of the block when testing pymonetdb,
  do process it for other implementations.

At the start of each block the parameters are reset to their default values.

The EXPECT clause can verify all parameters listen in the Parameters section of
the spec, all 'virtual parameters' and also the special case `valid` which is a
boolean indicating whether all validity rules in section 'Interpreting the
parameters' hold.

Note: an `EXPECT` of the virtual parameters implies `EXPECT valid=true`.

TODO before 1.0 does the above explanation make sense?


## Tests from the examples

```test
ACCEPT monetdb:///demo
EXPECT database=demo
EXPECT connect_scan=true
```

```test
ACCEPT monetdb://localhost/demo
EXPECT connect_scan=true
EXPECT database=demo
```

```test
ACCEPT monetdb://localhost./demo
EXPECT connect_scan=false
EXPECT connect_unix=
EXPECT connect_tcp=localhost
EXPECT connect_port=50000
EXPECT tls=off
EXPECT database=demo
```

```test
ACCEPT monetdb://localhost.:12345/demo
EXPECT connect_scan=false
EXPECT connect_unix=
EXPECT connect_tcp=localhost
EXPECT connect_port=12345
EXPECT tls=off
EXPECT database=demo
```

```test
ACCEPT monetdb://localhost:12345/demo
EXPECT connect_scan=false
EXPECT connect_unix=/tmp/.s.monetdb.12345
EXPECT connect_tcp=localhost
EXPECT connect_port=12345
EXPECT tls=off
EXPECT database=demo
```

```test
ACCEPT monetdb:///demo?user=monetdb&password=monetdb
EXPECT connect_scan=true
EXPECT database=demo
EXPECT user=monetdb
EXPECT password=monetdb
```

```test
ACCEPT monetdb://mdb.example.com:12345/demo
EXPECT connect_scan=false
EXPECT connect_unix=
EXPECT connect_tcp=mdb.example.com
EXPECT connect_port=12345
EXPECT tls=off
EXPECT database=demo
```

```test
ACCEPT monetdb://192.168.13.4:12345/demo
EXPECT connect_scan=false
EXPECT connect_unix=
EXPECT connect_tcp=192.168.13.4
EXPECT connect_port=12345
EXPECT tls=off
EXPECT database=demo
```

```test
ACCEPT monetdb://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:12345/demo
EXPECT host=2001:0db8:85a3:0000:0000:8a2e:0370:7334
EXPECT connect_scan=false
EXPECT connect_unix=
EXPECT connect_tcp=2001:0db8:85a3:0000:0000:8a2e:0370:7334
EXPECT connect_port=12345
EXPECT tls=off
EXPECT database=demo
```

```test
ACCEPT monetdb://localhost/
EXPECT connect_unix=/tmp/.s.monetdb.50000
EXPECT connect_scan=false
EXPECT connect_tcp=localhost
EXPECT tls=off
EXPECT database=
```

```test
ACCEPT monetdb://localhost
EXPECT connect_scan=false
EXPECT connect_unix=/tmp/.s.monetdb.50000
EXPECT connect_tcp=localhost
EXPECT tls=off
EXPECT database=
```

```test
ACCEPT monetdbs://mdb.example.com/demo
EXPECT connect_scan=false
EXPECT connect_unix=
EXPECT connect_tcp=mdb.example.com
EXPECT connect_port=50000
EXPECT tls=on
EXPECT connect_tls_verify=system
EXPECT database=demo
```

```test
ACCEPT monetdbs:///demo
EXPECT connect_scan=false
EXPECT connect_unix=
EXPECT connect_tcp=localhost
EXPECT connect_port=50000
EXPECT tls=on
EXPECT connect_tls_verify=system
EXPECT database=demo
```

```test
ACCEPT monetdbs://mdb.example.com/demo?cert=/home/user/server.crt
EXPECT connect_scan=false
EXPECT connect_unix=
EXPECT connect_tcp=mdb.example.com
EXPECT connect_port=50000
EXPECT tls=on
EXPECT connect_tls_verify=cert
EXPECT cert=/home/user/server.crt
EXPECT database=demo
```

```test
ACCEPT monetdbs://mdb.example.com/demo?certhash=sha256:fb:67:20:aa:00:9f:33:4c
EXPECT connect_scan=false
EXPECT connect_unix=
EXPECT connect_tcp=mdb.example.com
EXPECT connect_port=50000
EXPECT tls=on
EXPECT connect_tls_verify=hash
EXPECT certhash=sha256:fb:67:20:aa:00:9f:33:4c
EXPECT connect_certhash_digits=fb6720aa009f334c
EXPECT database=demo
```

```test
ACCEPT monetdb:///demo?sock=/var/monetdb/_sock&user=dbuser
EXPECT connect_scan=false
EXPECT connect_unix=/var/monetdb/_sock
EXPECT connect_tcp=
EXPECT tls=off
EXPECT database=demo
EXPECT user=dbuser
EXPECT password=
```

```test
ACCEPT monetdb://localhost/demo?sock=/var/monetdb/_sock&user=dbuser
EXPECT connect_scan=false
EXPECT connect_unix=/var/monetdb/_sock
EXPECT connect_tcp=
EXPECT tls=off
EXPECT database=demo
EXPECT user=dbuser
EXPECT password=
```


## Parameter tests

Tests derived from the parameter section. Test data types and defaults.

Everything can be SET and EXPECTed

```test
SET tls=on
EXPECT tls=on
SET host=bananahost
EXPECT host=bananahost
SET port=123
EXPECT port=123
SET database=bananadatabase
EXPECT database=bananadatabase
SET tableschema=bananatableschema
EXPECT tableschema=bananatableschema
SET table=bananatable
EXPECT table=bananatable
SET sock=c:\foo.txt
EXPECT sock=c:\foo.txt
SET cert=c:\foo.txt
EXPECT cert=c:\foo.txt
SET certhash=bananacerthash
EXPECT certhash=bananacerthash
SET clientkey=c:\foo.txt
EXPECT clientkey=c:\foo.txt
SET clientcert=c:\foo.txt
EXPECT clientcert=c:\foo.txt
SET user=bananauser
EXPECT user=bananauser
SET password=bananapassword
EXPECT password=bananapassword
SET language=bananalanguage
EXPECT language=bananalanguage
SET autocommit=on
EXPECT autocommit=on
SET schema=bananaschema
EXPECT schema=bananaschema
SET timezone=123
EXPECT timezone=123
SET binary=bananabinary
EXPECT binary=bananabinary
SET replysize=123
EXPECT replysize=123
SET fetchsize=123
EXPECT fetchsize=123
```

### core defaults

```test
EXPECT tls=false
EXPECT host=
EXPECT port=-1
EXPECT database=
EXPECT tableschema=
EXPECT table=
EXPECT binary=on
```

### sock

Not supported on Windows, but they should still parse.

```test
EXPECT sock=
ACCEPT monetdb:///?sock=/tmp/sock
EXPECT sock=/tmp/sock
ACCEPT monetdb:///?sock=C:/TEMP/sock
EXPECT sock=C:/TEMP/sock
NOT jdbc
ACCEPT monetdb:///?sock=C:\TEMP\sock
EXPECT sock=C:\TEMP\sock
```

### sockdir

```test
EXPECT sockdir=/tmp
ACCEPT monetdb:///demo?sockdir=/tmp/nonstandard
EXPECT sockdir=/tmp/nonstandard
EXPECT connect_unix=/tmp/nonstandard/.s.monetdb.50000
```

### cert

```test
EXPECT cert=
ACCEPT monetdbs:///?cert=/tmp/cert.pem
EXPECT cert=/tmp/cert.pem
ACCEPT monetdbs:///?cert=C:/TEMP/cert.pem
EXPECT cert=C:/TEMP/cert.pem
NOT jdbc
ACCEPT monetdbs:///?cert=C:\TEMP\cert.pem
EXPECT cert=C:\TEMP\cert.pem
```

### certhash

```test
EXPECT certhash=
ACCEPT monetdbs:///?certhash=sha256:001122ff
ACCEPT monetdbs:///?certhash=sha256:00:11:22:ff
ACCEPT monetdbs:///?certhash=sha256:::::aa::ff:::::
ACCEPT monetdbs:///?certhash=sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
```

This string of hexdigits is longer than the length of a SHA-256 digest.
It still parses, it will just never match.

```test
ACCEPT monetdbs:///?certhash=sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8550
ACCEPT monetdbs:///?certhash=sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855000000000000000000000000000000000000000001
```

```test
REJECT monetdbs:///?certhash=001122ff
REJECT monetdbs:///?certhash=Sha256:001122ff
REJECT monetdbs:///?certhash=sha256:001122gg
REJECT monetdbs:///?certhash=sha
REJECT monetdbs:///?certhash=sha1:aabbcc
REJECT monetdbs:///?certhash=sha1:
REJECT monetdbs:///?certhash=sha1:X
REJECT monetdbs:///?certhash=sha99:aabbcc
REJECT monetdbs:///?certhash=sha99:
REJECT monetdbs:///?certhash=sha99:X
```

### clientkey, clientcert

```test
EXPECT clientkey=
EXPECT clientcert=
ACCEPT monetdbs:///?clientkey=/tmp/clientkey.pem
EXPECT clientkey=/tmp/clientkey.pem
ACCEPT monetdbs:///?clientkey=C:/TEMP/clientkey.pem
EXPECT clientkey=C:/TEMP/clientkey.pem
NOT jdbc
ACCEPT monetdbs:///?clientkey=C:\TEMP\clientkey.pem
EXPECT clientkey=C:\TEMP\clientkey.pem
```

```test
EXPECT connect_clientkey=
EXPECT connect_clientcert=
```

```test
SET clientkey=/tmp/key.pem
SET clientcert=/tmp/cert.pem
EXPECT valid=true
EXPECT connect_clientkey=/tmp/key.pem
EXPECT connect_clientcert=/tmp/cert.pem
```

```test
SET clientkey=/tmp/key.pem
EXPECT valid=true
EXPECT connect_clientkey=/tmp/key.pem
EXPECT connect_clientcert=/tmp/key.pem
```

```test
SET clientcert=/tmp/cert.pem
EXPECT valid=false
```

```test
SET clientkey=dummy
EXPECT clientcert=
ACCEPT monetdbs:///?clientcert=/tmp/clientcert.pem
EXPECT clientcert=/tmp/clientcert.pem
ACCEPT monetdbs:///?clientcert=C:/TEMP/clientcert.pem
EXPECT clientcert=C:/TEMP/clientcert.pem
NOT jdbc
ACCEPT monetdbs:///?clientcert=C:\TEMP\clientcert.pem
EXPECT clientcert=C:\TEMP\clientcert.pem
```

### user, password

Not testing the default because they are (unfortunately)
implementation specific.

```test
ACCEPT monetdb:///?user=monetdb
EXPECT user=monetdb
ACCEPT monetdb:///?user=me&password=?
EXPECT user=me
EXPECT password=?
```

### language

```test
EXPECT language=sql
ACCEPT monetdb:///?language=msql
EXPECT language=msql
ACCEPT monetdb:///?language=sql
EXPECT language=sql
```

### autocommit

```test
ACCEPT monetdb:///?autocommit=true
EXPECT autocommit=true
ACCEPT monetdb:///?autocommit=on
EXPECT autocommit=true
ACCEPT monetdb:///?autocommit=yes
EXPECT autocommit=true
```

```test
ACCEPT monetdb:///?autocommit=false
EXPECT autocommit=false
ACCEPT monetdb:///?autocommit=off
EXPECT autocommit=false
ACCEPT monetdb:///?autocommit=no
EXPECT autocommit=false
```

```test
REJECT monetdb:///?autocommit=
REJECT monetdb:///?autocommit=banana
REJECT monetdb:///?autocommit=0
REJECT monetdb:///?autocommit=1
```

### schema, timezone

Must be accepted, no constraints on content

```test
EXPECT schema=
ACCEPT monetdb:///?schema=foo
EXPECT schema=foo
ACCEPT monetdb:///?schema=
EXPECT schema=
ACCEPT monetdb:///?schema=foo
```

```test
ACCEPT monetdb:///?timezone=0
EXPECT timezone=0
ACCEPT monetdb:///?timezone=120
EXPECT timezone=120
ACCEPT monetdb:///?timezone=-120
EXPECT timezone=-120
REJECT monetdb:///?timezone=banana
REJECT monetdb:///?timezone=
```

### replysize and fetchsize

Note we never check `EXPECT fetchsize=`, it doesn't exist.

```test
ACCEPT monetdb:///?replysize=150
EXPECT replysize=150
ACCEPT monetdb:///?fetchsize=150
EXPECT replysize=150
ACCEPT monetdb:///?fetchsize=100&replysize=200
EXPECT replysize=200
ACCEPT monetdb:///?replysize=100&fetchsize=200
EXPECT replysize=200
REJECT monetdb:///?replysize=
REJECT monetdb:///?fetchsize=
```

### binary

```test
EXPECT binary=on
EXPECT connect_binary=65535
```

```test
ACCEPT monetdb:///?binary=on
EXPECT connect_binary=65535

ACCEPT monetdb:///?binary=yes
EXPECT connect_binary=65535

ACCEPT monetdb:///?binary=true
EXPECT connect_binary=65535

ACCEPT monetdb:///?binary=yEs
EXPECT connect_binary=65535
```

```test
ACCEPT monetdb:///?binary=off
EXPECT connect_binary=0

ACCEPT monetdb:///?binary=no
EXPECT connect_binary=0

ACCEPT monetdb:///?binary=false
EXPECT connect_binary=0
```

```test
ACCEPT monetdb:///?binary=0
EXPECT connect_binary=0

ACCEPT monetdb:///?binary=5
EXPECT connect_binary=5

ACCEPT monetdb:///?binary=0100
EXPECT connect_binary=100
```

```test
REJECT monetdb:///?binary=
REJECT monetdb:///?binary=-1
REJECT monetdb:///?binary=1.0
REJECT monetdb:///?binary=banana
```

### unknown parameters

```test
REJECT monetdb:///?banana=bla
```

```test
ACCEPT monetdb:///?ban_ana=bla
ACCEPT monetdb:///?hash=sha1
ACCEPT monetdb:///?debug=true
ACCEPT monetdb:///?logfile=banana
```

Unfortunately we can't easily test that it won't allow us
to SET banana.

```test
SET ban_ana=bla
SET hash=sha1
SET debug=true
SET logfile=banana
```

## Combining sources

The defaults have been tested in the previous section.

Rule: If there is overlap, later sources take precedence.

```test
SET schema=a
ACCEPT monetdb:///db1?schema=b
EXPECT schema=b
EXPECT database=db1
EXPECT tls=off
ACCEPT monetdbs:///db2?schema=c
EXPECT tls=on
EXPECT database=db2
EXPECT schema=c
```

Rule: a source that sets user must set password or clear.

```skiptest
ACCEPT monetdb:///?user=foo
EXPECT user=foo
EXPECT password=
SET password=banana
EXPECT user=foo
EXPECT password=banana
SET user=bar
EXPECT password=
```

Rule: fetchsize is an alias for replysize, last occurrence counts

```test
SET replysize=200
ACCEPT monetdb:///?fetchsize=400
EXPECT replysize=400
ACCEPT monetdb:///?replysize=500&fetchsize=600
EXPECT replysize=600
```

```test
SET replysize=200
SET fetchsize=300
EXPECT replysize=300
```

Rule: parsing a URL sets all of tls, host, port and database
even if left out of the URL

```test
SET tls=on
SET host=banana
SET port=12345
SET database=foo
SET timezone=120
ACCEPT monetdb:///
EXPECT tls=off
EXPECT host=
EXPECT port=-1
EXPECT database=
```

```test
SET tls=on
SET host=banana
SET port=12345
SET database=foo
SET timezone=120
ACCEPT monetdb://dbhost/dbdb
EXPECT tls=off
EXPECT host=dbhost
EXPECT port=-1
EXPECT database=dbdb
```

Careful around passwords

```test
SET user=alan
SET password=turing
ACCEPT monetdbs:///
EXPECT user=alan
EXPECT password=turing
```

```test
SET user=alan
SET password=turing
ACCEPT monetdbs:///?user=mathison
EXPECT user=mathison
EXPECT password=
```

The rule is, "if **user** is set", not "if **user** is changed".

```test
SET user=alan
SET password=turing
ACCEPT monetdbs:///?user=alan
EXPECT user=alan
EXPECT password=
```

## URL syntax

General form

```test
REJECT monetdb:
REJECT monetdbs:
REJECT monetdb:/
REJECT monetdbs:/
ACCEPT monetdb://
ACCEPT monetdbs://
ACCEPT monetdb:///
ACCEPT monetdbs:///
```


```test
ACCEPT monetdb://host:12345/db1/schema2/table3?user=mr&password=bean
EXPECT tls=off
EXPECT host=host
EXPECT port=12345
EXPECT database=db1
EXPECT tableschema=schema2
EXPECT table=table3
EXPECT user=mr
EXPECT password=bean
```

Also, TLS and percent-escapes

```test
ACCEPT monetdbs://h%6Fst:12345/db%31/schema%32/table%33?user=%6Dr&p%61ssword=bean
EXPECT tls=on
EXPECT host=host
EXPECT port=12345
EXPECT database=db1
EXPECT tableschema=schema2
EXPECT table=table3
EXPECT user=mr
EXPECT password=bean
```

Port number

```test
REJECT monetdb://banana:0/
REJECT monetdb://banana:-1/
REJECT monetdb://banana:65536/
REJECT monetdb://banana:100000/
```

Trailing slash can be left off

```test
ACCEPT monetdb://host?user=claude&password=m%26ms
EXPECT host=host
EXPECT user=claude
EXPECT password=m&ms
```

Error to set tls, host, port, database, tableschema and table as query parameters.

```test
REJECT monetdb://foo:1/bar?tls=off
REJECT monetdb://foo:1/bar?host=localhost
REJECT monetdb://foo:1/bar?port=12345
REJECT monetdb://foo:1/bar?database=allmydata
REJECT monetdb://foo:1/bar?tableschema=banana
REJECT monetdb://foo:1/bar?table=tabularity
```

Last wins, already tested elsewhere but for completeness

```test
ACCEPT monetdbs:///?timezone=10&timezone=20
EXPECT timezone=20
```

Interesting case: setting user must clear the password but does
that also happen with repetitions within a URL?
Not sure. For the time being, no. This makes it easier for
situations where for example the query parameters come in
alphabetical order

```test
ACCEPT monetdb:///?user=foo&password=banana&user=bar
EXPECT user=bar
EXPECT password=banana
```

Similar but even simpler: user comes after password but does not
clear it.

```test
ACCEPT monetdb:///?password=pw&user=foo
EXPECT user=foo
EXPECT password=pw
```

Ways of writing booleans and the binary property have already been tested above.

Ip numbers:

```test
ACCEPT monetdb://192.168.1.1:12345/foo
EXPECT connect_unix=
EXPECT connect_tcp=192.168.1.1
EXPECT database=foo
```

```test
ACCEPT monetdb://[::1]:12345/foo
EXPECT connect_unix=
EXPECT connect_tcp=::1
EXPECT database=foo
```

```test
REJECT monetdb://[::1]banana/foo
```

Bad percent escapes:

```test
REJECT monetdb:///m%xxbad
```


## Interpreting

Testing the validity constraints.
They apply both when parsing a URL and with ad-hoc settings.

Rule 1, the type constraints, has already been tested in [Section Parameter
tests](#parameter-tests).

Rule 2, interaction between **sock** and **host** is tested below in
[the next subsection](#interaction-between-tls-host-sock-and-database).

Rule 3, about **binary**, is tested in [Subsection Binary](#binary).

Rule 4, **sock** vs **tls** is tested below in [the next
subsection](#interaction-between-tls-host-sock-and-database).

Rule 5, **certhash** syntax, is tested in [Subsection Certhash](#certhash).

Rule 6, **tls** **cert** **certhash** interaction, is tested
in [Subsection Interaction between tls, cert and certhash](#interaction-between-tls-cert-and-certhash).

Rule 7, **database**, **tableschema**, **table** is tested in [Subsection
Database, schema, table name
constraints](#database-schema-table-name-constraints).

Here are some tests for Rule 8, **port**.

```test
SET port=1
EXPECT valid=true
SET port=10
EXPECT valid=true
SET port=000010
EXPECT valid=true
SET port=65535
EXPECT valid=true
SET port=-1
EXPECT valid=true
SET port=0
EXPECT valid=false
SET port=-2
EXPECT valid=false
SET port=65536
EXPECT valid=false
```

### Database, schema, table name constraints

```test
SET database=
EXPECT valid=yes
SET database=banana
EXPECT valid=yes
SET database=UPPERCASE
EXPECT valid=yes
SET database=_under_score_
EXPECT valid=yes
SET database=with-dashes
EXPECT valid=yes
```

```test
SET database=with/slash
EXPECT valid=no
SET database=-flag
EXPECT valid=no
SET database=with space
EXPECT valid=no
SET database=with.period
EXPECT valid=yes
SET database=with%percent
EXPECT valid=no
SET database=with!exclamation
EXPECT valid=no
SET database=with?questionmark
EXPECT valid=no
```

```test
SET database=demo
SET tableschema=
EXPECT valid=yes
SET tableschema=banana
EXPECT valid=yes
SET tableschema=UPPERCASE
EXPECT valid=yes
SET tableschema=_under_score_
EXPECT valid=yes
SET tableschema=with-dashes
EXPECT valid=yes
```

```test
SET database=demo
SET tableschema=with/slash
EXPECT valid=no
SET tableschema=-flag
EXPECT valid=no
SET tableschema=with space
EXPECT valid=no
SET tableschema=with.period
EXPECT valid=yes
SET tableschema=with%percent
EXPECT valid=no
SET tableschema=with!exclamation
EXPECT valid=no
SET tableschema=with?questionmark
EXPECT valid=no
```

```test
SET database=demo
SET tableschema=sys
SET table=
EXPECT valid=yes
SET table=banana
EXPECT valid=yes
SET table=UPPERCASE
EXPECT valid=yes
SET table=_under_score_
EXPECT valid=yes
SET table=with-dashes
EXPECT valid=yes
```

```test
SET database=demo
SET tableschema=sys
SET table=with/slash
EXPECT valid=no
SET table=-flag
EXPECT valid=no
SET table=with space
EXPECT valid=no
SET table=with.period
EXPECT valid=yes
SET table=with%percent
EXPECT valid=no
SET table=with!exclamation
EXPECT valid=no
SET table=with?questionmark
EXPECT valid=no
```

### Interaction between tls, cert and certhash

```test
ACCEPT monetdbs:///?cert=/a/path
EXPECT connect_tls_verify=cert
ACCEPT monetdbs:///?certhash=sha256:aa
EXPECT connect_tls_verify=hash
ACCEPT monetdbs:///?cert=/a/path&certhash=sha256:aa
EXPECT connect_tls_verify=hash
REJECT monetdb:///?cert=/a/path
REJECT monetdb:///?certhash=sha256:aa
```

```test
SET tls=off
SET cert=
SET certhash=
EXPECT valid=yes
EXPECT connect_tls_verify=
```

```test
SET tls=off
SET cert=
SET certhash=sha256:abcdef
EXPECT valid=no
```

```test
SET tls=off
SET cert=/foo
SET certhash=
EXPECT valid=no
```

```test
SET tls=off
SET cert=/foo
SET certhash=sha256:abcdef
EXPECT valid=no
```

```test
SET tls=on
SET cert=
SET certhash=
EXPECT valid=yes
EXPECT connect_tls_verify=system
```

```test
SET tls=on
SET cert=
SET certhash=sha256:abcdef
EXPECT valid=yes
EXPECT connect_tls_verify=hash
```

```test
SET tls=on
SET cert=/foo
SET certhash=
EXPECT valid=yes
EXPECT connect_tls_verify=cert
```

```test
SET tls=on
SET cert=/foo
SET certhash=sha256:abcdef
EXPECT valid=yes
EXPECT connect_tls_verify=hash
```


### Interaction between tls, host, sock and database

The following tests should exhaustively test all variants.

```test
ACCEPT monetdb:///
EXPECT connect_scan=off
EXPECT connect_unix=/tmp/.s.monetdb.50000
EXPECT connect_tcp=localhost
```

```test
ACCEPT monetdb:///?sock=/a/path
EXPECT connect_scan=off
EXPECT connect_unix=/a/path
EXPECT connect_tcp=
```

```test
ACCEPT monetdb://localhost/
EXPECT connect_scan=off
EXPECT connect_unix=/tmp/.s.monetdb.50000
EXPECT connect_tcp=localhost
```

```test
ACCEPT monetdb://localhost/?sock=/a/path
EXPECT connect_scan=off
EXPECT connect_unix=/a/path
EXPECT connect_tcp=
```

```test
ACCEPT monetdb://localhost./
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=localhost
```

```test
REJECT monetdb://localhost./?sock=/a/path
```

```test
ACCEPT monetdb://not.localhost/
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=not.localhost
```

```test
REJECT monetdb://not.localhost/?sock=/a/path
```

```test
ACCEPT monetdbs:///
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=localhost
```

```test
REJECT monetdbs:///?sock=/a/path
```

```test
ACCEPT monetdbs://localhost/
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=localhost
```

```test
REJECT monetdbs://localhost/?sock=/a/path
```

```test
ACCEPT monetdbs://localhost./
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=localhost
```

```test
REJECT monetdbs://localhost./?sock=/a/path
```

```test
ACCEPT monetdbs://not.localhost/
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=not.localhost
```

```test
REJECT monetdbs://not.localhost/?sock=/a/path
```

```test
ACCEPT monetdb:///demo
EXPECT connect_scan=on
```

```test
ACCEPT monetdb:///demo?sock=/a/path
EXPECT connect_scan=off
EXPECT connect_unix=/a/path
EXPECT connect_tcp=
```

```test
ACCEPT monetdb://localhost/demo
EXPECT connect_scan=on
```

```test
ACCEPT monetdb://localhost/demo?sock=/a/path
EXPECT connect_scan=off
EXPECT connect_unix=/a/path
EXPECT connect_tcp=
```

```test
ACCEPT monetdb://localhost./demo
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=localhost
```

```test
REJECT monetdb://localhost./?sock=/a/path
```

```test
ACCEPT monetdb://not.localhost/demo
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=not.localhost
```

```test
REJECT monetdb://not.localhost/?sock=/a/path
```

```test
ACCEPT monetdbs:///demo
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=localhost
```

```test
REJECT monetdbs:///?sock=/a/path
```

```test
ACCEPT monetdbs://localhost/demo
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=localhost
```

```test
REJECT monetdbs://localhost/?sock=/a/path
```

```test
ACCEPT monetdbs://localhost./demo
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=localhost
```

```test
REJECT monetdbs://localhost./?sock=/a/path
```

```test
ACCEPT monetdbs://not.localhost/demo
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=not.localhost
```

```test
REJECT monetdbs://not.localhost/?sock=/a/path
```

### sock and sockdir

Sockdir only applies to implicit Unix domain sockets,
not to ones that are given explicitly

```test
EXPECT sockdir=/tmp
EXPECT port=-1
EXPECT host=
EXPECT connect_unix=/tmp/.s.monetdb.50000
SET sockdir=/somewhere/else
EXPECT connect_unix=/somewhere/else/.s.monetdb.50000
SET port=12345
EXPECT connect_unix=/somewhere/else/.s.monetdb.12345
```

## Legacy URL's

```test
REJECT mapi:
REJECT mapi:monetdb
REJECT mapi:monetdb:
REJECT mapi:monetdb:/
```

```test
ACCEPT mapi:monetdb://monet.db:12345/demo
EXPECT host=monet.db
EXPECT port=12345
EXPECT database=demo
EXPECT tls=off
EXPECT language=sql
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=monet.db
```

This one is the golden standard:

```test
ACCEPT mapi:monetdb://localhost:12345/demo
EXPECT host=localhost
EXPECT port=12345
EXPECT database=demo
EXPECT tls=off
EXPECT language=sql
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=localhost
```

```test
ACCEPT mapi:monetdb://localhost:12345/
EXPECT host=localhost
EXPECT port=12345
EXPECT database=
EXPECT tls=off
EXPECT language=sql
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=localhost
```

```test
ACCEPT mapi:monetdb://localhost:12345
EXPECT host=localhost
EXPECT port=12345
EXPECT database=
EXPECT tls=off
EXPECT language=sql
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=localhost
```

```test
ACCEPT mapi:monetdb://localhost/demo
EXPECT connect_scan=false
EXPECT connect_unix=
EXPECT connect_tcp=localhost
EXPECT connect_port=50000
```

```test
ACCEPT mapi:monetdb://:12345/demo
EXPECT host=
EXPECT port=12345
EXPECT database=demo
EXPECT tls=off
EXPECT language=sql
EXPECT connect_scan=off
EXPECT connect_unix=/tmp/.s.monetdb.12345
EXPECT connect_tcp=localhost
```

```test
ACCEPT mapi:monetdb://127.0.0.1:12345/demo
EXPECT host=127.0.0.1
EXPECT port=12345
EXPECT database=demo
EXPECT tls=off
EXPECT language=sql
EXPECT connect_scan=off
EXPECT connect_unix=
EXPECT connect_tcp=127.0.0.1
```

Database parameter allowed, overrides path

```test
ACCEPT mapi:monetdb://localhost:12345/demo?database=foo
EXPECT database=foo
```

User, username and password parameters are ignored:

```test
SET user=alan
SET password=turing
ACCEPT mapi:monetdb://localhost:12345/demo?user=foo
EXPECT user=alan
EXPECT password=turing
ACCEPT mapi:monetdb://localhost:12345/demo?password=foo
EXPECT user=alan
EXPECT password=turing
```

Pymonetdb used to accept user name and password before
the host name and should continue to do so.


```test
ONLY pymonetdb
SET user=alan
SET password=turing
ACCEPT mapi:monetdb://foo:bar@localhost:12345/demo
EXPECT user=foo
EXPECT password=bar
ACCEPT mapi:monetdb://banana@localhost:12345/demo
EXPECT user=banana
EXPECT password=
```

```test
NOT pymonetdb
SET user=alan
SET password=turing
REJECT mapi:monetdb://foo:bar@localhost:12345/demo
REJECT mapi:monetdb://banana@localhost:12345/demo
```

Unix domain sockets

```test
ACCEPT mapi:monetdb:///path/to/sock?database=demo
EXPECT host=
EXPECT sock=/path/to/sock
EXPECT port=-1
EXPECT database=demo
EXPECT tls=off
EXPECT language=sql
EXPECT connect_unix=/path/to/sock
EXPECT connect_tcp=
```

```test
ACCEPT mapi:monetdb:///path/to/sock
EXPECT host=
EXPECT sock=/path/to/sock
EXPECT port=-1
EXPECT database=
EXPECT tls=off
EXPECT language=sql
EXPECT connect_unix=/path/to/sock
EXPECT connect_tcp=
```

Corner case: both libmapi and pymonetdb interpret this as an attempt
to connect to socket '/'.  This will fail of course but the URL does parse

```test
ACCEPT mapi:monetdb:///
EXPECT host=
EXPECT sock=/
EXPECT connect_unix=/
EXPECT connect_tcp=
```

```test
NOT pymonetdb
PARSE mapi:monetdb:///foo:bar@path/to/sock
EXPECT sock=/foo:bar@path/to/sock
REJECT mapi:monetdb://foo:bar@/path/to/sock
```

```test
ONLY pymonetdb
SET user=alan
SET password=turing
ACCEPT mapi:monetdb://foo:bar@/path/to/sock
EXPECT host=
EXPECT sock=/path/to/sock
EXPECT user=foo
EXPECT password=bar
EXPECT connect_unix=/path/to/sock
EXPECT connect_tcp=
```

```test
ONLY pymonetdb
SET user=alan
SET password=turing
ACCEPT mapi:monetdb://foo@/path/to/sock
EXPECT host=
EXPECT sock=/path/to/sock
EXPECT user=foo
EXPECT password=
EXPECT connect_unix=/path/to/sock
EXPECT connect_tcp=
```

Language is supported

```test
SET language=sql
ACCEPT mapi:monetdb://localhost:12345?language=mal
EXPECT host=localhost
EXPECT sock=
EXPECT language=mal
SET language=sql
ACCEPT mapi:monetdb:///path/to/sock?language=mal
EXPECT host=
EXPECT sock=/path/to/sock
EXPECT language=mal
```

No percent decoding is performed

```test
REJECT mapi:monetdb://localhost:1234%35/demo
PARSE mapi:monetdb://loc%61lhost:12345/d%61tabase
EXPECT host=loc%61lhost
EXPECT database=d%61tabase
EXPECT valid=no
```

```test
PARSE mapi:monetdb://localhost:12345/db?database=b%61r&language=m%61l
EXPECT database=b%61r
EXPECT language=m%61l
EXPECT valid=no
```

l%61nguage is an unknown parameter, thus ignored not rejected

```test
SET language=sql
ACCEPT mapi:monetdb://localhost:12345/db?l%61nguage=mal
EXPECT language=sql
ACCEPT mapi:monetdb://localhost:12345/db?_l%61nguage=mal
```


## Merovingian URLs

These occur in redirects.
Leave host, port and database are not cleared the way the are
for `monetdb:`, `monetdbs:` and `mapi:monetdb:` URLs.

```test
SET host=banana
SET port=123
SET tls=on
SET sock=/tmp/sock
SET database=dummy
PARSE mapi:merovingian://proxy
EXPECT host=banana
EXPECT port=123
EXPECT tls=on
EXPECT sock=/tmp/sock
EXPECT database=dummy
```

```test
SET host=banana
SET port=123
SET tls=on
SET sock=/tmp/sock
SET database=dummy
PARSE mapi:merovingian://proxy?
EXPECT host=banana
EXPECT port=123
EXPECT tls=on
EXPECT sock=/tmp/sock
EXPECT database=dummy
```

```test
SET host=banana
SET port=123
SET tls=on
SET sock=/tmp/sock
SET database=dummy
PARSE mapi:merovingian://proxy?database=yeah&unknown=unknown
EXPECT host=banana
EXPECT port=123
EXPECT tls=on
EXPECT sock=/tmp/sock
EXPECT database=yeah
```