Skip to content

Commit

Permalink
irc.utils, test: also remove null (\x00) in safe()
Browse files Browse the repository at this point in the history
In `test_irc_utils` suite, rewrote `test_safe` and `test_safe_bytes` to
generate a bunch more permutations of invalid characters automatically
rather than writing them all out. The horse is definitely beaten *far*
past death at this point... but the tests sure are thorough(bred).

Also renamed `test_safe_null` -> `test_safe_none` to avoid confusion;
`test_safe` and `test_safe_bytes` are the cases that check behavior with
null characters/bytes. Python's docs technically do refer to `None` as
the "null object" once or twice, but most of the docs (and most of us
devs) simply call it `None`.
  • Loading branch information
dgw committed Sep 14, 2024
1 parent 1c6aeb9 commit 1cd02c4
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 23 deletions.
8 changes: 5 additions & 3 deletions sopel/irc/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ def safe(string):
:rtype: str
:raises TypeError: when ``string`` is ``None``
This function removes newlines from a string and always returns a unicode
string (``str``), but doesn't strip or alter it in any other way::
This function removes newlines and null-bytes from a string. It will always
return a Unicode ``str``, even if given non-Unicode input, but doesn't strip
or alter the string in any other way::
>>> safe('some text\\r\\n')
>>> safe('some \x00text\\r\\n')
'some text'
This is useful to ensure a string can be used in a IRC message.
Expand All @@ -45,6 +46,7 @@ def safe(string):
string = string.decode("utf8")
string = string.replace('\n', '')
string = string.replace('\r', '')
string = string.replace('\x00', '')
return string


Expand Down
49 changes: 29 additions & 20 deletions test/irc/test_irc_utils.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,52 @@
"""Tests for core ``sopel.irc.utils``"""
from __future__ import annotations

from itertools import permutations

import pytest

from sopel.irc import utils


def test_safe():
text = 'some text'
assert utils.safe(text + '\r\n') == text
assert utils.safe(text + '\n') == text
assert utils.safe(text + '\r') == text
assert utils.safe('\r\n' + text) == text
assert utils.safe('\n' + text) == text
assert utils.safe('\r' + text) == text
assert utils.safe('some \r\ntext') == text
assert utils.safe('some \ntext') == text
assert utils.safe('some \rtext') == text
variants = permutations(('\n', '\r', '\x00'))
for variant in variants:
seq = ''.join(variant)
assert utils.safe(text + seq) == text
assert utils.safe(seq + text) == text
assert utils.safe('some ' + seq + 'text') == text
assert utils.safe(
variant[0]
+ 'some '
+ variant[1]
+ 'text'
+ variant[2]
) == text


def test_safe_empty():
text = ''
assert utils.safe(text) == text


def test_safe_null():
def test_safe_none():
with pytest.raises(TypeError):
utils.safe(None)


def test_safe_bytes():
text = b'some text'
assert utils.safe(text) == text.decode('utf-8')
assert utils.safe(text + b'\r\n') == text.decode('utf-8')
assert utils.safe(text + b'\n') == text.decode('utf-8')
assert utils.safe(text + b'\r') == text.decode('utf-8')
assert utils.safe(b'\r\n' + text) == text.decode('utf-8')
assert utils.safe(b'\n' + text) == text.decode('utf-8')
assert utils.safe(b'\r' + text) == text.decode('utf-8')
assert utils.safe(b'some \r\ntext') == text.decode('utf-8')
assert utils.safe(b'some \ntext') == text.decode('utf-8')
assert utils.safe(b'some \rtext') == text.decode('utf-8')
variants = permutations((b'\n', b'\r', b'\x00'))
for variant in variants:
seq = b''.join(variant)
assert utils.safe(text + seq) == text.decode('utf-8')
assert utils.safe(seq + text) == text.decode('utf-8')
assert utils.safe(b'some ' + seq + b'text') == text.decode('utf-8')
assert utils.safe(
variant[0]
+ b'some '
+ variant[1]
+ b'text'
+ variant[2]
) == text.decode('utf-8')

0 comments on commit 1cd02c4

Please sign in to comment.