import os, sys
sys.path.append(os.path.join(os.getcwd(), sys.path[0], ".."))
from ds import dsunittest
dsunittest.setTestName("bttrack.py")

import tempfile
import threading
import time

from bt.BitTorrent import track 
from ds import task
from ds import dsfile
from bt import btdownloadlibrary
from bt import btmakemetafile
import kenosis
import BitTorrent.download

def dummychoose(default, size, saveas, dir):
    return saveas

def dummydisplay(dict):
    print dict

def dummyerror(message):
    print message

class Test(dsunittest.TestCase):
    def setUp(self):
        pass

    def testTracker(self):
        btPort = 1234

        taskList = task.TaskList(maxThreads=3)
        
        dfile = tempfile.mktemp()
        stopEvent = threading.Event()
        def trackerLf():
            print "tracker starting"
            track.track(["--port", "%s" % btPort, "--dfile", dfile, "--kenosis", 0], event=stopEvent)
            print "tracker finished"
        taskList.addCallableTask(trackerLf)
        taskList.start(wait=0)

        dataFile = tempfile.mktemp()
        dsfile.setFileContents(path=dataFile, data="fdsafq2352436gfa" * 2048)

        btmakemetafile.make_meta_file(file=dataFile,
                                      url="http://localhost:%s/announce" % btPort,
                                      piece_len_exp=18)
        assert os.path.exists("%s.torrent" % dataFile)
        
        def seederLf():
            print "seeder starting"

            def fin():
                pass
            url="file://%s.torrent" % dataFile
            file=dataFile
            ev=stopEvent
            BitTorrent.download.download(
                ['--url', url, '--saveas', file, "--kenosis_bootstrap", "127.0.0.1:5005"], 
                dummychoose, dummydisplay, fin, dummyerror, ev, 80)
            print "seeder done"
        taskList.addCallableTask(seederLf)

        dataFile2 = tempfile.mktemp()
        doneEvent = threading.Event()
        def leecherLf():
            time.sleep(2)
            print "leecher starting"

            ev = threading.Event()
            url="file://%s.torrent" % dataFile
            file=dataFile2
            def fin(ev = ev):
                ev.set()
            BitTorrent.download.download(['--url', url, '--saveas', file, "--kenosis_bootstrap", "127.0.0.1:5005"], 
                dummychoose, dummydisplay, fin, dummyerror, ev, 80)
            doneEvent.set()
            print "leecher done"
        taskList.addCallableTask(leecherLf)
            
        doneEvent.wait()
        self.assertEqual(dsfile.fileContents(path=dataFile), 
                         dsfile.fileContents(path=dataFile2))
        stopEvent.set()
        taskList.stop()
        while not taskList.activeTasks():
            time.sleep(0.1)

    def testTrackerKenosis(self):
        kenosisPort = 50070
        btPort = 1236

        taskList = task.TaskList(maxThreads=4)


        stopEvent = threading.Event()
        n = kenosis.Node(ports=[kenosisPort], serve=False, bootstrapNetAddress=None)
        nodeAddress = n.nodeAddress()
        class BtHandler:
            def trackerPort(self):
                return btPort
        n.registerNamedHandler(name='bt', handler=BtHandler())
        taskList.addCallableTask(lambda: n.serveUntilEvent(stopEvent))
        
        dfile = tempfile.mktemp()
        def trackerLf():
            print "tracker starting"
            track.track(["--port", "%s" % btPort, "--dfile", dfile, "--kenosis", 0], event=stopEvent)
            print "tracker finished"
        taskList.addCallableTask(trackerLf)
        taskList.start(wait=0)

        dataFile = tempfile.mktemp()
        dsfile.setFileContents(path=dataFile, data="dfasdfq2352436gfa" * 2048)

        btmakemetafile.make_meta_file(
            file=dataFile,
            url="http://%s.node.bt.kenosisp2p.org/announce" % nodeAddress,
            piece_len_exp=18)
        assert os.path.exists("%s.torrent" % dataFile)
        
        def seederLf():
            def fin():
                pass
            BitTorrent.download.download(
                ['--url', "file://%s.torrent" % dataFile,
                 "--kenosis", 1,
                 '--saveas', dataFile,
                 "--kenosis_bootstrap", "127.0.0.1:%s" % kenosisPort], 
                dummychoose, dummydisplay, fin, dummyerror, stopEvent, 80)
        taskList.addCallableTask(seederLf)

        dataFile2 = tempfile.mktemp()
        doneEvent = threading.Event()
        def leecherLf():
            time.sleep(2)
            print "leecher starting"
            ev = threading.Event()
            def fin(ev = ev):
                ev.set()
            BitTorrent.download.download(['--url', "file://%s.torrent" % dataFile,
                                          "--kenosis", 1,
                                          "--kenosis_bootstrap", "127.0.0.1:%s" % kenosisPort,
                                          '--saveas', dataFile2], 
                                         dummychoose, dummydisplay, fin, dummyerror, ev, 80)
            doneEvent.set()
            print "leecher done"
        taskList.addCallableTask(leecherLf)
            
        doneEvent.wait()
        self.assertEqual(dsfile.fileContents(path=dataFile), 
                         dsfile.fileContents(path=dataFile2))
        stopEvent.set()
        taskList.stop()
        while not taskList.activeTasks():
            time.sleep(0.1)

    def testTrackerBuiltInKenosis(self):
        kenosisPort = 50060
        btPort = 1235

        taskList = task.TaskList(maxThreads=3)

        stopEvent = threading.Event()
        dfile = tempfile.mktemp()
        self.nodeAddress_ = None
        gotAddressEvent = threading.Event()
        def nodeAddressFunc(nah):
            self.nodeAddress_ = nah
            gotAddressEvent.set()
            
        def trackerLf():
            print "tracker starting"
            track.track(["--port", "%s" % btPort,
                         "--dfile", dfile,
                         "--kenosis", "1",
                         "--kenosis_bootstrap", "",
                         "--kport", "%s" % kenosisPort],
                        event=stopEvent, nodeAddressFunc=nodeAddressFunc)
            print "tracker finished"
        taskList.addCallableTask(trackerLf)
        taskList.start(wait=0)

        dataFile = tempfile.mktemp()
        dsfile.setFileContents(path=dataFile, data="dafq2352436gfa" * 2048)

        gotAddressEvent.wait()
        self.assertNotEqual(self.nodeAddress_, None)
        btmakemetafile.make_meta_file(
            file=dataFile,
            url="http://%s.node.bt.kenosisp2p.org/announce" % self.nodeAddress_,
            piece_len_exp=18)
        assert os.path.exists("%s.torrent" % dataFile)
        
        def seederLf():
            def fin():
                pass
            BitTorrent.download.download(
                ['--url', "file://%s.torrent" % dataFile,
                 "--kenosis", 1,
                 '--saveas', dataFile,
                 "--kenosis_bootstrap", "127.0.0.1:%s" % kenosisPort], 
                dummychoose, dummydisplay, fin, dummyerror, stopEvent, 80)
        taskList.addCallableTask(seederLf)

        dataFile2 = tempfile.mktemp()
        doneEvent = threading.Event()
        def leecherLf():
            time.sleep(2)
            print "leecher starting"
            ev = threading.Event()
            def fin(ev = ev):
                ev.set()
            BitTorrent.download.download(['--url', "file://%s.torrent" % dataFile,
                                          "--kenosis", 1,
                                          "--kenosis_bootstrap", "127.0.0.1:%s" % kenosisPort,
                                          '--saveas', dataFile2], 
                                         dummychoose, dummydisplay, fin, dummyerror, ev, 80)
            doneEvent.set()
            print "leecher done"
        taskList.addCallableTask(leecherLf)
            
        doneEvent.wait()
        self.assertEqual(dsfile.fileContents(path=dataFile), 
                         dsfile.fileContents(path=dataFile2))
        stopEvent.set()
        taskList.stop()
        while not taskList.activeTasks():
            time.sleep(0.1)

