#!/usr/local/cpython-3.7/bin/python3

"""Tests for lifo_mod."""

import sys

import lifo_mod


def test_push1_pop1():
    """Push 1 value, pop it, compare."""
    lifo = lifo_mod.Lifo()
    lifo.push(1)

    if lifo.pop() == 1:
        if not lifo:
            return True

        sys.stderr.write('{}: test_push1_pop1: LIFO not empty\n'.format(sys.argv[0]))
        return False

    sys.stderr.write('{}: test_push1_pop1: Did not pop a 1\n'.format(sys.argv[0]))
    return False


def test_push2_pop2():
    """Push 2 values, pop 2 values, compare."""
    all_good = True

    lifo = lifo_mod.Lifo()
    lifo.push(1)
    lifo.push(2)

    if lifo.pop() != 2:
        sys.stderr.write('{}: test_push2_pop2: Did not pop a 2\n'.format(sys.argv[0]))
        all_good = False

    if lifo.pop() != 1:
        sys.stderr.write('{}: test_push2_pop2: Did not pop a 1\n'.format(sys.argv[0]))
        all_good = False

    if lifo:
        sys.stderr.write('{}: test_push2_pop2: LIFO not empty\n'.format(sys.argv[0]))
        all_good = False

    return all_good


def test_push3_pop3():
    """Push 3 values, pop 3 values, compare."""
    all_good = True

    lifo = lifo_mod.Lifo()
    lifo.push(1)
    lifo.push(2)
    lifo.push(3)

    if lifo.pop() != 3:
        sys.stderr.write('{}: test_push3_pop3: Did not pop a 3\n'.format(sys.argv[0]))
        all_good = False

    if lifo.pop() != 2:
        sys.stderr.write('{}: test_push3_pop3: Did not pop a 2\n'.format(sys.argv[0]))
        all_good = False

    if lifo.pop() != 1:
        sys.stderr.write('{}: test_push3_pop3: Did not pop a 1\n'.format(sys.argv[0]))
        all_good = False

    if lifo:
        sys.stderr.write('{}: test_push3_pop3: LIFO not empty\n'.format(sys.argv[0]))
        all_good = False

    return all_good


def test_push2_pop1_push1_pop2():
    """Push 2 values, pop 1 value, push 1 value, pop 2 values, compare."""
    all_good = True

    lifo = lifo_mod.Lifo()
    lifo.push(1)
    lifo.push(2)

    if lifo.pop() == 2:
        pass
    else:
        sys.stderr.write('{}: test_push2_pop1_push1_pop2: Did not pop a 2\n'.format(sys.argv[0]))
        all_good = False

    lifo.push(3)

    if lifo.pop() == 3:
        pass
    else:
        sys.stderr.write('{}: test_push2_pop1_push1_pop2: Did not pop a 3\n'.format(sys.argv[0]))
        all_good = False

    if lifo.pop() == 1:
        pass
    else:
        sys.stderr.write('{}: test_push2_pop1_push1_pop2: Did not pop a 1\n'.format(sys.argv[0]))
        all_good = False

    if not lifo:
        pass
    else:
        sys.stderr.write('{}: test_push2_pop1_push1_pop2: LIFO not empty\n'.format(sys.argv[0]))
        all_good = False

    return all_good


def test_push2_peek():
    """Push 2 values, peek, compare."""
    all_good = True

    lifo = lifo_mod.Lifo()
    lifo.push(1)
    lifo.push(2)

    if lifo.peek() == 2:
        pass
    else:
        sys.stderr.write('{}: test_push2_peek: peek not 2\n'.format(sys.argv[0]))
        all_good = False

    if len(lifo) == 2:
        pass
    else:
        sys.stderr.write('{}: test_push2_peek: length not 2\n'.format(sys.argv[0]))
        all_good = False

    return all_good


def test_push3_pop4():
    """Push 3 values, pop 4 values, verify exception."""
    all_good = True

    lifo = lifo_mod.Lifo()
    lifo.push(1)
    lifo.push(2)
    lifo.push(3)

    if lifo.pop() == 3:
        pass
    else:
        sys.stderr.write('{}: test_push3_pop4: Did not pop a 3\n'.format(sys.argv[0]))
        all_good = False

    if lifo.pop() == 2:
        pass
    else:
        sys.stderr.write('{}: test_push3_pop4: Did not pop a 2\n'.format(sys.argv[0]))
        all_good = False

    if lifo.pop() == 1:
        pass
    else:
        sys.stderr.write('{}: test_push3_pop4: Did not pop a 1\n'.format(sys.argv[0]))
        all_good = False

    try:
        lifo.pop()
    except IndexError:
        pass
    else:
        sys.stderr.write('{}: test_push3_pop4: Did not get an exception\n'.format(sys.argv[0]))
        all_good = False

    return all_good


def test_bool():
    """Test in a boolean context."""
    all_good = True

    lifo = lifo_mod.Lifo()
    if lifo:
        sys.stderr.write('{}: test_bool: lifo thinks it is not empty, but it is\n'.format(sys.argv[0]))
        all_good = False
    else:
        pass

    lifo.push(1)
    if not lifo:
        sys.stderr.write('{}: test_bool: lifo thinks it is empty, but it is not\n'.format(sys.argv[0]))
        all_good = False
    else:
        pass

    return all_good


def test_len():
    """Test len()."""
    all_good = True

    lifo = lifo_mod.Lifo()

    if lifo:
        sys.stderr.write('{}: test_len: lifo is not empty\n'.format(sys.argv[0]))
        all_good = False

    lifo.push(1)
    if len(lifo) == 1:
        pass
    else:
        sys.stderr.write('{}: test_len: len(lifo) is not 1\n'.format(sys.argv[0]))
        all_good = False

    lifo.push(5)
    if len(lifo) == 2:
        pass
    else:
        sys.stderr.write('{}: test_len: len(lifo) is not 2\n'.format(sys.argv[0]))
        all_good = False

    return all_good


def main():
    """Run all tests and report."""
    all_good = True

    all_good &= test_push1_pop1()
    all_good &= test_push2_pop2()
    all_good &= test_push3_pop3()
    all_good &= test_push2_pop1_push1_pop2()
    all_good &= test_push2_peek()
    all_good &= test_push3_pop4()
    all_good &= test_bool()
    all_good &= test_len()

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


main()