TypeInfo tests

This commit is contained in:
Daylon Wilkins
2020-02-15 21:39:00 -08:00
committed by Daylon Wilkins
parent 329fd907ac
commit 080aeea015
78 changed files with 4242 additions and 0 deletions

162
bats/back-compat.bats Normal file
View File

@@ -0,0 +1,162 @@
#!/usr/bin/env bats
load $BATS_TEST_DIRNAME/helper/common.bash
setup() {
setup_common
cp -a $BATS_TEST_DIRNAME/helper/testdata/. ./
}
teardown() {
teardown_common
}
@test "back-compat: data check" {
for testdir in */; do
cd "$testdir"
run dolt status
[ "$status" -eq "0" ]
run dolt branch
[ "$status" -eq "0" ]
[[ "$output" =~ "master" ]] || false
[[ "$output" =~ "conflict" ]] || false
[[ "$output" =~ "newcolumn" ]] || false
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`pk\` BIGINT NOT NULL COMMENT 'tag:0'" ]] || false
[[ "$output" =~ "\`a\` LONGTEXT COMMENT 'tag:694'" ]] || false
[[ "$output" =~ "\`b\` DATETIME COMMENT 'tag:2902'" ]] || false
run dolt sql -q "select * from abc order by pk asc"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
[[ "${lines[3]}" =~ " data " ]] || false
[[ "${lines[3]}" =~ " 2020-01-13 20:45:18.53558 " ]] || false
dolt checkout conflict
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`pk\` BIGINT NOT NULL COMMENT 'tag:0'" ]] || false
[[ "$output" =~ "\`a\` LONGTEXT COMMENT 'tag:694'" ]] || false
[[ "$output" =~ "\`b\` DATETIME COMMENT 'tag:2902'" ]] || false
run dolt sql -q "select * from abc order by pk asc"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
[[ "${lines[3]}" =~ " data " ]] || false
[[ "${lines[3]}" =~ " 2020-01-13 20:45:18.53558 " ]] || false
[[ "${lines[4]}" =~ " 2 " ]] || false
[[ "${lines[4]}" =~ " something " ]] || false
[[ "${lines[4]}" =~ " 2020-01-14 20:48:37.13061 " ]] || false
dolt checkout newcolumn
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`pk\` BIGINT NOT NULL COMMENT 'tag:0'" ]] || false
[[ "$output" =~ "\`a\` LONGTEXT COMMENT 'tag:694'" ]] || false
[[ "$output" =~ "\`b\` DATETIME COMMENT 'tag:2902'" ]] || false
[[ "$output" =~ "\`c\` BIGINT UNSIGNED COMMENT 'tag:4657'" ]] || false
run dolt sql -q "select * from abc order by pk asc"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
[[ "${lines[3]}" =~ " data " ]] || false
[[ "${lines[3]}" =~ " 2020-01-13 20:45:18.53558 " ]] || false
[[ "${lines[3]}" =~ " 2133" ]] || false
[[ "${lines[4]}" =~ " 2 " ]] || false
[[ "${lines[4]}" =~ " something " ]] || false
[[ "${lines[4]}" =~ " 2020-01-13 20:48:37.13061 " ]] || false
[[ "${lines[4]}" =~ " 1132020" ]] || false
cd ..
done
}
@test "back-compat: table operations" {
for testdir in */; do
cd "$testdir"
run dolt table cp abc copy
[ "$status" -eq "0" ]
run dolt table mv abc move
[ "$status" -eq "0" ]
run dolt ls
[ "$status" -eq "0" ]
[[ "$output" =~ "copy" ]] || false
[[ "$output" =~ "move" ]] || false
cd ..
done
}
@test "back-compat: adding commits" {
for testdir in */; do
cd "$testdir"
run dolt sql -q "insert into abc values (2, 'text', '2020-01-15 20:49:22.28427')"
[ "$status" -eq "0" ]
run dolt add .
[ "$status" -eq "0" ]
run dolt commit -m "Add value during test"
[ "$status" -eq "0" ]
run dolt sql -q "select * from abc order by pk asc"
[ "$status" -eq "0" ]
[[ "${lines[4]}" =~ " 2 " ]] || false
[[ "${lines[4]}" =~ " text " ]] || false
[[ "${lines[4]}" =~ " 2020-01-15 20:49:22.28427 " ]] || false
dolt checkout newcolumn
dolt checkout -b testaddcommit
run dolt sql -q "insert into abc values (3, 'text', '2020-01-15 20:49:22.28427', 9241)"
[ "$status" -eq "0" ]
run dolt add .
[ "$status" -eq "0" ]
run dolt commit -m "Add value during test"
[ "$status" -eq "0" ]
run dolt sql -q "select * from abc order by pk asc"
[ "$status" -eq "0" ]
[[ "${lines[5]}" =~ " 3 " ]] || false
[[ "${lines[5]}" =~ " text " ]] || false
[[ "${lines[5]}" =~ " 2020-01-15 20:49:22.28427 " ]] || false
[[ "${lines[5]}" =~ " 9241 " ]] || false
cd ..
done
}
@test "back-compat: merging" {
for testdir in */; do
cd "$testdir"
run dolt merge newcolumn
[ "$status" -eq "0" ]
[[ "$output" =~ "Fast-forward" ]] || false
cd ..
done
}
@test "back-compat: resolving conflicts" {
for testdir in */; do
cd "$testdir"
dolt checkout conflict
run dolt merge newcolumn
[ "$status" -eq "0" ]
[[ "$output" =~ "CONFLICT" ]] || false
run dolt conflicts cat abc
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " ours " ]] || false
[[ "${lines[3]}" =~ " 2 " ]] || false
[[ "${lines[3]}" =~ " something " ]] || false
[[ "${lines[3]}" =~ " 2020-01-14 20:48:37.13061 " ]] || false
[[ "${lines[3]}" =~ " <NULL> " ]] || false
[[ "${lines[4]}" =~ " theirs " ]] || false
[[ "${lines[4]}" =~ " 2 " ]] || false
[[ "${lines[4]}" =~ " something " ]] || false
[[ "${lines[4]}" =~ " 2020-01-13 20:48:37.13061 " ]] || false
[[ "${lines[4]}" =~ " 1132020 " ]] || false
run dolt conflicts resolve --theirs abc
[ "$status" -eq "0" ]
run dolt add .
[ "$status" -eq "0" ]
run dolt commit -m "Merged newcolumn into conflict"
[ "$status" -eq "0" ]
run dolt sql -q "select * from abc order by pk asc"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
[[ "${lines[3]}" =~ " data " ]] || false
[[ "${lines[3]}" =~ " 2020-01-13 20:45:18.53558 " ]] || false
[[ "${lines[3]}" =~ " 2133" ]] || false
[[ "${lines[4]}" =~ " 2 " ]] || false
[[ "${lines[4]}" =~ " something " ]] || false
[[ "${lines[4]}" =~ " 2020-01-13 20:48:37.13061 " ]] || false
[[ "${lines[4]}" =~ " 1132020" ]] || false
cd ..
done
}

View File

@@ -0,0 +1 @@
{}

View File

View File

@@ -0,0 +1 @@
4:__LD_1__:kgbtojhb52j8ni3hfrdnbntd2um8aetv:j88k1vjjvval95ejvp6ooq0vefc68h5c:m3sn7rmfc0lbis3codosl1k46hpv0kod:3:ml7hl70ar993tc32gla4ttjar0ogka86:1:5im08tb1mu140r7kvtrd04u8ub5qk607:4:ie2tcnurro57vl8urvucbjdrmmf9bo0h:1:9guvpb6l55h1t9aqaa9b7qnp1dnnelkd:1:k3ksuke2vcb2hgatpdqbhildb8raab5p:1:89knkh4sejb7tf05gqq01osftlbsmdq1:5:glc2mu652o0pt893a79j30tc6kgvk453:1:eiit9a47igil0id02vhgpq4g72ga3dha:1:jji5lv8nq265dpk6r11ug3gb6ih81hdr:1:c8dirve58o6npl3aufbupn3c2pt55el4:4:6oc2i2n9ln25n8go78dalvo3e9er9mg3:1:fkes7bk2bl0p9cvfgk3dd7uf6p4cqcm1:1:ojdo9hafo3mvlko0cefqcom7os26utln:1:c8a3b64elue3121ng0rgeagcnf48fbat:1:iellg8am40vu2tf61hbe7i0anhm76gtv:2:ju51cbttj99itbsbk2svu7sij2tu4rhl:4:9ibrf56gr6gsgr7cpnda4au9o0vd0412:2:srlc19tj78ldn4hbb8duso90i1vugc59:1:s69lvejsvg9so3l2nsquavmbai4dmu03:4:7er6962c841ghn8j0a357ujde9daq3mu:2:og4gt15c913id9e4iv7bcobjkn6aqn8d:1:7vu480853r3b0hitt89l7gc3r854fb53:1:rcksm0pvt2fop4deb2tf881mo0vj4ih8:1:0kl39j0i7gljemj93loojdhdbsj9lb36:1:u62g6ma6evirqjb11i0up0p1hppb50ou:1:4bujnjuatdli0klda7ucot0tl836jujt:1:m297l94np7ub1bp8irhpf3eta6bpegr8:4:rrbqpqt3l59s17rbva7pjrqhitbe4cc2:1:6739m2utlhl1k98f4o2fqmgtm12ino4t:1:di7sdosugcarnn353e8ldbnlts9v42s5:1:09hv7tllti9b3hfi7u5m3e7lpbne390a:1:qqc5268agbqc0nqdud6gn7m202teffnm:4:g2slg3mhtfb5m2tk00t8mor5lkboqj2m:1:ug6l7o53ntp50f252u65cj96om411v14:4:ca9rtjbjd7n5pkodo3rsl6bon0s8qe4j:1:q5eq2e7gn1osgqg6bdqctgi7o7lapsik:1:tmie2h7f80pblg0ojfk0v50qu8s97mpa:4:frc0ef452fhh97o534e7lol2b427lk56:1:es7vlqed0665gq9es3ns2uqeh75bkerc:4:os1po1dclurjkflegl02usl2r8rkg2cq:1:1rnurg4no9s6s23mdq8vvfmj0cik47db:1:oarahke38ufh3tmnfpafuvb51dfbhgmh:2:a9307merr53dd71vj459m7qo6rk435na:1:ag7kv5tuc4jvovmas7r5kel32dd94g86:1:csopsqdj2urggh85gbsfth4c9lf4r8vb:1:3dsltc9vis2m6o89bv0dh482pfme30ss:1:1nrr0bod1960bccqc6c2med68hod5gc7:2:miv7sdaoglrgfs2rgafm77kr6h9cbgvn:1:hgsmoadjsib12ml6e05or4q5urv9lt7l:4:a8hqijvam2c6r9qvbffsdj5r55bis0mn:2:naromh9oel8c6dmmg6lvg61ot3gvomkv:1:kmjfnt24t2vf8e58u3r5insr7tfohm2e:1

View File

@@ -0,0 +1,8 @@
{
"head": "refs/heads/master",
"staged": "hlgmnafjvlg8curcjc14dok7k1h3mqci",
"working": "hlgmnafjvlg8curcjc14dok7k1h3mqci",
"merge": null,
"remotes": null,
"branches": null
}

75
bats/helper/testdata/20200113/README.md vendored Normal file
View File

@@ -0,0 +1,75 @@
## Overview
This is test data that captures a repository on January 13, 2020. This may be used to verify that any serialization/deserialization changes are compatible with people's pre-existing data.
# Branch master
## Schema
```
CREATE TABLE `abc` (
`pk` BIGINT NOT NULL COMMENT 'tag:0',
`a` LONGTEXT COMMENT 'tag:694',
`b` DATETIME COMMENT 'tag:2902',
PRIMARY KEY (`pk`)
);
```
## Data
```
+----+------+---------------------------+
| pk | a | b |
+----+------+---------------------------+
| 1 | data | 2020-01-13 20:45:18.53558 |
+----+------+---------------------------+
```
# Branch conflict
## Schema
```
CREATE TABLE `abc` (
`pk` BIGINT NOT NULL COMMENT 'tag:0',
`a` LONGTEXT COMMENT 'tag:694',
`b` DATETIME COMMENT 'tag:2902',
PRIMARY KEY (`pk`)
);
```
## Data
```
+----+-----------+---------------------------+
| pk | a | b |
+----+-----------+---------------------------+
| 1 | data | 2020-01-13 20:45:18.53558 |
| 2 | something | 2020-01-14 20:48:37.13061 |
+----+-----------+---------------------------+
```
# Branch newcolumn
## Schema
```
CREATE TABLE `abc` (
`pk` BIGINT NOT NULL COMMENT 'tag:0',
`a` LONGTEXT COMMENT 'tag:694',
`b` DATETIME COMMENT 'tag:2902',
`c` BIGINT UNSIGNED COMMENT 'tag:4657',
PRIMARY KEY (`pk`)
);
```
## Data
```
+----+-----------+---------------------------+---------+
| pk | a | b | c |
+----+-----------+---------------------------+---------+
| 1 | data | 2020-01-13 20:45:18.53558 | 2133 |
| 2 | something | 2020-01-13 20:48:37.13061 | 1132020 |
+----+-----------+---------------------------+---------+
```

34
bats/helper/testdata/README.md vendored Normal file
View File

@@ -0,0 +1,34 @@
## Overview
This is a collection of repositories that are to be created whenever the on-disk format is changed in any way. This way, we can catch some errors that may arise from the new changes not properly reading the older formats. The test file is `back-compat.bats`, which loops over each directory and runs a set of basic tests to ensure that the latest code can both read and modify pre-existing data. Each repository will have the same branch names and same general schema.
## Steps
Whenever the format is updated, a new repository should be created from scratch with the new format. The following steps may be used to create a compatible repository:
```bash
dolt init
"UPDATE README.md"
dolt add .
dolt commit -m "Initialize data repository"
dolt sql -q "CREATE TABLE abc(pk BIGINT PRIMARY KEY, a LONGTEXT COMMENT 'tag:694', b DATETIME COMMENT 'tag:2902')"
dolt add .
dolt commit -m "Created table abc"
dolt sql -q "INSERT INTO abc VALUES (1, 'data', '2020-01-13 20:45:18.53558')"
dolt add .
dolt commit -m "Initial data"
dolt checkout -b conflict
dolt sql -q "INSERT INTO abc VALUES (2, 'something', '2020-01-14 20:48:37.13061')"
dolt add .
dolt commit -m "Added something row"
dolt checkout master
dolt checkout -b newcolumn
dolt sql -q "ALTER TABLE abc ADD COLUMN c BIGINT UNSIGNED COMMENT 'tag:4657'"
dolt sql -q "UPDATE abc SET c = 2133 WHERE c IS NULL"
dolt sql -q "INSERT INTO abc VALUES (2, 'something', '2020-01-13 20:48:37.13061', 1132020)"
dolt add .
dolt commit -m "Added something row and column c"
dolt checkout master
```
The generated `LICENSE.md` may be removed, and the `README.md` should be updated to reflect the information contained in the repository (this is assumed to be done immediately after `dolt init`). It is required for the repository to be on the `master` branch, as the tests assume this starting point.

995
bats/types.bats Normal file
View File

@@ -0,0 +1,995 @@
#!/usr/bin/env bats
load $BATS_TEST_DIRNAME/helper/common.bash
setup() {
setup_common
}
teardown() {
teardown_common
}
@test "types: BIGINT" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v BIGINT COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` BIGINT COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 4611686018427387903);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 4611686018427387903 " ]] || false
dolt sql -q "UPDATE test SET v=v*2+1 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 9223372036854775807 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 40000000000000000000);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, -40000000000000000000);"
[ "$status" -eq "1" ]
}
@test "types: BIGINT UNSIGNED" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v BIGINT UNSIGNED COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` BIGINT UNSIGNED COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 9223372036854775807);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 9223372036854775807 " ]] || false
skip "We can't parse values above the INT64 max in go-mysql-server yet"
dolt sql -q "UPDATE test SET v=v*2+1 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 18446744073709551615 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 40000000000000000000);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, -1);"
[ "$status" -eq "1" ]
}
@test "types: BINARY(10)" {
skip "This is not yet persisted in dolt"
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v BINARY(10) COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` BINARY(10) COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'abcdefg');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " abcdefg " ]] || false
dolt sql -q "UPDATE test SET v='1234567890' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1234567890 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, '12345678901');"
[ "$status" -eq "1" ]
}
@test "types: BIT(10)" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v BIT(10) COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` BIT(10) COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 511);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 511 " ]] || false
dolt sql -q "UPDATE test SET v=v*2+1 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1023 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 1024);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, -1);"
[ "$status" -eq "1" ]
}
@test "types: BLOB" {
skip "This is not yet persisted in dolt"
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v BLOB COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` BLOB COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'abcdefg');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " abcdefg " ]] || false
dolt sql -q "UPDATE test SET v='1234567890' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
}
@test "types: BOOLEAN" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v BOOLEAN COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` TINYINT COMMENT 'tag:1'" ]] || false
}
@test "types: CHAR(10)" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v CHAR(10) COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` CHAR(10) COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'abcdefg');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " abcdefg " ]] || false
dolt sql -q "UPDATE test SET v='1234567890' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1234567890 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, '12345678901');"
[ "$status" -eq "1" ]
}
@test "types: DATE" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v DATE COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` DATE COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, '2020-02-10 11:12:13.456789');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 2020-02-10 00:00:00 +0000 UTC " ]] || false
run dolt sql -q "REPLACE INTO test VALUES (1, '1000-01-01 00:00:00');"
[ "$status" -eq "0" ]
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1000-01-01 00:00:00 +0000 UTC " ]] || false
run dolt sql -q "REPLACE INTO test VALUES (1, '9999-01-01 23:59:59.999999');"
[ "$status" -eq "0" ]
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 9999-01-01 00:00:00 +0000 UTC " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, '999-01-01 00:00:00');"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, '10000-01-01 00:00:00');"
[ "$status" -eq "1" ]
}
@test "types: DATETIME" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v DATETIME COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` DATETIME COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, '2020-02-10 11:12:13.456789');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 2020-02-10 11:12:13.456789 +0000 UTC " ]] || false
run dolt sql -q "REPLACE INTO test VALUES (1, '1000-01-01 00:00:00');"
[ "$status" -eq "0" ]
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1000-01-01 00:00:00 +0000 UTC " ]] || false
run dolt sql -q "REPLACE INTO test VALUES (1, '9999-01-01 23:59:59.999999');"
[ "$status" -eq "0" ]
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 9999-01-01 23:59:59.999999 +0000 UTC " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, '999-01-01 00:00:00');"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, '10000-01-01 00:00:00');"
[ "$status" -eq "1" ]
}
@test "types: DECIMAL" {
skip "This is not yet persisted in dolt"
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v DECIMAL COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` DECIMAL(10, 0) COMMENT 'tag:1'" ]] || false
}
@test "types: DECIMAL(9)" {
skip "This is not yet persisted in dolt"
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v DECIMAL(9) COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` DECIMAL(9, 0) COMMENT 'tag:1'" ]] || false
}
@test "types: DECIMAL(9, 5)" {
skip "This is not yet persisted in dolt"
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v DECIMAL(10, 5) COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` DECIMAL(10, 5) COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 1234.56789);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1234.56789 " ]] || false
dolt sql -q "UPDATE test SET v=v*2 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 2469.13578 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 10000);"
[ "$status" -eq "1" ]
}
@test "types: DOUBLE" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v DOUBLE COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` DOUBLE COMMENT 'tag:1'" ]] || false
skip "We can't parse large float values in go-mysql-server yet"
run dolt sql -q "INSERT INTO test VALUES (1, 8.988465674311578540726371186585217839905e+307);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 8.988465674311578540726371186585217839905e+307 " ]] || false
dolt sql -q "UPDATE test SET v=v*2 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1.797693134862315708145274237317043567981e+308 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 3.5953862697246314162905484746340871359614113505168999e+308);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, -3.5953862697246314162905484746340871359614113505168999e+308);"
[ "$status" -eq "1" ]
}
@test "types: ENUM('a','b','c')" {
skip "This is not yet persisted in dolt"
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v ENUM('a','b','c') COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` ENUM('a','b','c') COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'a');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " a " ]] || false
dolt sql -q "UPDATE test SET v=2 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " b " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 'd');"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, '');"
[ "$status" -eq "1" ]
}
@test "types: FLOAT" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v FLOAT COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` FLOAT COMMENT 'tag:1'" ]] || false
skip "We can't parse large float values in go-mysql-server yet"
run dolt sql -q "INSERT INTO test VALUES (1, 170141173319264429905852091742258462720);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 170141173319264429905852091742258462720 " ]] || false
dolt sql -q "UPDATE test SET v=v*2 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 340282346638528859811704183484516925440 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 680564693277057719623408366969033850880);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, -680564693277057719623408366969033850880);"
[ "$status" -eq "1" ]
}
@test "types: INT" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v INT COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` INT COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 1073741823);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1073741823 " ]] || false
dolt sql -q "UPDATE test SET v=v*2+1 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 2147483647 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 2147483648);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, -2147483649);"
[ "$status" -eq "1" ]
}
@test "types: INT UNSIGNED" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v INT UNSIGNED COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` INT UNSIGNED COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 2147483647);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 2147483647 " ]] || false
dolt sql -q "UPDATE test SET v=v*2+1 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 4294967295 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 4294967296);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, -1);"
[ "$status" -eq "1" ]
}
@test "types: INTEGER" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v INTEGER COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` INT COMMENT 'tag:1'" ]] || false
}
@test "types: INTEGER UNSIGNED" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v INTEGER UNSIGNED COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` INT UNSIGNED COMMENT 'tag:1'" ]] || false
}
@test "types: LONGBLOB" {
skip "This is not yet persisted in dolt"
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v LONGBLOB COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` LONGBLOB COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'abcdefg');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " abcdefg " ]] || false
dolt sql -q "UPDATE test SET v='1234567890' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
}
@test "types: LONGTEXT" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v LONGTEXT COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` LONGTEXT COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'abcdefg');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " abcdefg " ]] || false
dolt sql -q "UPDATE test SET v='1234567890' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
}
@test "types: MEDIUMBLOB" {
skip "This is not yet persisted in dolt"
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v MEDIUMBLOB COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` MEDIUMBLOB COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'abcdefg');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " abcdefg " ]] || false
dolt sql -q "UPDATE test SET v='1234567890' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
}
@test "types: MEDIUMINT" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v MEDIUMINT COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` MEDIUMINT COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 4194303);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 4194303 " ]] || false
dolt sql -q "UPDATE test SET v=v*2+1 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 8388607 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 8388608);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, -8388609);"
[ "$status" -eq "1" ]
}
@test "types: MEDIUMINT UNSIGNED" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v MEDIUMINT UNSIGNED COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` MEDIUMINT UNSIGNED COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 8388607);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 8388607 " ]] || false
dolt sql -q "UPDATE test SET v=v*2+1 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 16777215 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 16777216);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, -1);"
[ "$status" -eq "1" ]
}
@test "types: MEDIUMTEXT" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v MEDIUMTEXT COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` MEDIUMTEXT COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'abcdefg');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " abcdefg " ]] || false
dolt sql -q "UPDATE test SET v='1234567890' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
}
@test "types: REAL" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v REAL COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` DOUBLE COMMENT 'tag:1'" ]] || false
}
@test "types: SET('a','b','c')" {
skip "This is not yet persisted in dolt"
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v SET('a','b','c') COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` SET('a','b','c') COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'b,a');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " a,b " ]] || false
dolt sql -q "UPDATE test SET v='b,a,c,c' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " a,b,c " ]] || false
run dolt sql -q "REPLACE INTO test VALUES (1, '');"
[ "$status" -eq "0" ]
run dolt sql -q "INSERT INTO test VALUES (2, 'd');"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, 'a,d');"
[ "$status" -eq "1" ]
}
@test "types: SMALLINT" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v SMALLINT COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` SMALLINT COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 16383);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 16383 " ]] || false
dolt sql -q "UPDATE test SET v=v*2+1 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 32767 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 32768);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, -32769);"
[ "$status" -eq "1" ]
}
@test "types: SMALLINT UNSIGNED" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v SMALLINT UNSIGNED COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` SMALLINT UNSIGNED COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 32767);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 32767 " ]] || false
dolt sql -q "UPDATE test SET v=v*2+1 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 65535 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 65536);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, -1);"
[ "$status" -eq "1" ]
}
@test "types: TEXT" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v TEXT COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` TEXT COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'abcdefg');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " abcdefg " ]] || false
dolt sql -q "UPDATE test SET v='1234567890' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
}
@test "types: TIME" {
skip "This is not yet persisted in dolt"
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v TIME COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` TIME COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, '11:22:33.444444');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 11:22:33.444444 " ]] || false
dolt sql -q "UPDATE test SET v='11:22' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 11:22:00 " ]] || false
run dolt sql -q "REPLACE INTO test VALUES (1, '850:00:00');"
[ "$status" -eq "0" ]
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 838:59:59 " ]] || false
run dolt sql -q "REPLACE INTO test VALUES (1, '-850:00:00');"
[ "$status" -eq "0" ]
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " -838:59:59 " ]] || false
}
@test "types: TIMESTAMP" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v TIMESTAMP COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` TIMESTAMP COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, '2020-02-10 11:12:13.456789');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 2020-02-10 11:12:13.456789 +0000 UTC " ]] || false
run dolt sql -q "REPLACE INTO test VALUES (1, '1970-01-01 00:00:01');"
[ "$status" -eq "0" ]
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1970-01-01 00:00:01 +0000 UTC " ]] || false
run dolt sql -q "REPLACE INTO test VALUES (1, '2038-01-19 03:14:07.999999');"
[ "$status" -eq "0" ]
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 2038-01-19 03:14:07.999999 +0000 UTC " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, '1970-01-01 00:00:00');"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, '2038-01-19 03:14:08');"
[ "$status" -eq "1" ]
}
@test "types: TINYBLOB" {
skip "This is not yet persisted in dolt"
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v TINYBLOB COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` TINYBLOB COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'abcdefg');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " abcdefg " ]] || false
dolt sql -q "UPDATE test SET v='1234567890' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
}
@test "types: TINYINT" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v TINYINT COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` TINYINT COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 63);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 63 " ]] || false
dolt sql -q "UPDATE test SET v=v*2+1 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 127 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 128);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, -129);"
[ "$status" -eq "1" ]
}
@test "types: TINYINT UNSIGNED" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v TINYINT UNSIGNED COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` TINYINT UNSIGNED COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 127);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 127 " ]] || false
dolt sql -q "UPDATE test SET v=v*2+1 WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 255 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 256);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, -1);"
[ "$status" -eq "1" ]
}
@test "types: TINYTEXT" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v TINYTEXT COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` TINYTEXT COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'abcdefg');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " abcdefg " ]] || false
dolt sql -q "UPDATE test SET v='1234567890' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
}
@test "types: VARBINARY(10)" {
skip "This is not yet persisted in dolt"
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v VARBINARY(10) COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` VARBINARY(10) COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'abcdefg');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " abcdefg " ]] || false
dolt sql -q "UPDATE test SET v='1234567890' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1234567890 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, '12345678901');"
[ "$status" -eq "1" ]
}
@test "types: VARCHAR(10)" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v VARCHAR(10) COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` VARCHAR(10) COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'abcdefg');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " abcdefg " ]] || false
dolt sql -q "UPDATE test SET v='1234567890' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1234567890 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, '12345678901');"
[ "$status" -eq "1" ]
}
@test "types: VARCHAR(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v VARCHAR(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` VARCHAR(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 'abcdefg');"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " abcdefg " ]] || false
dolt sql -q "UPDATE test SET v='1234567890' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1234567890 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, '12345678901');"
[ "$status" -eq "1" ]
}
@test "types: YEAR" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
v YEAR COMMENT 'tag:1',
PRIMARY KEY (pk)
);
SQL
run dolt schema show
[ "$status" -eq "0" ]
[[ "$output" =~ "\`v\` YEAR COMMENT 'tag:1'" ]] || false
run dolt sql -q "INSERT INTO test VALUES (1, 1901);"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1 " ]] || false
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 1901 " ]] || false
dolt sql -q "UPDATE test SET v='2155' WHERE pk=1;"
run dolt sql -q "SELECT * FROM test"
[ "$status" -eq "0" ]
[[ "${lines[3]}" =~ " 2155 " ]] || false
run dolt sql -q "INSERT INTO test VALUES (2, 1900);"
[ "$status" -eq "1" ]
run dolt sql -q "INSERT INTO test VALUES (2, '2156');"
[ "$status" -eq "1" ]
}

