Mercurial > cgi-bin > hgweb.cgi > PassMan
diff src/test/kotlin/name/blackcap/passman/ShplitterTest.kt @ 19:7d80cbcb67bb
add shlex-style splitter and tests
author | David Barts <n5jrn@me.com> |
---|---|
date | Sun, 30 Jun 2024 20:37:36 -0700 |
parents | |
children | 4391afcf6bd0 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/test/kotlin/name/blackcap/passman/ShplitterTest.kt Sun Jun 30 20:37:36 2024 -0700 @@ -0,0 +1,119 @@ +package name.blackcap.passman + +import org.junit.jupiter.api.Assertions.assertFalse +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test + +class ShplitterTest { + private lateinit var fixture: Shplitter + + @Test + fun complete() { + val CASES = arrayOf<String>( + "unquoted", + "\"double quoted\"", + "'single quoted'", + "back\\ slash", + "in\\terior back slash", + "\"first\" word double quoted", + "last word double \"quoted\"", + "'first' word single quoted", + "last word single 'quoted'") + + for (case in CASES) { + val fixture = Shplitter() + fixture.feed(case) + assertTrue(fixture.complete, "should be complete but is not: ${case}") + } + } + + @Test + fun incomplete() { + val CASES = arrayOf<String>( + "ends with backslash\\", + "unclosed double \"quote", + "ends with double quote\"", + "unclosed single 'quote", + "ends with single quote'" + ) + for (case in CASES) { + val fixture = Shplitter() + fixture.feed(case) + assertFalse(fixture.complete, "should not be complete but is: ${case}") + } + } + + // Test cases cribbed from Python shlex source. + data class TestDatum(val from: String, val to: Array<String>) + val TEST_DATA_1 = arrayOf<TestDatum>( + TestDatum("foo bar", arrayOf<String>("foo", "bar")), + TestDatum(" foo bar", arrayOf<String>("foo", "bar")), + TestDatum(" foo bar ", arrayOf<String>("foo", "bar")), + TestDatum("foo\tbar\tbla\tfasel", arrayOf<String>("foo", "bar", "bla", "fasel")), + TestDatum("x y z\t\txxxx", arrayOf<String>("x", "y", "z", "xxxx")), + TestDatum("\\x bar", arrayOf<String>("x", "bar")), + TestDatum("\\ x bar", arrayOf<String>(" x", "bar")), + TestDatum("\\ bar", arrayOf<String>(" bar")), + TestDatum("foo \\x bar", arrayOf<String>("foo", "x", "bar")), + TestDatum("foo \\ x bar", arrayOf<String>("foo", " x", "bar")), + TestDatum("foo \\ bar", arrayOf<String>("foo", " bar")), + TestDatum("foo \"bar\" bla", arrayOf<String>("foo", "bar", "bla")), + TestDatum("\"foo\" \"bar\" \"bla\"", arrayOf<String>("foo", "bar", "bla")), + TestDatum("\"foo\" bar \"bla\"", arrayOf<String>("foo", "bar", "bla")), + TestDatum("\"foo\" bar bla", arrayOf<String>("foo", "bar", "bla")), + TestDatum("foo 'bar' bla", arrayOf<String>("foo", "bar", "bla")), + TestDatum("'foo' 'bar' 'bla'", arrayOf<String>("foo", "bar", "bla")), + TestDatum("'foo' bar 'bla'", arrayOf<String>("foo", "bar", "bla")), + TestDatum("'foo' bar bla", arrayOf<String>("foo", "bar", "bla")), + TestDatum("blurb foo\"bar\"bar\"fasel\" baz", arrayOf<String>("blurb", "foobarbarfasel", "baz")), + TestDatum("blurb foo'bar'bar'fasel' baz", arrayOf<String>("blurb", "foobarbarfasel", "baz")), + TestDatum("\"\"", arrayOf<String>("")), + TestDatum("''", arrayOf<String>("")), + TestDatum("foo \"\" bar", arrayOf<String>("foo", "", "bar")), + TestDatum("foo '' bar", arrayOf<String>("foo", "", "bar")), + TestDatum("foo \"\" \"\" \"\" bar", arrayOf<String>("foo", "", "", "", "bar")), + TestDatum("foo '' '' '' bar", arrayOf<String>("foo", "", "", "", "bar")), + TestDatum("\"foo\\ bar\"", arrayOf<String>("foo bar"))); + val TEST_DATA_2 = arrayOf<TestDatum>( + TestDatum("\"foo\\\\ bar\"", arrayOf<String>("foo\\ bar")), + TestDatum("\"foo\\\\ bar\\\\\"", arrayOf<String>("foo\\ bar\\")), + TestDatum("\"foo\\\\\" bar\\\"", arrayOf<String>("foo\\", "bar\"")), + TestDatum("\"foo\\\\ bar\" dfadf", arrayOf<String>("foo\\ bar", "dfadf")), + TestDatum("\"foo\\\\\\ bar\\\" dfadf\"", arrayOf<String>("foo\\ bar\" dfadf")), + TestDatum("\"foo\\\\\\x bar\" dfadf", arrayOf<String>("foo\\x bar", "dfadf")), + TestDatum("\"foo\\x bar\\\" dfadf\"", arrayOf<String>("foox bar\" dfadf")), + TestDatum("\"foo\\x\"", arrayOf<String>("foox")), + TestDatum("\"foo\\ \"", arrayOf<String>("foo ")), + TestDatum("foo\\ xx", arrayOf<String>("foo xx")), + TestDatum("foo\\ x\\x", arrayOf<String>("foo xx")), + TestDatum("foo\\ x\\x\\\"\"\"", arrayOf<String>("foo xx\"")), + TestDatum("\"foo\\ x\\x\"", arrayOf<String>("foo xx")), + TestDatum("\"foo\\ x\\x\\\\\"", arrayOf<String>("foo xx\\")), + TestDatum("\"foo\\ x\\x\\\\\"\"foobar\"", arrayOf<String>("foo xx\\foobar")), + TestDatum("\"foo\\ x\\x\\\\\"\\'\"foobar\"", arrayOf<String>("foo xx\\'foobar")), + TestDatum("\"foo\\ x\\x\\\\\"\\'\"fo'obar\" 'don'\\''t'", arrayOf<String>("foo xx\\'foobar\" don\\t")), + TestDatum("'foo\\ bar'", arrayOf<String>("foo\\ bar")), + TestDatum("'foo\\\\ bar'", arrayOf<String>("foo\\\\ bar")), + TestDatum("foo\\ bar", arrayOf<String>("foo bar")), + TestDatum("foo#bar\\nbaz", arrayOf<String>("foo#barnbaz")), + TestDatum(":-) ;-)", arrayOf<String>(":-)", ":-)")), + TestDatum("áéíóú", arrayOf<String>("áéíóú")) + ) + + fun runArray(testData: Array<TestDatum>) { + for (testDatum in testData) { + val s = Shplitter() + s.feed(testDatum.from) + assertTrue(s.complete, "${testDatum.from}: should be complete, is not") + val split = s.split().toList() + val expecting = testDatum.to.asList() + assertTrue(split == expecting, "${testDatum.from}: expected ${expecting}, got $split") + } + } + + @Test + fun split() { + runArray(TEST_DATA_1) + runArray(TEST_DATA_2) + } +}