Skip to content

Commit 5314fb8

Browse files
committed
✅ increase test coverage
1 parent 01ad610 commit 5314fb8

File tree

3 files changed

+281
-0
lines changed

3 files changed

+281
-0
lines changed

tests/unit/debug_info_test.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import platform
2+
import sqlite3
3+
import sys
4+
from unittest.mock import MagicMock, patch
5+
6+
import pytest
7+
8+
from sqlite3_to_mysql.debug_info import _implementation, _mysql_version, info
9+
10+
11+
class TestDebugInfo:
12+
def test_implementation_cpython(self) -> None:
13+
"""Test _implementation function with CPython."""
14+
with patch("platform.python_implementation", return_value="CPython"):
15+
with patch("platform.python_version", return_value="3.8.0"):
16+
assert _implementation() == "CPython 3.8.0"
17+
18+
def test_implementation_pypy(self) -> None:
19+
"""Test _implementation function with PyPy."""
20+
with patch("platform.python_implementation", return_value="PyPy"):
21+
# Mock sys.pypy_version_info
22+
mock_version_info = MagicMock()
23+
mock_version_info.major = 7
24+
mock_version_info.minor = 3
25+
mock_version_info.micro = 1
26+
mock_version_info.releaselevel = "final"
27+
28+
with patch.object(sys, "pypy_version_info", mock_version_info, create=True):
29+
assert _implementation() == "PyPy 7.3.1"
30+
31+
def test_implementation_pypy_non_final(self) -> None:
32+
"""Test _implementation function with PyPy non-final release."""
33+
with patch("platform.python_implementation", return_value="PyPy"):
34+
# Mock sys.pypy_version_info
35+
mock_version_info = MagicMock()
36+
mock_version_info.major = 7
37+
mock_version_info.minor = 3
38+
mock_version_info.micro = 1
39+
mock_version_info.releaselevel = "beta"
40+
41+
with patch.object(sys, "pypy_version_info", mock_version_info, create=True):
42+
assert _implementation() == "PyPy 7.3.1beta"
43+
44+
def test_implementation_jython(self) -> None:
45+
"""Test _implementation function with Jython."""
46+
with patch("platform.python_implementation", return_value="Jython"):
47+
with patch("platform.python_version", return_value="2.7.2"):
48+
assert _implementation() == "Jython 2.7.2"
49+
50+
def test_implementation_ironpython(self) -> None:
51+
"""Test _implementation function with IronPython."""
52+
with patch("platform.python_implementation", return_value="IronPython"):
53+
with patch("platform.python_version", return_value="2.7.9"):
54+
assert _implementation() == "IronPython 2.7.9"
55+
56+
def test_implementation_unknown(self) -> None:
57+
"""Test _implementation function with unknown implementation."""
58+
with patch("platform.python_implementation", return_value="Unknown"):
59+
assert _implementation() == "Unknown Unknown"
60+
61+
def test_mysql_version_found(self) -> None:
62+
"""Test _mysql_version function when MySQL is found."""
63+
with patch("sqlite3_to_mysql.debug_info.which", return_value="/usr/bin/mysql"):
64+
with patch("sqlite3_to_mysql.debug_info.check_output", return_value=b"mysql Ver 8.0.23"):
65+
assert _mysql_version() == "mysql Ver 8.0.23"
66+
67+
def test_mysql_version_decode_error(self) -> None:
68+
"""Test _mysql_version function with decode error."""
69+
with patch("sqlite3_to_mysql.debug_info.which", return_value="/usr/bin/mysql"):
70+
with patch("sqlite3_to_mysql.debug_info.check_output", return_value=b"\xff\xfe"):
71+
# This should trigger a UnicodeDecodeError
72+
result = _mysql_version()
73+
assert "b'" in result # Should contain the string representation of bytes
74+
75+
def test_mysql_version_exception(self) -> None:
76+
"""Test _mysql_version function with exception."""
77+
with patch("sqlite3_to_mysql.debug_info.which", return_value="/usr/bin/mysql"):
78+
with patch("sqlite3_to_mysql.debug_info.check_output", side_effect=Exception("Command failed")):
79+
assert _mysql_version() == "MySQL client not found on the system"
80+
81+
def test_mysql_version_not_found(self) -> None:
82+
"""Test _mysql_version function when MySQL is not found."""
83+
with patch("sqlite3_to_mysql.debug_info.which", return_value=None):
84+
assert _mysql_version() == "MySQL client not found on the system"
85+
86+
def test_info(self) -> None:
87+
"""Test info function."""
88+
with patch("platform.system", return_value="Linux"):
89+
with patch("platform.release", return_value="5.4.0"):
90+
with patch("sqlite3_to_mysql.debug_info._implementation", return_value="CPython 3.8.0"):
91+
with patch("sqlite3_to_mysql.debug_info._mysql_version", return_value="mysql Ver 8.0.23"):
92+
with patch.object(sqlite3, "sqlite_version", "3.32.3"):
93+
result = info()
94+
assert result[0][0] == "sqlite3-to-mysql"
95+
assert result[2][0] == "Operating System"
96+
assert result[2][1] == "Linux 5.4.0"
97+
assert result[3][0] == "Python"
98+
assert result[3][1] == "CPython 3.8.0"
99+
assert result[4][0] == "MySQL"
100+
assert result[4][1] == "mysql Ver 8.0.23"
101+
assert result[5][0] == "SQLite"
102+
assert result[5][1] == "3.32.3"
103+
104+
def test_info_platform_error(self) -> None:
105+
"""Test info function with platform error."""
106+
with patch("platform.system", side_effect=IOError("Platform error")):
107+
with patch("sqlite3_to_mysql.debug_info._implementation", return_value="CPython 3.8.0"):
108+
with patch("sqlite3_to_mysql.debug_info._mysql_version", return_value="mysql Ver 8.0.23"):
109+
with patch.object(sqlite3, "sqlite_version", "3.32.3"):
110+
result = info()
111+
assert result[0][0] == "sqlite3-to-mysql"
112+
assert result[2][0] == "Operating System"
113+
assert result[2][1] == "Unknown"
114+
assert result[3][0] == "Python"
115+
assert result[3][1] == "CPython 3.8.0"
116+
assert result[4][0] == "MySQL"
117+
assert result[4][1] == "mysql Ver 8.0.23"
118+
assert result[5][0] == "SQLite"
119+
assert result[5][1] == "3.32.3"

