Browse Source

More test cases; coverage to 96%

Viktor Söderqvist 10 years ago
parent
commit
a1d7bce054
2 changed files with 70 additions and 37 deletions
  1. 7 11
      src/mysql_protocol.erl
  2. 63 26
      test/mysql_tests.erl

+ 7 - 11
src/mysql_protocol.erl

@@ -890,7 +890,7 @@ parse_packet_header(<<PacketLength:24/little-integer, SeqNum:8/integer>>) ->
 add_packet_headers(PacketBody, SeqNum) ->
 add_packet_headers(PacketBody, SeqNum) ->
     Bin = iolist_to_binary(PacketBody),
     Bin = iolist_to_binary(PacketBody),
     Size = size(Bin),
     Size = size(Bin),
-    SeqNum1 = (SeqNum + 1) rem 16#100,
+    SeqNum1 = (SeqNum + 1) band 16#ff,
     %% Todo: implement the case when Size >= 16#ffffff.
     %% Todo: implement the case when Size >= 16#ffffff.
     if Size < 16#ffffff ->
     if Size < 16#ffffff ->
         {[<<Size:24/little, SeqNum:8>>, Bin], SeqNum1}
         {[<<Size:24/little, SeqNum:8>>, Bin], SeqNum1}
@@ -969,16 +969,12 @@ lenenc_int(<<16#fe:8, Value:64/little, Rest/binary>>) -> {Value, Rest}.
 %% Length-encoded-integer encode. Appends the encoded value to Acc.
 %% Length-encoded-integer encode. Appends the encoded value to Acc.
 %% Values not representable in 64 bits are not accepted.
 %% Values not representable in 64 bits are not accepted.
 -spec lenenc_int_encode(0..16#ffffffffffffffff) -> binary().
 -spec lenenc_int_encode(0..16#ffffffffffffffff) -> binary().
-lenenc_int_encode(Value) when Value < 0 ->
-    error(badarg);
-lenenc_int_encode(Value) when Value < 251 ->
-    <<Value>>;
-lenenc_int_encode(Value) when Value =< 16#ffff ->
-    <<16#fc, Value:16/little>>;
-lenenc_int_encode(Value) when Value =< 16#ffffff ->
-    <<16#fd, Value:24/little>>;
-lenenc_int_encode(Value) when Value =< 16#ffffffffffffffff ->
-    <<16#fe, Value:64/little>>.
+lenenc_int_encode(Value) when Value >= 0 ->
+    if Value < 251 -> <<Value>>;
+       Value =< 16#ffff -> <<16#fc, Value:16/little>>;
+       Value =< 16#ffffff -> <<16#fd, Value:24/little>>;
+       Value =< 16#ffffffffffffffff -> <<16#fe, Value:64/little>>
+    end.
 
 
 %% lenenc_str/1 decodes length-encoded-string values
 %% lenenc_str/1 decodes length-encoded-string values
 -spec lenenc_str(Input :: binary()) -> {String :: binary(), Rest :: binary()}.
 -spec lenenc_str(Input :: binary()) -> {String :: binary(), Rest :: binary()}.

+ 63 - 26
test/mysql_tests.erl

@@ -29,7 +29,9 @@
                           "  bl BLOB,"
                           "  bl BLOB,"
                           "  tx TEXT NOT NULL," %% No default value
                           "  tx TEXT NOT NULL," %% No default value
                           "  f FLOAT,"
                           "  f FLOAT,"
+                          "  d DOUBLE,"
                           "  dc DECIMAL(5,3),"
                           "  dc DECIMAL(5,3),"
+                          "  y YEAR,"
                           "  ti TIME,"
                           "  ti TIME,"
                           "  ts TIMESTAMP,"
                           "  ts TIMESTAMP,"
                           "  da DATE,"
                           "  da DATE,"
@@ -74,7 +76,9 @@ query_test_() ->
              fun decimal/1,
              fun decimal/1,
              fun int/1,
              fun int/1,
              fun bit/1,
              fun bit/1,
+             fun date/1,
              fun time/1,
              fun time/1,
+             fun datetime/1,
              fun microseconds/1]}}.
              fun microseconds/1]}}.
 
 
 connect_with_db(_Pid) ->
 connect_with_db(_Pid) ->
