Skip to content

Commit

Permalink
fix:unittests (#2)
Browse files Browse the repository at this point in the history
* fix:unittests

* fix:unittests
  • Loading branch information
JarbasAl authored Jan 8, 2025
1 parent 36c3cd1 commit b3e5f84
Show file tree
Hide file tree
Showing 7 changed files with 335 additions and 38 deletions.
58 changes: 58 additions & 0 deletions .github/workflows/unittests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Run UnitTests
on:
pull_request:
branches:
- dev
paths-ignore:
- 'z85base91/version.py'
- '.github/**'
- '.gitignore'
- 'LICENSE'
- 'CHANGELOG.md'
- 'MANIFEST.in'
- 'README.md'
push:
branches:
- master
paths-ignore:
- 'z85base91/version.py'
- '.github/**'
- '.gitignore'
- 'LICENSE'
- 'CHANGELOG.md'
- 'MANIFEST.in'
- 'README.md'
workflow_dispatch:

jobs:
unit_tests:
strategy:
matrix:
python-version: ["3.10", "3.11" ]
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v2
- name: Set up python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install System Dependencies
run: |
sudo apt-get update
sudo apt install python3-dev swig
python -m pip install build wheel
- name: Install repo
run: |
pip install -e .
- name: Install test dependencies
run: |
pip install -r test/requirements.txt
- name: Run unittests
run: |
pytest --cov=z85base91 --cov-report xml test
- name: Upload coverage
if: "${{ matrix.python-version == '3.11' }}"
env:
CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}}
uses: codecov/codecov-action@v2
Empty file added test/__init__.py
Empty file.
2 changes: 2 additions & 0 deletions test/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pytest~=7.1
pytest-cov~=4.1
62 changes: 62 additions & 0 deletions test/test_b91.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import unittest
from z85base91 import B91


class TestB91(unittest.TestCase):
def test_encode_empty(self):
"""Test encoding an empty byte sequence."""
self.assertEqual(B91.encode(b''), b'')
self.assertEqual(B91.encode(''), b'')

def test_decode_empty(self):
"""Test decoding an empty string."""
self.assertEqual(B91.decode(''), b'')
self.assertEqual(B91.decode(b''), b'')

def test_encode_single_byte(self):
"""Test encoding a single byte."""
self.assertEqual(b'A', B91.decode(B91.encode(b'A')))
self.assertEqual(b'B', B91.decode(B91.encode('B')))
self.assertEqual(b'_~', B91.decode(B91.encode(b'_~')))
self.assertEqual(b'_~', B91.decode(B91.encode('_~')))

def test_encode_short_string(self):
"""Test encoding a short string."""
self.assertEqual(b'hello', B91.decode(B91.encode(b'hello')))
self.assertEqual(B91.decode('>OwJh>Io0Tv!lE'), b'Hello World')

def test_encode_decode_round_trip(self):
"""Test encoding and decoding round-trip."""
data = b'The quick brown fox jumps over the lazy dog.'
encoded = B91.encode(data)
decoded = B91.decode(encoded)
self.assertEqual(decoded, data)

def test_encode_unicode_string(self):
"""Test encoding a Unicode string."""
data = 'こんにちは' # Japanese for "hello"
encoded = B91.encode(data)
decoded = B91.decode(encoded)
self.assertEqual(decoded.decode('utf-8'), data)

def test_decode_invalid_character(self):
"""Test decoding with invalid Base91 characters."""
with self.assertRaises(ValueError):
B91.decode('Invalid🎉Chars')

def test_3bytes_threshold(self):
"""Test edge cases around the 88 threshold."""
data = b'\x00\x00\x00' # Minimal data
encoded = B91.encode(data)
self.assertEqual(B91.decode(encoded), data)

def test_encode_large_data(self):
"""Test encoding a large byte sequence."""
data = b'\xff' * 1000
encoded = B91.encode(data)
decoded = B91.decode(encoded)
self.assertEqual(decoded, data)


if __name__ == '__main__':
unittest.main()
62 changes: 62 additions & 0 deletions test/test_z85b.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import unittest
from z85base91 import Z85B


class TestZ85B(unittest.TestCase):
def test_encode_empty(self):
"""Test encoding an empty byte sequence."""
self.assertEqual(Z85B.encode(b''), b'')
self.assertEqual(Z85B.encode(''), b'')

def test_decode_empty(self):
"""Test decoding an empty string."""
self.assertEqual(Z85B.decode(''), b'')
self.assertEqual(Z85B.decode(b''), b'')

def test_encode_single_byte(self):
"""Test encoding a single byte."""
self.assertEqual(b'A', Z85B.decode(Z85B.encode(b'A')))
self.assertEqual(b'B', Z85B.decode(Z85B.encode('B')))
self.assertEqual(b'_~', Z85B.decode(Z85B.encode(b'_~')))
self.assertEqual(b'_~', Z85B.decode(Z85B.encode('_~')))

def test_encode_short_string(self):
"""Test encoding a short string."""
self.assertEqual(b'hello', Z85B.decode(Z85B.encode(b'hello')))
self.assertEqual(b'Hello World', Z85B.decode(Z85B.encode(b'Hello World')))

def test_encode_decode_round_trip(self):
"""Test encoding and decoding round-trip."""
data = b'The quick brown fox jumps over the lazy dog.'
encoded = Z85B.encode(data)
decoded = Z85B.decode(encoded)
self.assertEqual(decoded, data)