tests/unit/mysql_utils_test.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
from unittest.mock import MagicMock, patch
2+
13
import pytest
24
from packaging.version import Version
35

46
from sqlite3_to_mysql.mysql_utils import (
7+
CharSet,
58
check_mysql_fulltext_support,
69
check_mysql_json_support,
710
check_mysql_values_alias_support,
811
get_mysql_version,
12+
mysql_supported_character_sets,
913
safe_identifier_length,
1014
)
1115

@@ -85,3 +89,68 @@ def test_check_mysql_fulltext_support(self, version_string: str, expected: bool)
8589
)
8690
def test_safe_identifier_length(self, identifier: str, expected: str) -> None:
8791
assert safe_identifier_length(identifier) == expected
92+
93+
def test_mysql_supported_character_sets_with_charset(self) -> None:
94+
"""Test mysql_supported_character_sets function with a specific charset."""
95+
# Mock the MYSQL_CHARACTER_SETS list
96+
mock_character_sets = [
97+
None, # Index 0
98+
("utf8", "utf8_general_ci", True), # Index 1
99+
("latin1", "latin1_swedish_ci", True), # Index 2
100+
]
101+
102+
with patch("sqlite3_to_mysql.mysql_utils.MYSQL_CHARACTER_SETS", mock_character_sets):
103+
# Test with a charset that exists
104+
result = list(mysql_supported_character_sets(charset="utf8"))
105+
assert len(result) == 1
106+
assert result[0] == CharSet(1, "utf8", "utf8_general_ci")
107+
108+
# Test with a charset that doesn't exist
109+
result = list(mysql_supported_character_sets(charset="unknown"))
110+
assert len(result) == 0
111+
112+
def test_mysql_supported_character_sets_without_charset(self) -> None:
113+
"""Test mysql_supported_character_sets function without a specific charset."""
114+
# Mock the MYSQL_CHARACTER_SETS list
115+
mock_character_sets = [
116+
None, # Index 0
117+
("utf8", "utf8_general_ci", True), # Index 1
118+
("latin1", "latin1_swedish_ci", True), # Index 2
119+
]
120+
121+
# Mock the CharacterSet().get_supported() method
122+
mock_get_supported = MagicMock(return_value=["utf8", "latin1"])
123+
124+
with patch("sqlite3_to_mysql.mysql_utils.MYSQL_CHARACTER_SETS", mock_character_sets):
125+
with patch("mysql.connector.CharacterSet.get_supported", mock_get_supported):
126+
result = list(mysql_supported_character_sets())
127+
# The function yields a CharSet for each combination of charset and index
128+
assert len(result) == 4
129+
assert CharSet(1, "utf8", "utf8_general_ci") in result
130+
assert CharSet(2, "utf8", "latin1_swedish_ci") in result
131+
assert CharSet(1, "latin1", "utf8_general_ci") in result
132+
assert CharSet(2, "latin1", "latin1_swedish_ci") in result
133+
134+
def test_mysql_supported_character_sets_with_keyerror(self) -> None:
135+
"""Test mysql_supported_character_sets function with KeyError."""
136+
# Mock the MYSQL_CHARACTER_SETS list with an entry that will cause a KeyError
137+
mock_character_sets = [
138+
None, # Index 0
139+
("utf8", "utf8_general_ci", True), # Index 1
140+
None, # Index 2 - This will cause a KeyError when accessed
141+
]
142+
143+
with patch("sqlite3_to_mysql.mysql_utils.MYSQL_CHARACTER_SETS", mock_character_sets):
144+
# Test with a charset that exists but will cause a KeyError
145+
result = list(mysql_supported_character_sets(charset="utf8"))
146+
assert len(result) == 1
147+
assert result[0] == CharSet(1, "utf8", "utf8_general_ci")
148+
149+
# Mock for testing without charset
150+
mock_get_supported = MagicMock(return_value=["utf8"])
151+
152+
with patch("sqlite3_to_mysql.mysql_utils.MYSQL_CHARACTER_SETS", mock_character_sets):
153+
with patch("mysql.connector.CharacterSet.get_supported", mock_get_supported):
154+
result = list(mysql_supported_character_sets())
155+
assert len(result) == 1
156+
assert CharSet(1, "utf8", "utf8_general_ci") in result