@@ -110,9 +114,9 @@ basic_queries(Pid) ->
 
 
 text_protocol(Pid) ->
 text_protocol(Pid) ->
     ok = mysql:query(Pid, ?create_table_t),
     ok = mysql:query(Pid, ?create_table_t),
-    ok = mysql:query(Pid, <<"INSERT INTO t (bl, f, dc, ti, ts, da, c)"
-                            " VALUES ('blob', 3.14, 3.14, '00:22:11',"
-                            " '2014-11-03 00:22:24', '2014-11-03',"
+    ok = mysql:query(Pid, <<"INSERT INTO t (bl, f, d, dc, y, ti, ts, da, c)"
+                            " VALUES ('blob', 3.14, 3.14, 3.14, 2014,"
+                            "'00:22:11', '2014-11-03 00:22:24', '2014-11-03',"
                             " NULL)">>),
                             " NULL)">>),
     ?assertEqual(1, mysql:warning_count(Pid)), %% tx has no default value
     ?assertEqual(1, mysql:warning_count(Pid)), %% tx has no default value
     ?assertEqual(1, mysql:insert_id(Pid)),     %% auto_increment starts from 1
     ?assertEqual(1, mysql:insert_id(Pid)),     %% auto_increment starts from 1
@@ -120,45 +124,37 @@ text_protocol(Pid) ->
 
 
     %% select
     %% select
     {ok, Columns, Rows} = mysql:query(Pid, <<"SELECT * FROM t">>),
     {ok, Columns, Rows} = mysql:query(Pid, <<"SELECT * FROM t">>),
-    ?assertEqual([<<"id">>, <<"bl">>, <<"tx">>, <<"f">>, <<"dc">>, <<"ti">>,
-                  <<"ts">>, <<"da">>, <<"c">>], Columns),
-    ?assertEqual([[1, <<"blob">>, <<>>, 3.14, 3.14, {0, {0, 22, 11}},
+    ?assertEqual([<<"id">>, <<"bl">>, <<"tx">>, <<"f">>, <<"d">>, <<"dc">>,
+                  <<"y">>, <<"ti">>, <<"ts">>, <<"da">>, <<"c">>], Columns),
+    ?assertEqual([[1, <<"blob">>, <<>>, 3.14, 3.14, 3.14,
+                   2014, {0, {0, 22, 11}},
                    {{2014, 11, 03}, {00, 22, 24}}, {2014, 11, 03}, null]],
                    {{2014, 11, 03}, {00, 22, 24}}, {2014, 11, 03}, null]],
                  Rows),
                  Rows),
 
 
-    %% TODO:
-    %% * More types: BIT, SET, ENUM, GEOMETRY
-
     ok = mysql:query(Pid, <<"DROP TABLE t">>).
     ok = mysql:query(Pid, <<"DROP TABLE t">>).
 
 
 binary_protocol(Pid) ->
 binary_protocol(Pid) ->
     ok = mysql:query(Pid, ?create_table_t),
     ok = mysql:query(Pid, ?create_table_t),
     %% The same queries as in the text protocol. Expect the same results.
     %% The same queries as in the text protocol. Expect the same results.
-    {ok, Ins} = mysql:prepare(Pid, <<"INSERT INTO t (bl, f, dc, ti, ts, da, c)"
-                                     " VALUES (?, ?, ?, ?, ?, ?, ?)">>),
+    {ok, Ins} = mysql:prepare(Pid, <<"INSERT INTO t (bl, f, d, dc, y, ti,"
+                                     " ts, da, c)"
+                                     " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)">>),
 
 
-    ok = mysql:execute(Pid, Ins, [<<"blob">>, 3.14, 3.14,
-                                  {0, {0, 22, 11}}, 
+    ok = mysql:execute(Pid, Ins, [<<"blob">>, 3.14, 3.14, 3.14,
+                                  2014, {0, {0, 22, 11}}, 
                                   {{2014, 11, 03}, {0, 22, 24}},
                                   {{2014, 11, 03}, {0, 22, 24}},
                                   {2014, 11, 03}, null]),
                                   {2014, 11, 03}, null]),
 
 