View File

@@ -0,0 +1,253 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"fmt"
"math"
"strconv"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/liquidata-inc/dolt/go/store/types"
)
func TestBitConvertNomsValueToValue(t *testing.T) {
tests := []struct {
typ *bitType
input types.Uint
output uint64
expectedErr bool
}{
{
generateBitType(t, 1),
0,
0,
false,
},
{
generateBitType(t, 1),
1,
1,
false,
},
{
generateBitType(t, 11),
250,
250,
false,
},
{
generateBitType(t, 64),
math.MaxUint64,
math.MaxUint64,
false,
},
{
generateBitType(t, 1),
7,
0,
true,
},
{
generateBitType(t, 10),
374562394,
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ConvertNomsValueToValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, output)
}
})
}
}
func TestBitConvertValueToNomsValue(t *testing.T) {
tests := []struct {
typ *bitType
input interface{}
output types.Uint
expectedErr bool
}{
{
generateBitType(t, 1),
true,
1,
false,
},
{
generateBitType(t, 5),
int16(25),
25,
false,
},
{
generateBitType(t, 64),
uint64(287946293486),
287946293486,
false,
},
{
generateBitType(t, 3),
float32(78.3),
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ConvertValueToNomsValue(test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}
func TestBitFormatValue(t *testing.T) {
tests := []struct {
typ *bitType
input types.Uint
output string
expectedErr bool
}{
{
generateBitType(t, 1),
0,
"0",
false,
},
{
generateBitType(t, 1),
1,
"1",
false,
},
{
generateBitType(t, 11),
250,
"250",
false,
},
{
generateBitType(t, 64),
math.MaxUint64,
strconv.FormatUint(math.MaxUint64, 10),
false,
},
{
generateBitType(t, 1),
7,
"",
true,
},
{
generateBitType(t, 10),
374562394,
"",
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.FormatValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, *output)
}
})
}
}
func TestBitParseValue(t *testing.T) {
tests := []struct {
typ *bitType
input string
output types.Uint
expectedErr bool
}{
{
generateBitType(t, 1),
"0",
0,
false,
},
{
generateBitType(t, 5),
"25",
25,
false,
},
{
generateBitType(t, 64),
"287946293486",
287946293486,
false,
},
{
generateBitType(t, 3),
"78.3",
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ParseValue(&test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}
func generateBitTypes(t *testing.T, numOfTypes uint16) []TypeInfo {
var res []TypeInfo
loop(t, 1, 64, numOfTypes, func(i int64) {
res = append(res, generateBitType(t, uint8(i)))
})
return res
}
func generateBitType(t *testing.T, bits uint8) *bitType {
typ, err := CreateBitTypeFromParams(map[string]string{
bitTypeParam_Bits: strconv.FormatInt(int64(bits), 10),
})
require.NoError(t, err)
realType, ok := typ.(*bitType)
require.True(t, ok)
return realType
}

View File

@@ -0,0 +1,180 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/liquidata-inc/dolt/go/store/types"
)
func TestBoolConvertNomsValueToValue(t *testing.T) {
tests := []struct {
input types.Bool
output uint64
expectedErr bool
}{
{
false,
0,
false,
},
{
true,
1,
false,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, BoolType.String(), test.input), func(t *testing.T) {
output, err := BoolType.ConvertNomsValueToValue(test.input)
require.NoError(t, err)
require.Equal(t, test.output, output)
})
}
}
func TestBoolConvertValueToNomsValue(t *testing.T) {
tests := []struct {
input interface{}
output types.Bool
expectedErr bool
}{
{
true,
true,
false,
},
{
int16(25),
true,
false,
},
{
uint32(84875),
true,
false,
},
{
"FALSE",
false,
false,
},
{
"0",
false,
false,
},
{
"44",
true,
false,
},
{
[]byte{32, 1, 84},
false,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, BoolType.String(), test.input), func(t *testing.T) {
output, err := BoolType.ConvertValueToNomsValue(test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}
func TestBoolFormatValue(t *testing.T) {
tests := []struct {
input types.Bool
output string
expectedErr bool
}{
{
false,
"0",
false,
},
{
true,
"1",
false,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, BoolType.String(), test.input), func(t *testing.T) {
output, err := BoolType.FormatValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, *output)
}
})
}
}
func TestBoolParseValue(t *testing.T) {
tests := []struct {
input string
output types.Bool
expectedErr bool
}{
{
"0",
false,
false,
},
{
"25",
true,
false,
},
{
"true",
true,
false,
},
{
"something",
false,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, BoolType.String(), test.input), func(t *testing.T) {
output, err := BoolType.ParseValue(&test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}

View File

@@ -0,0 +1,39 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"math"
"testing"
"github.com/stretchr/testify/require"
"github.com/liquidata-inc/dolt/go/libraries/utils/mathutil"
)
func loop(t *testing.T, start int64, endInclusive int64, numOfSteps uint16, loopedFunc func(int64)) {
require.True(t, endInclusive > start)
maxNumOfSteps := endInclusive - start + 1
trueNumOfSteps := mathutil.MinInt64(int64(numOfSteps), maxNumOfSteps) - 1
inc := float64(maxNumOfSteps) / float64(trueNumOfSteps)
fCurrentVal := float64(start)
currentVal := int64(math.Round(fCurrentVal))
fCurrentVal -= 1
for currentVal <= endInclusive {
loopedFunc(currentVal)
fCurrentVal += inc
currentVal = int64(math.Round(fCurrentVal))
}
}

View File

@@ -0,0 +1,264 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/liquidata-inc/dolt/go/store/types"
)
func TestDatetimeConvertNomsValueToValue(t *testing.T) {
tests := []struct {
typ *datetimeType
input types.Timestamp
output time.Time
expectedErr bool
}{
{
DateType,
types.Timestamp(time.Date(1880, 1, 2, 4, 6, 3, 472382485, time.UTC)),
time.Date(1880, 1, 2, 0, 0, 0, 0, time.UTC),
false,
},
{
TimestampType,
types.Timestamp(time.Date(2030, 1, 2, 4, 6, 3, 472382485, time.UTC)),
time.Date(2030, 1, 2, 4, 6, 3, 472382485, time.UTC),
false,
},
{
DatetimeType,
types.Timestamp(time.Date(5800, 1, 2, 4, 6, 3, 472382485, time.UTC)),
time.Date(5800, 1, 2, 4, 6, 3, 472382485, time.UTC),
false,
},
{
DatetimeType,
types.Timestamp(time.Date(9999, 12, 31, 23, 59, 59, 999999000, time.UTC)),
time.Date(9999, 12, 31, 23, 59, 59, 999999000, time.UTC),
false,
},
{
TimestampType,
types.Timestamp(time.Date(2039, 1, 2, 4, 6, 3, 472382485, time.UTC)),
time.Time{},
true,
},
{
DatetimeType,
types.Timestamp(time.Date(5, 1, 2, 4, 6, 3, 472382485, time.UTC)),
time.Time{},
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ConvertNomsValueToValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, output)
}
})
}
}
func TestDatetimeConvertValueToNomsValue(t *testing.T) {
tests := []struct {
typ *datetimeType
input interface{}
output types.Timestamp
expectedErr bool
}{
{
DateType,
time.Date(1880, 1, 2, 4, 6, 3, 472382485, time.UTC),
types.Timestamp(time.Date(1880, 1, 2, 0, 0, 0, 0, time.UTC)),
false,
},
{
TimestampType,
time.Date(2030, 1, 2, 4, 6, 3, 472382485, time.UTC),
types.Timestamp(time.Date(2030, 1, 2, 4, 6, 3, 472382485, time.UTC)),
false,
},
{
DatetimeType,
time.Date(5800, 1, 2, 4, 6, 3, 472382485, time.UTC),
types.Timestamp(time.Date(5800, 1, 2, 4, 6, 3, 472382485, time.UTC)),
false,
},
{
DatetimeType,
time.Date(9999, 12, 31, 23, 59, 59, 999999000, time.UTC),
types.Timestamp(time.Date(9999, 12, 31, 23, 59, 59, 999999000, time.UTC)),
false,
},
{
TimestampType,
time.Date(2039, 1, 2, 4, 6, 3, 472382485, time.UTC),
types.Timestamp{},
true,
},
{
DatetimeType,
time.Date(5, 1, 2, 4, 6, 3, 472382485, time.UTC),
types.Timestamp{},
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ConvertValueToNomsValue(test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}
func TestDatetimeFormatValue(t *testing.T) {
tests := []struct {
typ *datetimeType
input types.Timestamp
output string
expectedErr bool
}{
{
DateType,
types.Timestamp(time.Date(1880, 1, 2, 4, 6, 3, 472382485, time.UTC)),
"1880-01-02",
false,
},
{
TimestampType,
types.Timestamp(time.Date(2030, 1, 2, 4, 6, 3, 472382485, time.UTC)),
"2030-01-02 04:06:03.472382",
false,
},
{
DatetimeType,
types.Timestamp(time.Date(5800, 1, 2, 4, 6, 3, 472382485, time.UTC)),
"5800-01-02 04:06:03.472382",
false,
},
{
DatetimeType,
types.Timestamp(time.Date(9999, 12, 31, 23, 59, 59, 999999000, time.UTC)),
"9999-12-31 23:59:59.999999",
false,
},
{
TimestampType,
types.Timestamp(time.Date(2039, 1, 2, 4, 6, 3, 472382485, time.UTC)),
"",
true,
},
{
DatetimeType,
types.Timestamp(time.Date(5, 1, 2, 4, 6, 3, 472382485, time.UTC)),
"",
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.FormatValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, *output)
}
})
}
}
func TestDatetimeParseValue(t *testing.T) {
tests := []struct {
typ *datetimeType
input string
output types.Timestamp
expectedErr bool
}{
{
DateType,
"1880-01-02 04:06:03.472382",
types.Timestamp(time.Date(1880, 1, 2, 0, 0, 0, 0, time.UTC)),
false,
},
{
DateType,
"1880-01-02",
types.Timestamp(time.Date(1880, 1, 2, 0, 0, 0, 0, time.UTC)),
false,
},
{
TimestampType,
"2030-01-02 04:06:03.472382",
types.Timestamp(time.Date(2030, 1, 2, 4, 6, 3, 472382000, time.UTC)),
false,
},
{
DatetimeType,
"5800-01-02 04:06:03.472382",
types.Timestamp(time.Date(5800, 1, 2, 4, 6, 3, 472382000, time.UTC)),
false,
},
{
DatetimeType,
"9999-12-31 23:59:59.999999",
types.Timestamp(time.Date(9999, 12, 31, 23, 59, 59, 999999000, time.UTC)),
false,
},
{
TimestampType,
"2039-01-02 04:06:03.472382",
types.Timestamp{},
true,
},
{
DatetimeType,
"0005-01-02 04:06:03.472382",
types.Timestamp{},
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ParseValue(&test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}

View File

@@ -0,0 +1,50 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"strconv"
"testing"
"github.com/src-d/go-mysql-server/sql"
"github.com/stretchr/testify/require"
)
//TODO: add some basic tests once the storage format has been decided
func generateDecimalTypes(t *testing.T, numOfTypes uint16) []TypeInfo {
var res []TypeInfo
scaleMult := float64(sql.DecimalTypeMaxScale) / sql.DecimalTypeMaxPrecision
loop(t, 1, sql.DecimalTypeMaxPrecision, numOfTypes, func(i int64) {
if i%9 <= 5 {
res = append(res, generateDecimalType(t, i, int64(float64(i)*scaleMult)))
} else {
res = append(res, generateDecimalType(t, i, 0))
}
})
return res
}
func generateDecimalType(t *testing.T, precision int64, scale int64) *decimalType {
typ, err := CreateDecimalTypeFromParams(map[string]string{
decimalTypeParam_Precision: strconv.FormatInt(precision, 10),
decimalTypeParam_Scale: strconv.FormatInt(scale, 10),
})
require.NoError(t, err)
realType, ok := typ.(*decimalType)
require.True(t, ok)
return realType
}

View File

@@ -0,0 +1,49 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"testing"
"github.com/src-d/go-mysql-server/sql"
"github.com/stretchr/testify/require"
)
//TODO: add some basic tests once the storage format has been decided
func generateEnumTypes(t *testing.T, numOfTypes int64) []TypeInfo {
res := make([]TypeInfo, numOfTypes)
for i := int64(1); i <= numOfTypes; i++ {
res[i-1] = generateEnumType(t, int(i))
}
return res
}
func generateEnumType(t *testing.T, numOfElements int) *enumType {
require.True(t, numOfElements >= 1 && numOfElements <= sql.EnumTypeMaxElements)
vals := make([]string, numOfElements)
str := make([]byte, 4)
alphabet := "abcdefghijklmnopqrstuvwxyz"
for i := 0; i < numOfElements; i++ {
x := i
for j := 2; j >= 0; j-- {
x /= len(alphabet)
str[j] = alphabet[x%len(alphabet)]
}
str[3] = alphabet[i%len(alphabet)]
vals[i] = string(str)
}
return &enumType{sql.MustCreateEnumType(vals, sql.Collation_Default)}
}

View File

@@ -0,0 +1,230 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"fmt"
"math"
"strconv"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/liquidata-inc/dolt/go/store/types"
)
func TestFloatConvertNomsValueToValue(t *testing.T) {
tests := []struct {
typ *floatType
input types.Float
output interface{}
expectedErr bool
}{
{
Float32Type,
0,
float32(0),
false,
},
{
Float64Type,
1,
float64(1),
false,
},
{
Float32Type,
250,
float32(250),
false,
},
{
Float64Type,
math.MaxFloat64,
float64(math.MaxFloat64),
false,
},
{
Float32Type,
math.MaxFloat64,
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ConvertNomsValueToValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, output)
}
})
}
}
func TestFloatConvertValueToNomsValue(t *testing.T) {
tests := []struct {
typ *floatType
input interface{}
output types.Float
expectedErr bool
}{
{
Float32Type,
true,
1,
false,
},
{
Float64Type,
"25",
25,
false,
},
{
Float64Type,
uint64(287946293486),
287946293486,
false,
},
{
Float32Type,
time.Unix(137849, 0),
137849,
false,
},
{
Float64Type,
complex128(14i),
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ConvertValueToNomsValue(test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}
func TestFloatFormatValue(t *testing.T) {
tests := []struct {
typ *floatType
input types.Float
output string
expectedErr bool
}{
{
Float32Type,
0,
"0",
false,
},
{
Float64Type,
1,
"1",
false,
},
{
Float32Type,
250,
"250",
false,
},
{
Float64Type,
math.MaxFloat64,
strconv.FormatFloat(math.MaxFloat64, 'f', -1, 64),
false,
},
{
Float32Type,
math.MaxFloat64,
"",
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.FormatValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, *output)
}
})
}
}
func TestFloatParseValue(t *testing.T) {
tests := []struct {
typ *floatType
input string
output types.Float
expectedErr bool
}{
{
Float32Type,
"423.5",
423.5,
false,
},
{
Float64Type,
"81277392850347",
81277392850347,
false,
},
{
Float64Type,
"12345.03125",
12345.03125,
false,
},
{
Float64Type,
"something",
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ParseValue(&test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}

View File

@@ -0,0 +1,161 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/liquidata-inc/dolt/go/store/types"
)
func TestInlineBlobConvertNomsValueToValue(t *testing.T) {
tests := []struct {
input types.InlineBlob
output string
}{
{
[]byte("hi"),
"hi",
},
{
[]byte("hello there"),
"hello there",
},
{
[]byte("هذا هو بعض نماذج النص التي أستخدمها لاختبار عناصر"),
"هذا هو بعض نماذج النص التي أستخدمها لاختبار عناصر",
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, InlineBlobType.String(), test.input), func(t *testing.T) {
output, err := InlineBlobType.ConvertNomsValueToValue(test.input)
require.NoError(t, err)
require.Equal(t, test.output, output)
})
}
}
func TestInlineBlobConvertValueToNomsValue(t *testing.T) {
tests := []struct {
input interface{}
output types.InlineBlob
expectedErr bool
}{
{
int16(25),
[]byte("25"),
false,
},
{
uint64(287946293486),
[]byte("287946293486"),
false,
},
{
float32(78.25),
[]byte("78.25"),
false,
},
{
"something",
[]byte("something"),
false,
},
{
time.Date(1880, 1, 2, 3, 4, 5, 0, time.UTC),
[]byte("1880-01-02 03:04:05"),
false,
},
{
complex128(32),
[]byte{},
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, InlineBlobType.String(), test.input), func(t *testing.T) {
output, err := InlineBlobType.ConvertValueToNomsValue(test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}
func TestInlineBlobFormatValue(t *testing.T) {
tests := []struct {
input types.InlineBlob
output string
}{
{
[]byte("hi"),
"hi",
},
{
[]byte("hello there"),
"hello there",
},
{
[]byte("هذا هو بعض نماذج النص التي أستخدمها لاختبار عناصر"),
"هذا هو بعض نماذج النص التي أستخدمها لاختبار عناصر",
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, InlineBlobType.String(), test.input), func(t *testing.T) {
output, err := InlineBlobType.FormatValue(test.input)
require.NoError(t, err)
require.Equal(t, test.output, *output)
})
}
}
func TestInlineBlobParseValue(t *testing.T) {
tests := []struct {
input string
output types.InlineBlob
}{
{
"hi",
[]byte("hi"),
},
{
"hello there",
[]byte("hello there"),
},
{
"هذا هو بعض نماذج النص التي أستخدمها لاختبار عناصر",
[]byte("هذا هو بعض نماذج النص التي أستخدمها لاختبار عناصر"),
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, InlineBlobType.String(), test.input), func(t *testing.T) {
output, err := InlineBlobType.ParseValue(&test.input)
require.NoError(t, err)
assert.Equal(t, test.output, output)
})
}
}

View File

@@ -0,0 +1,277 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"fmt"
"math"
"strconv"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/liquidata-inc/dolt/go/store/types"
)
func TestIntConvertNomsValueToValue(t *testing.T) {
tests := []struct {
typ *intType
input types.Int
output interface{}
expectedErr bool
}{
{
Int8Type,
120,
int8(120),
false,
},
{
Int16Type,
30000,
int16(30000),
false,
},
{
Int24Type,
7000000,
int32(7000000),
false,
},
{
Int32Type,
2000000000,
int32(2000000000),
false,
},
{
Int64Type,
math.MaxInt64,
int64(math.MaxInt64),
false,
},
{
Int8Type,
-200,
0,
true,
},
{
Int32Type,
math.MaxInt64,
0,
true,
},
{
Int24Type,
1 << 25,
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ConvertNomsValueToValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, output)
}
})
}
}
func TestIntConvertValueToNomsValue(t *testing.T) {
tests := []struct {
typ *intType
input interface{}
output types.Int
expectedErr bool
}{
{
Int8Type,
true,
1,
false,
},
{
Int16Type,
int16(25),
25,
false,
},
{
Int24Type,
uint64(184035),
184035,
false,
},
{
Int32Type,
float32(312.1235),
312,
false,
},
{
Int64Type,
"184035",
184035,
false,
},
{
Int24Type,
int32(math.MaxInt32),
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ConvertValueToNomsValue(test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}
func TestIntFormatValue(t *testing.T) {
tests := []struct {
typ *intType
input types.Int
output string
expectedErr bool
}{
{
Int8Type,
120,
"120",
false,
},
{
Int16Type,
30000,
"30000",
false,
},
{
Int24Type,
7000000,
"7000000",
false,
},
{
Int32Type,
2000000000,
"2000000000",
false,
},
{
Int64Type,
math.MaxInt64,
strconv.FormatInt(math.MaxInt64, 10),
false,
},
{
Int32Type,
math.MaxInt64,
"",
true,
},
{
Int24Type,
1 << 25,
"",
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.FormatValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, *output)
}
})
}
}
func TestIntParseValue(t *testing.T) {
tests := []struct {
typ *intType
input string
output types.Int
expectedErr bool
}{
{
Int8Type,
"120",
120,
false,
},
{
Int16Type,
"30000",
30000,
false,
},
{
Int24Type,
"7000000",
7000000,
false,
},
{
Int32Type,
"2000000000",
2000000000,
false,
},
{
Int64Type,
strconv.FormatInt(math.MaxInt64, 10),
math.MaxInt64,
false,
},
{
Int32Type,
"something",
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ParseValue(&test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}

View File

@@ -0,0 +1,43 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"testing"
"github.com/src-d/go-mysql-server/sql"
"github.com/stretchr/testify/require"
)
//TODO: add some basic tests once the storage format has been decided
func generateSetTypes(t *testing.T, numOfTypes int64) []TypeInfo {
res := make([]TypeInfo, numOfTypes)
for i := int64(1); i <= numOfTypes; i++ {
res[i-1] = generateSetType(t, int(i))
}
return res
}
func generateSetType(t *testing.T, numOfElements int) *setType {
require.True(t, numOfElements >= 1 && numOfElements <= sql.SetTypeMaxElements)
vals := make([]string, numOfElements)
alphabet := "abcdefghijklmnopqrstuvwxyz"
lenAlphabet := len(alphabet)
for i := 0; i < numOfElements; i++ {
vals[i] = string([]byte{alphabet[(i/lenAlphabet)%lenAlphabet], alphabet[i%lenAlphabet]})
}
return &setType{sql.MustCreateSetType(vals, sql.Collation_Default)}
}

View File

@@ -0,0 +1,17 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
//TODO: add some basic tests once the storage format has been decided

View File

@@ -0,0 +1,381 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"fmt"
"testing"
"time"
"github.com/src-d/go-mysql-server/sql"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/liquidata-inc/dolt/go/store/types"
)
func TestTypeInfoSuite(t *testing.T) {
typeInfoArrays, validTypeValues := generateTypeInfoArrays(t)
t.Run("VerifyArray", func(t *testing.T) {
verifyTypeInfoArrays(t, typeInfoArrays, validTypeValues)
})
t.Run("ConvertRoundTrip", func(t *testing.T) {
testTypeInfoConvertRoundTrip(t, typeInfoArrays, validTypeValues)
})
t.Run("Equals", func(t *testing.T) {
testTypeInfoEquals(t, typeInfoArrays)
})
t.Run("ForeignKindHandling", func(t *testing.T) {
testTypeInfoForeignKindHandling(t, typeInfoArrays, validTypeValues)
})
t.Run("FormatParseRoundTrip", func(t *testing.T) {
testTypeInfoFormatParseRoundTrip(t, typeInfoArrays, validTypeValues)
})
t.Run("GetTypeParams", func(t *testing.T) {
testTypeInfoGetTypeParams(t, typeInfoArrays)
})
t.Run("NullHandling", func(t *testing.T) {
testTypeInfoNullHandling(t, typeInfoArrays)
})
t.Run("NomsKind", func(t *testing.T) {
testTypeInfoNomsKind(t, typeInfoArrays, validTypeValues)
})
t.Run("ToSqlType", func(t *testing.T) {
testTypeInfoToSqlType(t, typeInfoArrays)
})
}
// verify that the TypeInfos and values are all consistent with each other, and cover the full range of types
func verifyTypeInfoArrays(t *testing.T, tiArrays [][]TypeInfo, vaArrays [][]types.Value) {
require.Equal(t, len(tiArrays), len(vaArrays))
seenTypeInfos := make(map[Identifier]bool)
for identifier := range Identifiers {
seenTypeInfos[identifier] = false
}
// delete any types that should not be tested
delete(seenTypeInfos, UnknownTypeIdentifier)
delete(seenTypeInfos, TupleTypeIdentifier)
for _, tiArray := range tiArrays {
// no row should be empty
require.True(t, len(tiArray) > 0, `length of array "%v" should be greater than zero`, len(tiArray))
firstIdentifier := tiArray[0].GetTypeIdentifier()
t.Run(firstIdentifier.String(), func(t *testing.T) {
seen, ok := seenTypeInfos[firstIdentifier]
require.True(t, ok, `identifier "%v" is not recognized`, firstIdentifier)
require.False(t, seen, `identifier "%v" is used by another type from the array`, firstIdentifier)
seenTypeInfos[firstIdentifier] = true
for _, ti := range tiArray {
// verify that all of the types have the same identifier
require.Equal(t, firstIdentifier, ti.GetTypeIdentifier(),
`expected "%v" but got "%v"`, firstIdentifier, ti.GetTypeIdentifier())
}
})
}
// make sure that we are testing all of the types (unless deleted above)
for seenti, seen := range seenTypeInfos {
require.True(t, seen, `identifier "%v" does not have a relevant type being tested`, seenti)
}
for _, vaArray := range vaArrays {
// no row should be empty
require.True(t, len(vaArray) > 0, `length of array "%v" should be greater than zero`, len(vaArray))
firstKind := vaArray[0].Kind()
for _, val := range vaArray {
// verify that all of the values in an row are of the same kind
require.Equal(t, firstKind, val.Kind(), `expected kind "%v" but got "%v"`, firstKind, val.Kind())
}
}
}
// assuming valid data, verifies that the To-From interface{} functions can round trip
func testTypeInfoConvertRoundTrip(t *testing.T, tiArrays [][]TypeInfo, vaArrays [][]types.Value) {
for rowIndex, tiArray := range tiArrays {
t.Run(tiArray[0].GetTypeIdentifier().String(), func(t *testing.T) {
//TODO: determine the storage format for DecimalType
//TODO: determine the storage format for VarBinaryType
if tiArray[0].GetTypeIdentifier() == DecimalTypeIdentifier || tiArray[0].GetTypeIdentifier() == VarBinaryTypeIdentifier {
t.Skipf(`"%v" not yet persisted, thus no need to fix tests`, tiArray[0].GetTypeIdentifier().String())
}
for _, ti := range tiArray {
atLeastOneValid := false
t.Run(ti.String(), func(t *testing.T) {
for _, val := range vaArrays[rowIndex] {
t.Run(fmt.Sprintf(`types.%v(%v)`, val.Kind().String(), val.HumanReadableString()), func(t *testing.T) {
vInterface, err := ti.ConvertNomsValueToValue(val)
if ti.IsValid(val) {
atLeastOneValid = true
require.NoError(t, err)
outVal, err := ti.ConvertValueToNomsValue(vInterface)
require.NoError(t, err)
if ti == DateType { // Special case as DateType removes the hh:mm:ss
val = types.Timestamp(time.Time(val.(types.Timestamp)).Truncate(24 * time.Hour))
require.True(t, val.Equals(outVal), "\"%v\"\n\"%v\"", val, outVal)
} else {
require.True(t, val.Equals(outVal), "\"%v\"\n\"%v\"", val, outVal)
}
} else {
assert.Error(t, err)
}
})
}
})
require.True(t, atLeastOneValid, `all values reported false for "%v"`, ti.String())
}
})
}
}
// each TypeInfo in tiArrays is unique, so all equality comparisons should fail when the indices don't match
func testTypeInfoEquals(t *testing.T, tiArrays [][]TypeInfo) {
for tiArrayIndex, tiArray := range tiArrays {
t.Run(tiArray[0].GetTypeIdentifier().String(), func(t *testing.T) {
// check this TypeInfo against its own variations, EX: Int16 & Int32
// a != b should also mean b != a
for i := range tiArray {
ti1 := tiArray[i]
t.Run(ti1.String(), func(t *testing.T) {
for j := range tiArray {
ti2 := tiArray[j]
t.Run(fmt.Sprintf(ti2.String()), func(t *testing.T) {
equality := ti1.Equals(ti2)
if i == j {
assert.True(t, equality)
} else {
assert.False(t, equality)
}
})
}
})
}
// we just check the first element and assume it'll hold true for the other values
firstTi := tiArray[0]
t.Run(fmt.Sprintf(`%v Others`, firstTi), func(t *testing.T) {
// check this TypeInfo against the other types, EX: Int16 & Float64
for tiArrayIndex2, tiArray2 := range tiArrays {
if tiArrayIndex == tiArrayIndex2 {
// this is the for loop above
continue
}
for _, otherTi := range tiArray2 {
t.Run(fmt.Sprintf(otherTi.String()), func(t *testing.T) {
equality := firstTi.Equals(otherTi)
assert.False(t, equality)
})
}
}
})
})
}
}
// ConvertNomsValueToValue and FormatValue should fail if the kind does not match the TypeInfo kind
func testTypeInfoForeignKindHandling(t *testing.T, tiArrays [][]TypeInfo, vaArrays [][]types.Value) {
for _, tiArray := range tiArrays {
t.Run(tiArray[0].GetTypeIdentifier().String(), func(t *testing.T) {
for _, ti := range tiArray {
t.Run(ti.String(), func(t *testing.T) {
for _, vaArray := range vaArrays {
for _, val := range vaArray {
t.Run(fmt.Sprintf(`types.%v(%v)`, val.Kind().String(), val.HumanReadableString()), func(t *testing.T) {
if ti.NomsKind() != val.Kind() {
_, err := ti.ConvertNomsValueToValue(val)
assert.Error(t, err)
_, err = ti.FormatValue(val)
assert.Error(t, err)
}
})
}
}
})
}
})
}
}
// assuming valid data, verifies that the To-From string functions can round trip
func testTypeInfoFormatParseRoundTrip(t *testing.T, tiArrays [][]TypeInfo, vaArrays [][]types.Value) {
for rowIndex, tiArray := range tiArrays {
t.Run(tiArray[0].GetTypeIdentifier().String(), func(t *testing.T) {
//TODO: determine the storage format for DecimalType
//TODO: determine the storage format for VarBinaryType
if tiArray[0].GetTypeIdentifier() == DecimalTypeIdentifier || tiArray[0].GetTypeIdentifier() == VarBinaryTypeIdentifier {
t.Skipf(`"%v" not yet persisted, thus no need to fix tests`, tiArray[0].GetTypeIdentifier().String())
}
for _, ti := range tiArray {
atLeastOneValid := false
t.Run(ti.String(), func(t *testing.T) {
for _, val := range vaArrays[rowIndex] {
t.Run(fmt.Sprintf(`types.%v(%v)`, val.Kind().String(), val.HumanReadableString()), func(t *testing.T) {
str, err := ti.FormatValue(val)
if ti.IsValid(val) {
atLeastOneValid = true
require.NoError(t, err)
outVal, err := ti.ParseValue(str)
require.NoError(t, err)
if ti == DateType { // special case as DateType removes the hh:mm:ss
val = types.Timestamp(time.Time(val.(types.Timestamp)).Truncate(24 * time.Hour))
require.True(t, val.Equals(outVal), "\"%v\"\n\"%v\"", val, outVal)
} else {
require.True(t, val.Equals(outVal), "\"%v\"\n\"%v\"", val, outVal)
}
} else {
assert.Error(t, err)
}
})
}
})
require.True(t, atLeastOneValid, `all values reported false for "%v"`, ti.String())
}
})
}
}
// verify that FromTypeParams can reconstruct the exact same TypeInfo from the params
func testTypeInfoGetTypeParams(t *testing.T, tiArrays [][]TypeInfo) {
for _, tiArray := range tiArrays {
t.Run(tiArray[0].GetTypeIdentifier().String(), func(t *testing.T) {
for _, ti := range tiArray {
t.Run(ti.String(), func(t *testing.T) {
newTi, err := FromTypeParams(ti.GetTypeIdentifier(), ti.GetTypeParams())
require.NoError(t, err)
require.True(t, ti.Equals(newTi), "%v\n%v", ti.String(), newTi.String())
})
}
})
}
}
// makes sure that everything can handle nil and NullValue (if applicable)
func testTypeInfoNullHandling(t *testing.T, tiArrays [][]TypeInfo) {
for _, tiArray := range tiArrays {
t.Run(tiArray[0].GetTypeIdentifier().String(), func(t *testing.T) {
for _, ti := range tiArray {
t.Run(ti.String(), func(t *testing.T) {
t.Run("ConvertNomsValueToValue", func(t *testing.T) {
val, err := ti.ConvertNomsValueToValue(types.NullValue)
require.NoError(t, err)
require.Nil(t, val)
val, err = ti.ConvertNomsValueToValue(nil)
require.NoError(t, err)
require.Nil(t, val)
})
t.Run("ConvertValueToNomsValue", func(t *testing.T) {
tVal, err := ti.ConvertValueToNomsValue(nil)
require.NoError(t, err)
require.Equal(t, types.NullValue, tVal)
})
t.Run("FormatValue", func(t *testing.T) {
tVal, err := ti.FormatValue(types.NullValue)
require.NoError(t, err)
require.Nil(t, tVal)
tVal, err = ti.FormatValue(nil)
require.NoError(t, err)
require.Nil(t, tVal)
})
t.Run("IsValid", func(t *testing.T) {
require.True(t, ti.IsValid(types.NullValue))
require.True(t, ti.IsValid(nil))
})
t.Run("ParseValue", func(t *testing.T) {
tVal, err := ti.ParseValue(nil)
require.NoError(t, err)
require.Equal(t, types.NullValue, tVal)
})
})
}
})
}
}
// smoke test checking that the returned NomsKind is consistent and matches the values.
func testTypeInfoNomsKind(t *testing.T, tiArrays [][]TypeInfo, vaArrays [][]types.Value) {
for rowIndex, tiArray := range tiArrays {
t.Run(tiArray[0].GetTypeIdentifier().String(), func(t *testing.T) {
nomsKind := tiArray[0].NomsKind()
for _, ti := range tiArray {
t.Run("Equality "+ti.String(), func(t *testing.T) {
require.Equal(t, nomsKind, ti.NomsKind())
})
}
t.Run("Values "+tiArray[0].NomsKind().String(), func(t *testing.T) {
for _, val := range vaArrays[rowIndex] {
require.Equal(t, nomsKind, val.Kind())
}
})
})
}
}
// smoke test so that there are no obvious panics when returning SQL types
func testTypeInfoToSqlType(t *testing.T, tiArrays [][]TypeInfo) {
for _, tiArray := range tiArrays {
t.Run(tiArray[0].GetTypeIdentifier().String(), func(t *testing.T) {
for _, ti := range tiArray {
t.Run(ti.String(), func(t *testing.T) {
_ = ti.ToSqlType()
})
}
})
}
}
// generate unique TypeInfos for each type, and also values that are valid for at least one of the TypeInfos for the matching row
func generateTypeInfoArrays(t *testing.T) ([][]TypeInfo, [][]types.Value) {
return [][]TypeInfo{
generateBitTypes(t, 16),
{BoolType},
{DateType, DatetimeType, TimestampType},
generateDecimalTypes(t, 16),
generateEnumTypes(t, 16),
{Float32Type, Float64Type},
{InlineBlobType},
{Int8Type, Int16Type, Int24Type, Int32Type, Int64Type},
generateSetTypes(t, 16),
{TimeType},
{Uint8Type, Uint16Type, Uint24Type, Uint32Type, Uint64Type},
{UuidType},
append(generateVarBinaryTypes(t, 12),
&varBinaryType{sql.TinyBlob}, &varBinaryType{sql.Blob},
&varBinaryType{sql.MediumBlob}, &varBinaryType{sql.LongBlob}),
append(generateVarStringTypes(t, 12),
&varStringType{sql.CreateTinyText(sql.Collation_Default)}, &varStringType{sql.CreateText(sql.Collation_Default)},
&varStringType{sql.CreateMediumText(sql.Collation_Default)}, &varStringType{sql.CreateLongText(sql.Collation_Default)}),
{YearType},
},
[][]types.Value{
{types.Uint(1), types.Uint(207), types.Uint(79147), types.Uint(34845728), types.Uint(9274618927)}, //Bit
{types.Bool(false), types.Bool(true)}, //Bool
{types.Timestamp(time.Date(1000, 1, 1, 0, 0, 0, 0, time.UTC)), //Datetime
types.Timestamp(time.Date(1970, 1, 1, 0, 0, 1, 0, time.UTC)),
types.Timestamp(time.Date(2000, 2, 28, 14, 38, 43, 583395000, time.UTC)),
types.Timestamp(time.Date(2038, 1, 19, 3, 14, 7, 999999000, time.UTC)),
types.Timestamp(time.Date(9999, 12, 31, 23, 59, 59, 999999000, time.UTC))},
{types.String("1"), types.String("-1.5"), types.String("4723245"), //Decimal
types.String("8923583.125"), types.String("1198728394234798423466321.27349757")},
{types.String("aaaa"), types.String("aaaa,aaac"), types.String("aaag"), types.String("aaab,aaad,aaaf"), types.String("aaag,aaah")}, //Enum
{types.Float(1.0), types.Float(65513.75), types.Float(4293902592), types.Float(4.58E71), types.Float(7.172E285)}, //Float
{types.InlineBlob{0}, types.InlineBlob{21}, types.InlineBlob{1, 17}, types.InlineBlob{72, 42}, types.InlineBlob{21, 122, 236}}, //InlineBlob
{types.Int(20), types.Int(215), types.Int(237493), types.Int(2035753568), types.Int(2384384576063)}, //Int
{types.String("aa"), types.String("aa,ac"), types.String("ag"), types.String("ab,ad,af"), types.String("ag,ah")}, //Set
{types.String("00:00:00"), types.String("00:00:01"), types.String("00:01:53"), types.String("68:36:59"), types.String("127:27:10.485214")}, //Time
{types.Uint(20), types.Uint(275), types.Uint(328395), types.Uint(630257298), types.Uint(93897259874)}, //Uint
{types.UUID{3}, types.UUID{3, 13}, types.UUID{128, 238, 82, 12}, types.UUID{31, 54, 23, 13, 63, 43}, types.UUID{83, 64, 21, 14, 42, 6, 35, 7, 54, 234, 6, 32, 1, 4, 2, 4}}, //Uuid
{types.String([]byte{1}), types.String([]byte{42, 52}), types.String([]byte{84, 32, 13, 63, 12, 86}), //VarBinary
types.String([]byte{1, 32, 235, 64, 32, 23, 45, 76}), types.String([]byte{123, 234, 34, 223, 76, 35, 32, 12, 84, 26, 15, 34, 65, 86, 45, 23, 43, 12, 76, 154, 234, 76, 34})},
{types.String(""), types.String("a"), types.String("abc"), //VarString
types.String("abcdefghijklmnopqrstuvwxyz"), types.String("هذا هو بعض نماذج النص التي أستخدمها لاختبار عناصر")},
{types.Int(1901), types.Int(1950), types.Int(2000), types.Int(2080), types.Int(2155)}, //Year
}
}

View File

@@ -0,0 +1,271 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"fmt"
"math"
"strconv"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/liquidata-inc/dolt/go/store/types"
)
func TestUintConvertNomsValueToValue(t *testing.T) {
tests := []struct {
typ *uintType
input types.Uint
output interface{}
expectedErr bool
}{
{
Uint8Type,
120,
uint8(120),
false,
},
{
Uint16Type,
30000,
uint16(30000),
false,
},
{
Uint24Type,
7000000,
uint32(7000000),
false,
},
{
Uint32Type,
2000000000,
uint32(2000000000),
false,
},
{
Uint64Type,
math.MaxInt64,
uint64(math.MaxInt64),
false,
},
{
Uint32Type,
math.MaxUint64,
0,
true,
},
{
Uint24Type,
1 << 25,
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ConvertNomsValueToValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, output)
}
})
}
}
func TestUintConvertValueToNomsValue(t *testing.T) {
tests := []struct {
typ *uintType
input interface{}
output types.Uint
expectedErr bool
}{
{
Uint8Type,
true,
1,
false,
},
{
Uint16Type,
int16(25),
25,
false,
},
{
Uint24Type,
uint64(184035),
184035,
false,
},
{
Uint32Type,
float32(312.1235),
312,
false,
},
{
Uint64Type,
"184035",
184035,
false,
},
{
Uint24Type,
int32(math.MaxInt32),
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ConvertValueToNomsValue(test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}
func TestUintFormatValue(t *testing.T) {
tests := []struct {
typ *uintType
input types.Uint
output string
expectedErr bool
}{
{
Uint8Type,
120,
"120",
false,
},
{
Uint16Type,
30000,
"30000",
false,
},
{
Uint24Type,
7000000,
"7000000",
false,
},
{
Uint32Type,
2000000000,
"2000000000",
false,
},
{
Uint64Type,
math.MaxUint64,
strconv.FormatUint(math.MaxUint64, 10),
false,
},
{
Uint32Type,
math.MaxUint64,
"",
true,
},
{
Uint24Type,
1 << 25,
"",
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.FormatValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, *output)
}
})
}
}
func TestUintParseValue(t *testing.T) {
tests := []struct {
typ *uintType
input string
output types.Uint
expectedErr bool
}{
{
Uint8Type,
"120",
120,
false,
},
{
Uint16Type,
"30000",
30000,
false,
},
{
Uint24Type,
"7000000",
7000000,
false,
},
{
Uint32Type,
"2000000000",
2000000000,
false,
},
{
Uint64Type,
strconv.FormatInt(math.MaxInt64, 10),
math.MaxInt64,
false,
},
{
Uint32Type,
"something",
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ParseValue(&test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}

View File

@@ -0,0 +1,204 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"fmt"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/liquidata-inc/dolt/go/store/types"
)
func TestUuidConvertNomsValueToValue(t *testing.T) {
tests := []struct {
input types.UUID
output string
}{
{
types.UUID(uuid.UUID{0}),
"00000000-0000-0000-0000-000000000000",
},
{
types.UUID(uuid.UUID{1, 2, 3, 4}),
"01020304-0000-0000-0000-000000000000",
},
{
types.UUID(uuid.UUID{11, 22, 33, 44, 55, 66, 77, 88, 99}),
"0b16212c-3742-4d58-6300-000000000000",
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, UuidType.String(), test.input), func(t *testing.T) {
output, err := UuidType.ConvertNomsValueToValue(test.input)
require.NoError(t, err)
require.Equal(t, test.output, output)
})
}
}
func TestUuidConvertValueToNomsValue(t *testing.T) {
tests := []struct {
input interface{}
output types.UUID
expectedErr bool
}{
{
uuid.UUID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
types.UUID(uuid.UUID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}),
false,
},
{
"01020304-0506-0708-090a-0b0c0d0e0f10",
types.UUID(uuid.UUID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}),
false,
},
{
int8(1),
types.UUID{},
true,
},
{
int16(1),
types.UUID{},
true,
},
{
int32(1),
types.UUID{},
true,
},
{
int64(1),
types.UUID{},
true,
},
{
uint8(1),
types.UUID{},
true,
},
{
uint16(1),
types.UUID{},
true,
},
{
uint32(1),
types.UUID{},
true,
},
{
uint64(1),
types.UUID{},
true,
},
{
false,
types.UUID{},
true,
},
{
"something",
types.UUID{},
true,
},
{
"",
types.UUID{},
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, UuidType.String(), test.input), func(t *testing.T) {
output, err := UuidType.ConvertValueToNomsValue(test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output, "%v\n%v", test.output, output)
} else {
assert.Error(t, err)
}
})
}
}
func TestUuidFormatValue(t *testing.T) {
tests := []struct {
input types.UUID
output string
}{
{
types.UUID(uuid.UUID{0}),
"00000000-0000-0000-0000-000000000000",
},
{
types.UUID(uuid.UUID{1, 2, 3, 4}),
"01020304-0000-0000-0000-000000000000",
},
{
types.UUID(uuid.UUID{11, 22, 33, 44, 55, 66, 77, 88, 99}),
"0b16212c-3742-4d58-6300-000000000000",
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, UuidType.String(), test.input), func(t *testing.T) {
output, err := UuidType.FormatValue(test.input)
require.NoError(t, err)
require.Equal(t, test.output, *output)
})
}
}
func TestUuidParseValue(t *testing.T) {
tests := []struct {
input string
output types.UUID
expectedErr bool
}{
{
"01020304-0000-0000-0000-000000000000",
types.UUID(uuid.UUID{1, 2, 3, 4}),
false,
},
{
"01020304-0506-0708-090a-0b0c0d0e0f10",
types.UUID(uuid.UUID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}),
false,
},
{
"something",
types.UUID{},
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, UuidType.String(), test.input), func(t *testing.T) {
output, err := UuidType.ParseValue(&test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}

View File

@@ -0,0 +1,48 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"testing"
"github.com/src-d/go-mysql-server/sql"
"github.com/stretchr/testify/require"
"vitess.io/vitess/go/sqltypes"
)
//TODO: add some basic tests once the storage format has been decided
func generateVarBinaryTypes(t *testing.T, numOfTypes uint16) []TypeInfo {
var res []TypeInfo
loop(t, 1, 500, numOfTypes, func(i int64) {
pad := false
if i%2 == 0 {
pad = true
}
res = append(res, generateVarBinaryType(t, i, pad))
})
return res
}
func generateVarBinaryType(t *testing.T, length int64, pad bool) *varBinaryType {
require.True(t, length > 0)
if pad {
t, err := sql.CreateBinary(sqltypes.Binary, length)
if err == nil {
return &varBinaryType{t}
}
}
return &varBinaryType{sql.MustCreateBinary(sqltypes.VarBinary, length)}
}

View File

@@ -0,0 +1,289 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"fmt"
"testing"
"time"
"github.com/src-d/go-mysql-server/sql"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"vitess.io/vitess/go/sqltypes"
"github.com/liquidata-inc/dolt/go/store/types"
)
func TestVarStringConvertNomsValueToValue(t *testing.T) {
tests := []struct {
typ *varStringType
input types.String
output string
expectedErr bool
}{
{
generateVarStringType(t, 10, false),
"0 ",
"0 ",
false,
},
{
generateVarStringType(t, 10, true),
"0 ",
"0",
false,
},
{
generateVarStringType(t, 80, false),
"this is some text that will be returned",
"this is some text that will be returned",
false,
},
{
&varStringType{sql.CreateLongText(sql.Collation_Default)},
" This is a sentence. ",
" This is a sentence. ",
false,
},
{
generateVarStringType(t, 2, false),
"yay",
"",
true,
},
{
generateVarStringType(t, 2, true),
"yey",
"",
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ConvertNomsValueToValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, output)
}
})
}
}
func TestVarStringConvertValueToNomsValue(t *testing.T) {
tests := []struct {
typ *varStringType
input interface{}
output types.String
expectedErr bool
}{
{
generateVarStringType(t, 10, false),
"0 ",
"0 ",
false,
},
{
generateVarStringType(t, 10, true),
[]byte("0 "),
"0 ", // converting to NomsValue counts as storage, thus we don't trim then
false,
},
{
generateVarStringType(t, 80, false),
int64(28354),
"28354",
false,
},
{
&varStringType{sql.CreateLongText(sql.Collation_Default)},
float32(3724.75),
"3724.75",
false,
},
{
generateVarStringType(t, 80, false),
time.Date(2030, 1, 2, 4, 6, 3, 472382485, time.UTC),
"2030-01-02 04:06:03.472382",
false,
},
{
generateVarStringType(t, 2, true),
"yey",
"",
true,
},
{
generateVarStringType(t, 2, true),
int32(382),
"",
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ConvertValueToNomsValue(test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}
func TestVarStringFormatValue(t *testing.T) {
tests := []struct {
typ *varStringType
input types.String
output string
expectedErr bool
}{
{
generateVarStringType(t, 10, false),
"0 ",
"0 ",
false,
},
{
generateVarStringType(t, 10, true),
"0 ",
"0",
false,
},
{
generateVarStringType(t, 80, false),
"this is some text that will be returned",
"this is some text that will be returned",
false,
},
{
&varStringType{sql.CreateLongText(sql.Collation_Default)},
" This is a sentence. ",
" This is a sentence. ",
false,
},
{
generateVarStringType(t, 2, false),
"yay",
"",
true,
},
{
generateVarStringType(t, 2, true),
"yey",
"",
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.FormatValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, *output)
}
})
}
}
func TestVarStringParseValue(t *testing.T) {
tests := []struct {
typ *varStringType
input string
output types.String
expectedErr bool
}{
{
generateVarStringType(t, 10, false),
"0 ",
"0 ",
false,
},
{
generateVarStringType(t, 10, true),
"0 ",
"0 ", // converting to NomsValue counts as storage, thus we don't trim then
false,
},
{
generateVarStringType(t, 80, false),
"this is some text that will be returned",
"this is some text that will be returned",
false,
},
{
&varStringType{sql.CreateLongText(sql.Collation_Default)},
" This is a sentence. ",
" This is a sentence. ",
false,
},
{
generateVarStringType(t, 2, false),
"yay",
"",
true,
},
{
generateVarStringType(t, 2, true),
"yey",
"",
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, test.typ.String(), test.input), func(t *testing.T) {
output, err := test.typ.ParseValue(&test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}
func generateVarStringTypes(t *testing.T, numOfTypes uint16) []TypeInfo {
var res []TypeInfo
loop(t, 1, 500, numOfTypes, func(i int64) {
rts := false
if i%2 == 0 {
rts = true
}
res = append(res, generateVarStringType(t, i, rts))
})
return res
}
func generateVarStringType(t *testing.T, length int64, rts bool) *varStringType {
require.True(t, length > 0)
if rts {
t, err := sql.CreateStringWithDefaults(sqltypes.Char, length)
if err == nil {
return &varStringType{t}
}
}
return &varStringType{sql.MustCreateStringWithDefaults(sqltypes.VarChar, length)}
}

View File

@@ -0,0 +1,210 @@
// Copyright 2020 Liquidata, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package typeinfo
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/liquidata-inc/dolt/go/store/types"
)
func TestYearConvertNomsValueToValue(t *testing.T) {
tests := []struct {
input types.Int
output int16
expectedErr bool
}{
{
0,
0,
false,
},
{
1901,
1901,
false,
},
{
2000,
2000,
false,
},
{
2155,
2155,
false,
},
{
3000,
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, YearType.String(), test.input), func(t *testing.T) {
output, err := YearType.ConvertNomsValueToValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, output)
}
})
}
}
func TestYearConvertValueToNomsValue(t *testing.T) {
tests := []struct {
input interface{}
output types.Int
expectedErr bool
}{
{
time.Date(2001, 1, 1, 0, 0, 0, 0, time.UTC),
2001,
false,
},
{
int8(70),
1970,
false,
},
{
uint64(89),
1989,
false,
},
{
"5",
2005,
false,
},
{
float32(7884.3),
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, YearType.String(), test.input), func(t *testing.T) {
output, err := YearType.ConvertValueToNomsValue(test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}
func TestYearFormatValue(t *testing.T) {
tests := []struct {
input types.Int
output string
expectedErr bool
}{
{
1,
"2001",
false,
},
{
1901,
"1901",
false,
},
{
2000,
"2000",
false,
},
{
89,
"1989",
false,
},
{
3000,
"",
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, YearType.String(), test.input), func(t *testing.T) {
output, err := YearType.FormatValue(test.input)
if test.expectedErr {
assert.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, test.output, *output)
}
})
}
}
func TestYearParseValue(t *testing.T) {
tests := []struct {
input string
output types.Int
expectedErr bool
}{
{
"2001",
2001,
false,
},
{
"1901",
1901,
false,
},
{
"2000",
2000,
false,
},
{
"89",
1989,
false,
},
{
"3000",
0,
true,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf(`%v %v`, YearType.String(), test.input), func(t *testing.T) {
output, err := YearType.ParseValue(&test.input)
if !test.expectedErr {
require.NoError(t, err)
assert.Equal(t, test.output, output)
} else {
assert.Error(t, err)
}
})
}
}