def test_encode_unicode_string(self):
"""Test encoding a Unicode string."""
data = 'こんにちは' # Japanese for "hello"
encoded = Z85B.encode(data)
decoded = Z85B.decode(encoded)
self.assertEqual(decoded.decode('utf-8'), data)

def test_decode_invalid_character(self):
"""Test decoding with invalid Base91 characters."""
with self.assertRaises(ValueError):
Z85B.decode('Invalid🎉Chars')

def test_edge_case_88_threshold(self):
"""Test edge cases around the 88 threshold."""
data = b'\x00\x00\x00' # Minimal data
encoded = Z85B.encode(data)
self.assertEqual(Z85B.decode(encoded), data)

def test_encode_large_data(self):
"""Test encoding a large byte sequence."""
data = b'\xff' * 1000
encoded = Z85B.encode(data)
decoded = Z85B.decode(encoded)
self.assertEqual(decoded, data)


if __name__ == '__main__':
unittest.main()
104 changes: 104 additions & 0 deletions test/test_z85p.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import unittest
from z85base91 import Z85P


class TestZ85P(unittest.TestCase):
def test_encode_empty(self):
"""Test encoding an empty byte sequence."""
self.assertEqual(Z85P.encode(b''), b'\x00')
self.assertEqual(Z85P.encode(''), b'\x00')

def test_decode_empty(self):
"""Test decoding an empty string."""
self.assertEqual(Z85P.decode(b'\x00'), b'')
self.assertEqual(Z85P.decode(''), b'')
self.assertEqual(Z85P.decode(b''), b'')

def test_encode_single_byte(self):
"""Test encoding a single byte."""
self.assertEqual(b'A', Z85P.decode(Z85P.encode(b'A')))
self.assertEqual(b'B', Z85P.decode(Z85P.encode('B')))
self.assertEqual(b'_~', Z85P.decode(Z85P.encode(b'_~')))
self.assertEqual(b'_~', Z85P.decode(Z85P.encode('_~')))

def test_encode_short_string(self):
"""Test encoding a short string."""
self.assertEqual(b'hello', Z85P.decode(Z85P.encode(b'hello')))

def test_encode_decode_round_trip(self):
"""Test encoding and decoding round-trip."""
data = b'The quick brown fox jumps over the lazy dog.'
encoded = Z85P.encode(data)
decoded = Z85P.decode(encoded)
self.assertEqual(decoded, data)

def test_encode_unicode_string(self):
"""Test encoding a Unicode string."""
data = 'こんにちは' # Japanese for "hello"
encoded = Z85P.encode(data)
decoded = Z85P.decode(encoded)
self.assertEqual(decoded.decode('utf-8'), data)

def test_decode_invalid_character(self):
"""Test decoding with invalid z85 characters."""
with self.assertRaises(ValueError):
Z85P.decode('Invalid🎉Chars')

def test_encode_large_data(self):
"""Test encoding a large byte sequence."""
data = b'\xff' * 1000
encoded = Z85P.encode(data)
decoded = Z85P.decode(encoded)
self.assertEqual(decoded, data)

def test_padding_single_byte(self):
"""Test encoding and decoding with one byte that requires padding."""
data = b'\x01' # Single byte, should get padded with 3 \x00 bytes
encoded = Z85P.encode(data)
self.assertEqual(encoded[0], 3) # Check padding byte
self.assertEqual(Z85P.decode(encoded), data)

def test_padding_two_bytes(self):
"""Test encoding and decoding with two bytes that require padding."""
data = b'\x01\x01' # Two bytes, should get padded with 2 \x00 bytes
encoded = Z85P.encode(data)
self.assertEqual(encoded[0], 2) # Check padding byte
self.assertEqual(Z85P.decode(encoded), data)

def test_padding_three_bytes(self):
"""Test encoding and decoding with three bytes that require padding."""
data = b'\x01\x01\x01' # Three bytes, should get padded with 1 \x00 byte
encoded = Z85P.encode(data)
self.assertEqual(encoded[0], 1) # Check padding byte
self.assertEqual(Z85P.decode(encoded), data)

def test_no_padding_5_bytes(self): # fails
data = b'\x01\x01\x01\x01\x01' # 5 bytes
encoded = Z85P.encode(data)
self.assertEqual(encoded[0], 3) # Check padding byte
self.assertEqual(Z85P.decode(encoded), data)

def test_no_padding_needed(self):
"""Test encoding and decoding with data that doesn't need padding."""
data = b'\x01\x01\x01\x01' # Exactly 4 bytes, no padding
encoded = Z85P.encode(data)
self.assertEqual(encoded[0], 0) # No padding
self.assertEqual(Z85P.decode(encoded), data)

def test_round_trip_padding(self):
"""Test round-trip encoding and decoding with padding."""
data = b'\x01\x01\x01' # Less than 4 bytes, needs padding
encoded = Z85P.encode(data)
decoded = Z85P.decode(encoded)
self.assertEqual(decoded, data) # Ensure padding is correctly removed

def test_padding_removal_after_decoding(self):
"""Test ensuring padding is correctly removed after decoding."""
data = b'\x01\x01\x01' # Less than 4 bytes, needs padding
encoded = Z85P.encode(data)
self.assertEqual(encoded[0], 1) # Padding size is 1
decoded = Z85P.decode(encoded)
self.assertEqual(decoded, data) # Padding should be removed

if __name__ == '__main__':
unittest.main()
Loading

0 comments on commit b3e5f84

Please sign in to comment.