-    %% TODO: Put the expected result in a macro to make sure they are identical
-    %% for the text and the binary protocol tests.
-
     {ok, Stmt} = mysql:prepare(Pid, <<"SELECT * FROM t WHERE id=?">>),
     {ok, Stmt} = mysql:prepare(Pid, <<"SELECT * FROM t WHERE id=?">>),
     {ok, Columns, Rows} = mysql:execute(Pid, Stmt, [1]),
     {ok, Columns, Rows} = mysql:execute(Pid, Stmt, [1]),
-    ?assertEqual([<<"id">>, <<"bl">>, <<"tx">>, <<"f">>, <<"dc">>, <<"ti">>,
+    ?assertEqual([<<"id">>, <<"bl">>, <<"tx">>, <<"f">>, <<"d">>, <<"dc">>,
+                  <<"y">>, <<"ti">>,
                   <<"ts">>, <<"da">>, <<"c">>], Columns),
                   <<"ts">>, <<"da">>, <<"c">>], Columns),
-    ?assertEqual([[1, <<"blob">>, <<>>, 3.14, 3.14,
-                   {0, {0, 22, 11}},
+    ?assertEqual([[1, <<"blob">>, <<>>, 3.14, 3.14, 3.14,
+                   2014, {0, {0, 22, 11}},
                    {{2014, 11, 03}, {00, 22, 24}}, {2014, 11, 03}, null]],
                    {{2014, 11, 03}, {00, 22, 24}}, {2014, 11, 03}, null]],
                  Rows),
                  Rows),
 
 
-    %% TODO: Both send and receive the following values:
-    %% * Values for all types
-    %% * Negative numbers for all integer types
-    %% * Integer overflow
-
     ok = mysql:query(Pid, <<"DROP TABLE t">>).
     ok = mysql:query(Pid, <<"DROP TABLE t">>).
 
 
 float_rounding(Pid) ->
 float_rounding(Pid) ->
@@ -254,7 +250,19 @@ int(Pid) ->
     ok = mysql:query(Pid, "CREATE TABLE tint (i TINYINT)"),
     ok = mysql:query(Pid, "CREATE TABLE tint (i TINYINT)"),
     write_read_text_binary(Pid, 127, <<"1000">>, <<"tint">>, <<"i">>),
     write_read_text_binary(Pid, 127, <<"1000">>, <<"tint">>, <<"i">>),
     write_read_text_binary(Pid, -128, <<"-1000">>, <<"tint">>, <<"i">>),
     write_read_text_binary(Pid, -128, <<"-1000">>, <<"tint">>, <<"i">>),
-    ok = mysql:query(Pid, "DROP TABLE tint").
+    ok = mysql:query(Pid, "DROP TABLE tint"),
+    %% SMALLINT
+    ok = mysql:query(Pid, "CREATE TABLE sint (i SMALLINT)"),
+    write_read_text_binary(Pid, 32000, <<"32000">>, <<"sint">>, <<"i">>),
+    write_read_text_binary(Pid, -32000, <<"-32000">>, <<"sint">>, <<"i">>),
+    ok = mysql:query(Pid, "DROP TABLE sint"),
+    %% BIGINT
+    ok = mysql:query(Pid, "CREATE TABLE bint (i BIGINT)"),
+    write_read_text_binary(Pid, 123456789012, <<"123456789012">>,
+                           <<"bint">>, <<"i">>),
+    write_read_text_binary(Pid, -123456789012, <<"-123456789012">>,
+                           <<"bint">>, <<"i">>),
+    ok = mysql:query(Pid, "DROP TABLE bint").
 
 
 %% The BIT(N) datatype in MySQL 5.0.3 and later: the equivallent to bitstring()
 %% The BIT(N) datatype in MySQL 5.0.3 and later: the equivallent to bitstring()
 bit(Pid) ->
 bit(Pid) ->
