#!/usr/bin/python3

"""Unit tests for bashquote.py."""

from __future__ import print_function

import sys

import bashquote as bashquote_mod


def to_bytes(string):
    """Convert a string to bytes."""
    return string.encode(encoding='ASCII', errors='backslashreplace')


def test_one(input_string, expected_output_string, repetitions=1):
    """Test one input/output pair - first as a string, second as a byte string"""

    all_good = True

    string = input_string
    for _unused_repetitionno in range(repetitions):
        bashquote_string = bashquote_mod.BashquoteString()
        bashquote_string.add(string)
        string = bashquote_string.result()

    actual_output_string = string

    if actual_output_string != expected_output_string:
        sys.stderr.write('{}: actual string {} does not match expected {}\n'.format(
            sys.argv[0],
            actual_output_string,
            expected_output_string,
        ))
        # sys.stderr.write('{}\n'.format(actual_output_string))
        # sys.stderr.write('{}\n'.format(expected_output_string))
        all_good = False

    input_byte_string = to_bytes(input_string)
    expected_output_byte_string = to_bytes(expected_output_string)

    byte_string = input_byte_string
    for _unused_repetitionno in range(repetitions):
        bashquote_byte_string = bashquote_mod.BashquoteBytes()
        bashquote_byte_string.add(byte_string)
        byte_string = bashquote_byte_string.result()

    actual_output_byte_string = byte_string

    if actual_output_byte_string != expected_output_byte_string:
        sys.stderr.write('{}: actual byte string {} does not match expected {}\n'.format(
            sys.argv[0],
            actual_output_byte_string,
            expected_output_byte_string,
        ))
        # sys.stderr.write('{}\n'.format(actual_output_byte_string))
        # sys.stderr.write('{}\n'.format(expected_output_byte_string))
        all_good = False

    return all_good


def main():
    """Main function."""

    all_good = True

    all_good &= test_one("ab", "'ab'")
    all_good &= test_one("a'b", "'a'\"'\"'b'")
    all_good &= test_one('a"b', '\'a"b\'')
    all_good &= test_one(r"a\bc", r"'a\bc'")
    all_good &= test_one(r"a\\bc", r"'a\\bc'")

    # This gets into a mix of POSIX shell quoting and python quoting. It's not pretty.
    all_good &= test_one("ab", "''\"'\"'ab'\"'\"''", repetitions=2)
    all_good &= test_one("a'b", "''\"'\"'a'\"'\"'\"'\"'\"'\"'\"'\"'b'\"'\"''", repetitions=2)
    all_good &= test_one('a"b', "''\"'\"'a\"b'\"'\"''", repetitions=2)
    all_good &= test_one(r"a\bc", "''\"'\"'a\\bc'\"'\"''", repetitions=2)
    all_good &= test_one(r"a\\bc", "''\"'\"'a\\\\bc'\"'\"''", repetitions=2)

    if not all_good:
        sys.stderr.write('{}: One or more tests failed\n'.format(sys.argv[0]))
        sys.exit(1)


main()