#!/usr/bin/env python3

# osmo_gsm_tester: logging tests
#
# Copyright (C) 2016-2017 by sysmocom - s.f.m.c. GmbH
#
# Author: Neels Hofmeyr <neels@hofmeyr.de>
#
# This program 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.
#
# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.

import _prep

import sys
import os

from osmo_gsm_tester.core import log

#log.targets[0].get_time_str = lambda: '01:02:03'
fake_time = '01:02:03'
log.style_change(time=True, time_fmt=fake_time)
log.set_all_levels(None)

print('- Testing global log functions')
log.log('from log.log()', _origin='<origin>', _category=log.C_TST)
log.dbg('from log.dbg(), not seen', _origin='<origin>', _category=log.C_TST)
log.set_level(log.C_TST, log.L_DBG)
log.dbg('from log.dbg()', _origin='<origin>', _category=log.C_TST)
log.set_level(log.C_TST, log.L_LOG)
log.err('from log.err()', _origin='<origin>', _category=log.C_TST)

print('- Testing log.Origin functions')
class LogTest(log.Origin):
    def __init__(self, *name_items, **detail_items):
        super().__init__(log.C_TST, *name_items, **detail_items)

t = LogTest('some', 'name', some="detail")

t.log("hello log")
t.err("hello err")
t.dbg("hello dbg not visible")

t.log("message", int=3, tuple=('foo', 42), none=None, str='str\n')

log.set_level(log.C_TST, log.L_DBG)
t.dbg("hello dbg")

print('- Testing log.style()')

log.style(time=True, category=False, level=False, origin=False, src=False, time_fmt=fake_time)
t.dbg("only time")
log.style(time=False, category=True, level=False, origin=False, src=False, time_fmt=fake_time)
t.dbg("only category")
log.style(time=False, category=False, level=True, origin=False, src=False, time_fmt=fake_time)
t.dbg("only level")
log.style(time=False, category=False, level=False, origin=True, src=False, time_fmt=fake_time)
t.dbg("only origin")
log.style(time=False, category=False, level=False, origin=False, src=True, time_fmt=fake_time)
t.dbg("only src")

print('- Testing log.style_change()')
log.style(time=False, category=False, level=False, origin=False, src=False, time_fmt=fake_time)
t.dbg("no log format")
log.style_change(time=True)
t.dbg("add time")
log.style_change(time=True, time_fmt=0)
t.dbg("but no time format")
log.style_change(time=True, time_fmt=fake_time)
log.style_change(level=True)
t.dbg("add level")
log.style_change(category=True)
t.dbg("add category")
log.style_change(src=True)
t.dbg("add src")
log.style_change(origin=True)
t.dbg("add origin")

print('- Testing origin_width')
t = LogTest('shortname')
log.style(origin_width=23, time_fmt=fake_time)
t.log("origin str set to 23 chars")
t.set_name('very long name', some='details', and_some=(3, 'things', 'in a tuple'))
t.log("long origin str")
t.dbg("long origin str dbg")
t.err("long origin str err")

print('- Testing log.Origin with omitted info')
t = LogTest()
t.log("hello log, name implicit from class name")

t = LogTest('explicit_name')
t._set_log_category(None)
t.log("hello log, no category set")

t = LogTest()
t._set_log_category(None)
t.log("hello log, no category nor name set")
t.dbg("hello log, no category nor name set, not seen")
log.set_level(log.C_DEFAULT, log.L_DBG)
t.dbg("debug message, no category nor name set")

print('- Testing logging of Exceptions, tracing origins')
log.style(time_fmt=fake_time, origin_width=0)

class Thing(log.Origin):
    def __init__(self, some_path):
        super().__init__(log.C_TST, some_path)

    def say(self, msg):
        print(msg)

    def l1(self):
        level2 = Thing('level2')
        level2.l2()

    def l2(self):
        level3 = Thing('level3')
        level3.l3(self)

    def l3(self, level2):
        print('nested print just prints')
        self.log('nested log()')
        level2.log('nested l2 log() from within l3 scope')
        raise ValueError('bork')

try:
    level1 = Thing('level1')
    level1.l1()
except Exception:
    log.log_exn()

print('- Disallow origin loops')
try:
    t = Thing('foo')
    t._set_parent(t)
    raise RuntimeError('this should not be reached')
except log.OriginLoopError:
    print('disallowed successfully')
    pass

# vim: expandtab tabstop=4 shiftwidth=4