@@ -265,6 +273,17 @@ bit(Pid) ->
                            <<"bits">>, <<"b">>),
                            <<"bits">>, <<"b">>),
     ok = mysql:query(Pid, "DROP TABLE bits").
     ok = mysql:query(Pid, "DROP TABLE bits").
 
 
+date(Pid) ->
+    ok = mysql:query(Pid, "CREATE TABLE d (d DATE)"),
+    lists:foreach(
+        fun ({Value, SqlLiteral}) ->
+            write_read_text_binary(Pid, Value, SqlLiteral, <<"d">>, <<"d">>)
+        end,
+        [{{2014, 11, 03}, <<"'2014-11-03'">>},
+         {{0, 0, 0},      <<"'0000-00-00'">>}]
+    ),
+    ok = mysql:query(Pid, "DROP TABLE d").
+
 %% Test TIME value representation. There are a few things to check.
 %% Test TIME value representation. There are a few things to check.
 time(Pid) ->
 time(Pid) ->
     ok = mysql:query(Pid, "CREATE TABLE tm (tm TIME)"),
     ok = mysql:query(Pid, "CREATE TABLE tm (tm TIME)"),
@@ -278,10 +297,28 @@ time(Pid) ->
          {{-1, {23, 59, 0}},  <<"'-00:01:00'">>},
          {{-1, {23, 59, 0}},  <<"'-00:01:00'">>},
          {{-1, {23, 0, 0}},   <<"'-01:00:00'">>},
          {{-1, {23, 0, 0}},   <<"'-01:00:00'">>},
          {{-1, {0, 0, 0}},    <<"'-24:00:00'">>},
          {{-1, {0, 0, 0}},    <<"'-24:00:00'">>},
-         {{-5, {10, 0, 0}},  <<"'-110:00:00'">>}]
+         {{-5, {10, 0, 0}},  <<"'-110:00:00'">>},
+         {{0, {0, 0, 0}},      <<"'00:00:00'">>}]
     ),
     ),
+    %% Zero seconds as a float.
+    ok = mysql:query(Pid, "INSERT INTO tm (tm) VALUES (?)",
+                     [{-1, {1, 2, 0.0}}]),
+    ?assertEqual({ok, [<<"tm">>], [[{-1, {1, 2, 0}}]]},
+                 mysql:query(Pid, "SELECT tm FROM tm")),
     ok = mysql:query(Pid, "DROP TABLE tm").
     ok = mysql:query(Pid, "DROP TABLE tm").
 
 
+datetime(Pid) ->
+    ok = mysql:query(Pid, "CREATE TABLE dt (dt DATETIME)"),
+    lists:foreach(
+        fun ({Value, SqlLiteral}) ->
+            write_read_text_binary(Pid, Value, SqlLiteral, <<"dt">>, <<"dt">>)
+        end,
+        [{{{2014, 12, 14}, {19, 39, 20}},   <<"'2014-12-14 19:39:20'">>},
+         {{{2014, 12, 14}, {0, 0, 0}},      <<"'2014-12-14 00:00:00'">>},
+         {{{0, 0, 0}, {0, 0, 0}},           <<"'0000-00-00 00:00:00'">>}]
+    ),
+    ok = mysql:query(Pid, "DROP TABLE dt").
+
 microseconds(Pid) ->
 microseconds(Pid) ->
     %% Check whether we have the required version for this testcase.
     %% Check whether we have the required version for this testcase.
     {ok, _, [[Version]]} = mysql:query(Pid, <<"SELECT @@version">>),
     {ok, _, [[Version]]} = mysql:query(Pid, <<"SELECT @@version">>),