# This requires:
# - a connection to the internet
# - bittorrent ports to be open back to this computer
# - a tracker to be connected to the bt.kenosisp2p.org subnet.
class NetworkTest(dsunittest.TestCase):
    def testTrackerKenosisp2pOrg(self):
        btPort = 6969
        taskList = task.TaskList(maxThreads=2)

        stopEvent = threading.Event()
        taskList.start(wait=0)

        dataFile = tempfile.mktemp()
        dsfile.setFileContents(path=dataFile, data="dfasq2352436gfa" * 2048)

        btmakemetafile.make_meta_file(
            file=dataFile,
            url="http://nobodycachethis.bt.kenosisp2p.org:%s/announce" % btPort,
            piece_len_exp=18)
        assert os.path.exists("%s.torrent" % dataFile)
        
        def seederLf():
            def fin():
                pass
            BitTorrent.download.download(['--url', "file://%s.torrent" % dataFile,
                                          "--kenosis", 1,
                                          '--saveas', dataFile], 
                                         dummychoose, dummydisplay, fin, dummyerror, stopEvent, 80)
        taskList.addCallableTask(seederLf)

        dataFile2 = tempfile.mktemp()
        doneEvent = threading.Event()
        def leecherLf():
            time.sleep(2)
            print "leecher starting"
            ev = threading.Event()
            def fin(ev = ev):
                ev.set()
            BitTorrent.download.download(['--url', "file://%s.torrent" % dataFile,
                                          "--kenosis", 0,
                                          '--saveas', dataFile2], 
                                         dummychoose, dummydisplay, fin, dummyerror, ev, 80)
            doneEvent.set()
            print "leecher done"
        taskList.addCallableTask(leecherLf)
            
        doneEvent.wait()
        self.assertEqual(dsfile.fileContents(path=dataFile), 
                         dsfile.fileContents(path=dataFile2))
        stopEvent.set()
        taskList.stop()
        while not taskList.activeTasks():
            time.sleep(0.1)
        
        
if __name__ == "__main__":
    dsunittest.main()
    