tests/unit/sqlite_utils_test.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
from datetime import date, timedelta
2+
from decimal import Decimal
3+
from unittest.mock import patch
4+
5+
import pytest
6+
from dateutil.parser import ParserError
7+
from packaging.version import Version
8+
9+
from sqlite3_to_mysql.sqlite_utils import (
10+
adapt_decimal,
11+
adapt_timedelta,
12+
check_sqlite_table_xinfo_support,
13+
convert_date,
14+
convert_decimal,
15+
convert_timedelta,
16+
unicase_compare,
17+
)
18+
19+
20+
class TestSQLiteUtils:
21+
def test_adapt_decimal(self) -> None:
22+
"""Test adapt_decimal function."""
23+
assert adapt_decimal(Decimal("123.45")) == "123.45"
24+
assert adapt_decimal(Decimal("0")) == "0"
25+
assert adapt_decimal(Decimal("-123.45")) == "-123.45"
26+
27+
def test_convert_decimal(self) -> None:
28+
"""Test convert_decimal function."""
29+
assert convert_decimal(b"123.45") == Decimal("123.45")
30+
assert convert_decimal(b"0") == Decimal("0")
31+
assert convert_decimal(b"-123.45") == Decimal("-123.45")
32+
33+
def test_adapt_timedelta(self) -> None:
34+
"""Test adapt_timedelta function."""
35+
assert adapt_timedelta(timedelta(hours=1, minutes=30, seconds=45)) == "01:30:45"
36+
assert adapt_timedelta(timedelta(hours=0, minutes=0, seconds=0)) == "00:00:00"
37+
assert adapt_timedelta(timedelta(hours=100, minutes=30, seconds=45)) == "100:30:45"
38+
39+
def test_convert_timedelta(self) -> None:
40+
"""Test convert_timedelta function."""
41+
assert convert_timedelta(b"01:30:45") == timedelta(hours=1, minutes=30, seconds=45)
42+
assert convert_timedelta(b"00:00:00") == timedelta(hours=0, minutes=0, seconds=0)
43+
assert convert_timedelta(b"100:30:45") == timedelta(hours=100, minutes=30, seconds=45)
44+
45+
def test_unicase_compare(self) -> None:
46+
"""Test unicase_compare function."""
47+
# Test with lowercase strings
48+
assert unicase_compare("abc", "def") == -1
49+
assert unicase_compare("def", "abc") == 1
50+
assert unicase_compare("abc", "abc") == 0
51+
52+
# Test with mixed case strings
53+
assert unicase_compare("Abc", "def") == -1
54+
assert unicase_compare("DEF", "abc") == 1
55+
assert unicase_compare("ABC", "abc") == 0
56+
57+
# Test with accented characters
58+
assert unicase_compare("café", "cafe") == 0
59+
assert unicase_compare("café", "cafz") == -1
60+
assert unicase_compare("cafz", "café") == 1
61+
62+
def test_convert_date(self) -> None:
63+
"""Test convert_date function."""
64+
# Test with string
65+
assert convert_date("2020-01-01") == date(2020, 1, 1)
66+
assert convert_date("2020/01/01") == date(2020, 1, 1)
67+
assert convert_date("Jan 1, 2020") == date(2020, 1, 1)
68+
69+
# Test with bytes
70+
assert convert_date(b"2020-01-01") == date(2020, 1, 1)
71+
assert convert_date(b"2020/01/01") == date(2020, 1, 1)
72+
assert convert_date(b"Jan 1, 2020") == date(2020, 1, 1)
73+
74+
def test_convert_date_error(self) -> None:
75+
"""Test convert_date function with invalid date."""
76+
with pytest.raises(ValueError):
77+
convert_date("not a date")
78+
79+
with pytest.raises(ValueError):
80+
convert_date(b"not a date")
81+
82+
@pytest.mark.parametrize(
83+
"version_string,expected",
84+
[
85+
("3.25.0", False),
86+
("3.26.0", True),
87+
("3.27.0", True),
88+
("4.0.0", True),
89+
],
90+
)
91+
def test_check_sqlite_table_xinfo_support(self, version_string: str, expected: bool) -> None:
92+
"""Test check_sqlite_table_xinfo_support function."""
93+
assert check_sqlite_table_xinfo_support(version_string) == expected

0 commit comments

Comments
 (0)