From 5b1d2e56a141e18eb3679f2a7798e856f6913d7b Mon Sep 17 00:00:00 2001
From: Dmitri Bogomolov <4glitch@gmail.com>
Date: Tue, 10 Apr 2018 18:29:39 +0300
Subject: [PATCH] Changes into test mode:   run in background, stop after 30
 sec since last API response

---
 .travis.yml           |  3 +++
 src/api.py            |  4 +++-
 src/bitmessagemain.py | 33 ++++++++++++++++++++++-----------
 3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 5dbda892..b2acd619 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,7 +7,10 @@ addons:
       - build-essential
       - libcap-dev
 install:
+  - pip install -r requirements.txt
+  - ln -s src pybitmessage  # tests environment
   - python setup.py install
 script:
   - python checkdeps.py
   - pybitmessage -t
+  - python setup.py test
diff --git a/src/api.py b/src/api.py
index 0493ecb7..4d1d404d 100644
--- a/src/api.py
+++ b/src/api.py
@@ -1456,7 +1456,9 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
     def _handle_request(self, method, params):
         if method not in self.handlers:
             raise APIError(20, 'Invalid method: %s' % method)
-        return self.handlers[method](self, params)
+        result = self.handlers[method](self, params)
+        state.last_api_response = time.time()
+        return result
 
     def _dispatch(self, method, params):
         # pylint: disable=attribute-defined-outside-init
diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py
index a063261d..20d48566 100755
--- a/src/bitmessagemain.py
+++ b/src/bitmessagemain.py
@@ -25,10 +25,8 @@ import getopt
 # Used to capture a Ctrl-C keypress so that Bitmessage can shutdown gracefully.
 import signal
 import socket
-from datetime import datetime
+import time
 from struct import pack
-from subprocess import call
-from time import sleep
 
 from helper_startup import (
     isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections
@@ -189,6 +187,20 @@ class Main:
             elif opt in ("-t", "--test"):
                 state.testmode = daemon = True
                 state.enableGUI = False  # run without a UI
+                # Fallback: in case when no api command was issued
+                state.last_api_response = time.time()
+                # Apply special settings
+                config = BMConfigParser()
+                config.set(
+                    'bitmessagesettings', 'apienabled', 'true')
+                config.set(
+                    'bitmessagesettings', 'apiusername', 'username')
+                config.set(
+                    'bitmessagesettings', 'apipassword', 'password')
+                config.set(
+                    'bitmessagesettings', 'apinotifypath',
+                    os.path.join(app_dir, 'tests', 'apinotify_handler.py')
+                )
 
         # is the application already running?  If yes then exit.
         if state.enableGUI and not state.curses and not depends.check_pyqt():
@@ -206,7 +218,7 @@ class Main:
             )
         shared.thisapp = singleinstance("", daemon)
 
-        if daemon and not state.testmode:
+        if daemon:
             with shared.printLock:
                 print('Running as a daemon. Send TERM signal to end.')
             self.daemonize()
@@ -346,12 +358,11 @@ class Main:
             BMConfigParser().remove_option('bitmessagesettings', 'dontconnect')
 
         if daemon:
-            if state.testmode:
-                sleep(30)
-                # make testing
-                self.stop()
             while state.shutdown == 0:
-                sleep(1)
+                time.sleep(1)
+                if (state.testmode and
+                        time.time() - state.last_api_response >= 30):
+                    self.stop()
 
     def daemonize(self):
         grandfatherPid = os.getpid()
@@ -362,7 +373,7 @@ class Main:
                 shared.thisapp.cleanup()
                 # wait until grandchild ready
                 while True:
-                    sleep(1)
+                    time.sleep(1)
                 os._exit(0)
         except AttributeError:
             # fork not implemented
@@ -383,7 +394,7 @@ class Main:
                 shared.thisapp.cleanup()
                 # wait until child ready
                 while True:
-                    sleep(1)
+                    time.sleep(1)
                 os._exit(0)
         except AttributeError:
             # fork not implemented