""" Test package of Clockskew IRI-IIF script """
# Copyright (C) 2013 Libor Polčák
#
# 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 time
import unittest

import clockskew

class FakeClass():

    def __init__(self):
        self.calls = []
        self.params = []

    def addParam(self, *args, **kwargs):
        self.params.append((args, kwargs))

    def __getattr__(self, attr):
        self.calls.append(attr)
        return self.addParam


class Tests(unittest.TestCase):

    def setUp(self):
        clockskew.similar_skew = {}

    def compareIRIMessages(self, left, right):
        self.assertEqual(left[0], right[0])
        self.assertTrue(left[1] < right[1] < left[1]+1)
        self.assertEqual(left[2], right[2])
        self.assertEqual(left[3], right[3])
        self.assertEqual(left[4], right[4])

    def testKnownAddressPair(self):
        t = "tcp"
        a1 = "10.0.0.1"
        a2 = "2001:db8::1"
        self.assertFalse(clockskew.knownAddressPair(t, a1, a2))
        self.assertFalse(clockskew.knownAddressPair(t, a2, a1))
        clockskew.addAddressPair(t, a1, a2)
        self.assertTrue(clockskew.knownAddressPair(t, a1, a2))
        self.assertTrue(clockskew.knownAddressPair(t, a2, a1))
        t2 = "javascript"
        self.assertFalse(clockskew.knownAddressPair(t2, a1, a2))
        self.assertFalse(clockskew.knownAddressPair(t2, a2, a1))

    def testCreateIRI(self):
        moduleType = "test"
        t = time.time()
        iriType = "CONTINUE"
        iriText = "Test case"
        nids = [("IPv4", "10.0.0.1"), ("IPv6", "2001:db8::dead:beef"), ("IPv6", "2001:67c:1220:8b0::147.229.176.19")]
        iri = clockskew.createIRI(moduleType, iriType, iriText, [n for _, n in nids])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, iriType, iriText, nids),
                iri)

    def testProcessInputLine2(self):
        fakeSocket = FakeClass()
        moduleType = "tcp"
        a1 = "10.0.0.1"
        a2 = "2001:db8::2"
        t = time.time()
        clockskew.processInputLine("active\t%s\t%s\t%s" % (moduleType, a1, a2), fakeSocket, ".")
        clockskew.processInputLine("active\t%s\t%s\t%s" % (moduleType, a1, a2), fakeSocket, ".")
        clockskew.processInputLine("active\t%s\t%s" % (moduleType, a1), fakeSocket, ".")
        self.assertEqual(fakeSocket.calls, ["send", "send", "send"])
        iriMessages = []
        for iri, emptyDict in fakeSocket.params:
            self.assertEqual(emptyDict, {})
            self.assertEqual(len(iri), 1)
            iriMessages.append(iri[0])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "BEGIN", (0, 0), [("IPv4", a1), ("IPv6", a2)]),
                iriMessages[0])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "CONTINUE", (0, 0), [("IPv4", a1), ("IPv6", a2)]),
                iriMessages[1])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "END", "", [("IPv4", a1), ("IPv6", a2)]),
                iriMessages[2])

    def testProcessInputLine3(self):
        fakeSocket = FakeClass()
        moduleType = "tcp"
        a1 = "10.0.0.1"
        a2 = "2001:db8::2"
        a3 = "2001:db8::3"
        t = time.time()
        clockskew.processInputLine("active\t%s\t%s\t%s\t%s" % (moduleType, a1, a2, a3), fakeSocket, ".")
        clockskew.processInputLine("active\t%s\t%s\t%s" % (moduleType, a1, a2), fakeSocket, ".")
        self.assertEqual(fakeSocket.calls, ["send", "send", "send", "send"])
        iriMessages = []
        for iri, emptyDict in fakeSocket.params:
            self.assertEqual(emptyDict, {})
            self.assertEqual(len(iri), 1)
            iriMessages.append(iri[0])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "BEGIN", (0, 0), [("IPv4", a1), ("IPv6", a2)]),
                iriMessages[0])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "BEGIN", (0, 0), [("IPv4", a1), ("IPv6", a3)]),
                iriMessages[1])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "END", "", [("IPv4", a1), ("IPv6", a3)]),
                iriMessages[2])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "CONTINUE", (0, 0), [("IPv4", a1), ("IPv6", a2)]),
                iriMessages[3])

    def testProcessInputLine4(self):
        fakeSocket = FakeClass()
        moduleType = "js"
        a1 = "10.0.0.1"
        a2 = "2001:db8::2"
        a3 = "2001:db8::3"
        t = time.time()
        clockskew.processInputLine("active\t%s\t%s\t%s" % (moduleType, a1, a2), fakeSocket, ".")
        clockskew.processInputLine("active\t%s\t%s\t%s\t%s" % (moduleType, a1, a2, a3), fakeSocket, ".")
        clockskew.processInputLine("active\t%s\t%s\t%s" % (moduleType, a1, a2), fakeSocket, ".")
        self.assertEqual(fakeSocket.calls, ["send", "send", "send", "send", "send"])
        iriMessages = []
        for iri, emptyDict in fakeSocket.params:
            self.assertEqual(emptyDict, {})
            self.assertEqual(len(iri), 1)
            iriMessages.append(iri[0])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "BEGIN", (0, 0), [("IPv4", a1), ("IPv6", a2)]),
                iriMessages[0])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "CONTINUE", (0, 0), [("IPv4", a1), ("IPv6", a2)]),
                iriMessages[1])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "BEGIN", (0, 0), [("IPv4", a1), ("IPv6", a3)]),
                iriMessages[2])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "END", "", [("IPv4", a1), ("IPv6", a3)]),
                iriMessages[3])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "CONTINUE", (0, 0), [("IPv4", a1), ("IPv6", a2)]),
                iriMessages[4])
    
    def testProcessInputLineInactive(self):
        fakeSocket = FakeClass()
        moduleType = "js"
        a1 = "10.0.0.1"
        a2 = "2001:db8::2"
        a3 = "2001:db8::3"
        t = time.time()
        clockskew.processInputLine("active\t%s\t%s\t%s" % (moduleType, a1, a2), fakeSocket, ".")
        clockskew.processInputLine("active\t%s\t%s\t%s\t%s" % (moduleType, a1, a2, a3), fakeSocket, ".")
        clockskew.processInputLine("inactive\t%s\t%s" % (moduleType, a1), fakeSocket, ".")
        self.assertEqual(fakeSocket.calls, ["send", "send", "send", "send", "send", "send"])
        iriMessages = []
        for iri, emptyDict in fakeSocket.params:
            self.assertEqual(emptyDict, {})
            self.assertEqual(len(iri), 1)
            iriMessages.append(iri[0])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "BEGIN", (0, 0), [("IPv4", a1), ("IPv6", a2)]),
                iriMessages[0])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "CONTINUE", (0, 0), [("IPv4", a1), ("IPv6", a2)]),
                iriMessages[1])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "BEGIN", (0, 0), [("IPv4", a1), ("IPv6", a3)]),
                iriMessages[2])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "END", "", [("IPv4", a1), ("IPv6", a2)]),
                iriMessages[3])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "END", "", [("IPv4", a1), ("IPv6", a3)]),
                iriMessages[4])
        self.compareIRIMessages(
                ("clockskew_" + moduleType, t, "END", "inactive", [("IPv4", a1), ("IPv4", a1)]),
                iriMessages[5])
    def testProcessEmptyLine(self):
        clockskew.processInputLine(" ", None," ")

def suite():
	test = unittest.makeSuite(Tests, "test")
	return unittest.TestSuite(tuple(test))

def test():
	runner = unittest.TextTestRunner()
	runner.run(suite())

