#!/usr/bin/env python3
#
# A simple test framework similar to Perl's Test::More module.
# Copyright (c) 2018, Hiroyuki Ohsaki.
# All rights reserved.
#
# $Id: test_more.py,v 1.1 2018/05/29 03:51:14 ohsaki Exp ohsaki $
#

import sys

# if True, test failure raises an AssertionError exception
raise_error = False

# the total number of tests performed
count = 0

def _print(*args):
    print(*args, file=sys.stdout)

def _display_result(is_success, msg='', note=''):
    """Display test result, whose result is IS_SUCCESS.  Test result includes
    the test number and test result ('ok' or 'ng'), followed by the message
    MSG and the note NOTE if provided."""
    global count
    count += 1
    if note:
        note = '\t' + note
    if is_success:
        _print(f'{count}: ok {msg}{note}')
    else:
        if raise_error:
            raise AssertionError(f'{count}: ng {msg}{note}')
        else:
            _print(f'{count}: ng {msg}{note}')

def ok(v, note=''):
    """Test if V is True, and display wheter the test was successful or
    not. Additional information NOTE is displayed if present."""
    _display_result(v, note=note)

def eq(v1, v2, note=''):
    """Test if V1 is equal to V2, and display wheter the test was successful
    or not. Additional information NOTE is displayed if present."""
    _display_result(v1 == v2, f'{v1} == {v2}', note=note)

def neq(v1, v2, note=''):
    _display_result(v1 != v2, f'{v1} != {v2}', note=note)

def cmp_ok(v1, op, v2, note=''):
    if op == '>':
        result = v1 > v2
    elif op == '>=':
        result = v1 >= v2
    elif op == '<':
        result = v1 < v2
    elif op == '<=':
        result = v1 <= v2
    elif op == '==':
        result = v1 == v2
    elif op == '!=':
        result = v1 != v2
    _display_result(result, f'{v1} {op} {v2}', note=note)

def is_deeply(v1, v2, note=''):
    """Test if V1 and V2 are the same, and display wheter the test was
    successful or not. Additional information NOTE is displayed if present."""
    _display_result(repr(v1) == repr(v2), f'{v1} == {v2}', note=note)

def isa_ok(obj, cls, note=''):
    _display_result(type(obj) == cls, f'{obj} == {cls}', note=note)

def can_ok(obj, attr, note=''):
    _display_result(attr in obj.__dict__, f'{obj} has {attr}', note=note)

def main():
    ok(True)
    ok(True, 'always true')
    ok(False)
    ok(False, 'always false')
    eq(1, 1)
    eq(1, 2)
    eq([], [])
    eq(['a', 'b', [1, 2]], ['a', 'b', [1, 2]])
    is_deeply(['a', 'b', [1]], ['a', 'b', [1, 2]])
    is_deeply(['a', 'b', [1, 2]], ['a', 'b', [1, 2]])

if __name__ == "__main__":
    main()
