# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: # Copyright 2014-2021 Florian Bruhin (The Compiler) # # This file is part of qutebrowser. # # qutebrowser is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # qutebrowser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with qutebrowser. If not, see . """Tests for qutebrowser.misc.split.""" import dataclasses from typing import List import pytest from qutebrowser.misc import split # Most tests copied from Python's shlex. # The original test data set was from shellwords, by Hartmut Goebel. # Format: input/split|output|without|keep/split|output|with|keep/ test_data_str = r""" one two/one|two/one| two/ one "two three" four/one|two three|four/one| "two three"| four/ one 'two three' four/one|two three|four/one| 'two three'| four/ one "two\" three" four/one|two" three|four/one| "two\" three"| four/ one 'two'\'' three' four/one|two' three|four/one| 'two'\'' three'| four/ one "two three/one|two three/one| "two three/ one 'two three/one|two three/one| 'two three/ one\/one\/one\/ one "two\/one|two\/one| "two\/ one /one/one| / open -t i/open|-t|i/open| -t| i/ foo bar/foo|bar/foo| bar/ foo bar/foo|bar/ foo| bar/ foo bar /foo|bar/ foo| bar| / foo bar bla fasel/foo|bar|bla|fasel/foo| bar| bla| fasel/ x y z xxxx/x|y|z|xxxx/x| y| z| xxxx/ \x bar/x|bar/\x| bar/ \ x bar/ x|bar/\ x| bar/ \ bar/ bar/\ bar/ foo \x bar/foo|x|bar/foo| \x| bar/ foo \ x bar/foo| x|bar/foo| \ x| bar/ foo \ bar/foo| bar/foo| \ bar/ foo "bar" bla/foo|bar|bla/foo| "bar"| bla/ "foo" "bar" "bla"/foo|bar|bla/"foo"| "bar"| "bla"/ "foo" bar "bla"/foo|bar|bla/"foo"| bar| "bla"/ "foo" bar bla/foo|bar|bla/"foo"| bar| bla/ foo 'bar' bla/foo|bar|bla/foo| 'bar'| bla/ 'foo' 'bar' 'bla'/foo|bar|bla/'foo'| 'bar'| 'bla'/ 'foo' bar 'bla'/foo|bar|bla/'foo'| bar| 'bla'/ 'foo' bar bla/foo|bar|bla/'foo'| bar| bla/ blurb foo"bar"bar"fasel" baz/blurb|foobarbarfasel|baz/blurb| foo"bar"bar"fasel"| baz/ blurb foo'bar'bar'fasel' baz/blurb|foobarbarfasel|baz/blurb| foo'bar'bar'fasel'| baz/ ""//""/ ''//''/ foo "" bar/foo||bar/foo| ""| bar/ foo '' bar/foo||bar/foo| ''| bar/ foo "" "" "" bar/foo||||bar/foo| ""| ""| ""| bar/ foo '' '' '' bar/foo||||bar/foo| ''| ''| ''| bar/ \"/"/\"/ "\""/"/"\""/ "foo\ bar"/foo\ bar/"foo\ bar"/ "foo\\ bar"/foo\ bar/"foo\\ bar"/ "foo\\ bar\""/foo\ bar"/"foo\\ bar\""/ "foo\\" bar\"/foo\|bar"/"foo\\"| bar\"/ "foo\\ bar\" dfadf"/foo\ bar" dfadf/"foo\\ bar\" dfadf"/ "foo\\\ bar\" dfadf"/foo\\ bar" dfadf/"foo\\\ bar\" dfadf"/ "foo\\\x bar\" dfadf"/foo\\x bar" dfadf/"foo\\\x bar\" dfadf"/ "foo\x bar\" dfadf"/foo\x bar" dfadf/"foo\x bar\" dfadf"/ \'/'/\'/ 'foo\ bar'/foo\ bar/'foo\ bar'/ 'foo\\ bar'/foo\\ bar/'foo\\ bar'/ "foo\\\x bar\" df'a\ 'df"/foo\\x bar" df'a\ 'df/"foo\\\x bar\" df'a\ 'df"/ \"foo/"foo/\"foo/ \"foo\x/"foox/\"foo\x/ "foo\x"/foo\x/"foo\x"/ "foo\ "/foo\ /"foo\ "/ foo\ xx/foo xx/foo\ xx/ foo\ x\x/foo xx/foo\ x\x/ foo\ x\x\"/foo xx"/foo\ x\x\"/ "foo\ x\x"/foo\ x\x/"foo\ x\x"/ "foo\ x\x\\"/foo\ x\x\/"foo\ x\x\\"/ "foo\ x\x\\""foobar"/foo\ x\x\foobar/"foo\ x\x\\""foobar"/ "foo\ x\x\\"\'"foobar"/foo\ x\x\'foobar/"foo\ x\x\\"\'"foobar"/ "foo\ x\x\\"\'"fo'obar"/foo\ x\x\'fo'obar/"foo\ x\x\\"\'"fo'obar"/ "foo\ x\x\\"\'"fo'obar" 'don'\''t'/foo\ x\x\'fo'obar|don't/"foo\ x\x\\"\'"fo'obar"| 'don'\''t'/ "foo\ x\x\\"\'"fo'obar" 'don'\''t' \\/foo\ x\x\'fo'obar|don't|\/"foo\ x\x\\"\'"fo'obar"| 'don'\''t'| \\/ foo\ bar/foo bar/foo\ bar/ :-) ;-)/:-)|;-)/:-)| ;-)/ áéíóú/áéíóú/áéíóú/ """ def _parse_split_test_data_str(): """Parse the test data set into a TestCase object to use in tests. Returns: A list of TestCase objects with str attributes: inp, keep, no_keep """ @dataclasses.dataclass class TestCase: inp: str keep: List[str] no_keep: List[str] for line in test_data_str.splitlines(): if not line: continue data = line.split('/') item = TestCase(inp=data[0], keep=data[1].split('|'), no_keep=data[2].split('|')) yield item yield TestCase(inp='', keep=[], no_keep=[]) class TestSplit: """Test split.""" @pytest.fixture(params=list(_parse_split_test_data_str()), ids=lambda e: e.inp) def split_test_case(self, request): """Fixture to automatically parametrize all depending tests. It will use the test data from test_data_str, parsed using _parse_split_test_data_str(). """ return request.param def test_split(self, split_test_case): """Test splitting.""" items = split.split(split_test_case.inp) assert items == split_test_case.keep def test_split_keep_original(self, split_test_case): """Test if splitting with keep=True yields the original string.""" items = split.split(split_test_case.inp, keep=True) assert ''.join(items) == split_test_case.inp def test_split_keep(self, split_test_case): """Test splitting with keep=True.""" items = split.split(split_test_case.inp, keep=True) assert items == split_test_case.no_keep class TestSimpleSplit: """Test simple_split.""" TESTS = { ' foo bar': [' foo', ' bar'], 'foobar': ['foobar'], ' foo bar baz ': [' foo', ' bar', ' baz', ' '], 'f\ti\ts\th': ['f', '\ti', '\ts', '\th'], 'foo\nbar': ['foo', '\nbar'], } @pytest.mark.parametrize('test', sorted(TESTS), ids=repr) def test_str_split(self, test): """Test if the behavior matches str.split.""" assert split.simple_split(test) == test.rstrip().split() @pytest.mark.parametrize('s, maxsplit', [("foo bar baz", 1), (" foo bar baz ", 0)], ids=repr) def test_str_split_maxsplit(self, s, maxsplit): """Test if the behavior matches str.split with given maxsplit.""" actual = split.simple_split(s, maxsplit=maxsplit) expected = s.rstrip().split(maxsplit=maxsplit) assert actual == expected @pytest.mark.parametrize('test, expected', sorted(TESTS.items()), ids=repr) def test_split_keep(self, test, expected): """Test splitting with keep=True.""" assert split.simple_split(test, keep=True) == expected def test_maxsplit_0_keep(self): """Test special case with maxsplit=0 and keep=True.""" s = "foo bar" assert split.simple_split(s, keep=True, maxsplit=0) == [s]