[svn r599] Automated test scripts in Python (it will runs over gcov, and generate reports on GMyth library running). trunk
authorrosfran
Wed Apr 25 01:07:56 2007 +0100 (2007-04-25)
branchtrunk
changeset 59395263ab433f1
parent 592 0f77fcb97269
child 594 f36075170a4e
[svn r599] Automated test scripts in Python (it will runs over gcov, and generate reports on GMyth library running).
gmyth/tests/Makefile.am
gmyth/tests/common.h
gmyth/tests/compile
gmyth/tests/compile_file_exists
gmyth/tests/compile_test_connection
gmyth/tests/compile_test_epg
gmyth/tests/compile_test_recorder
gmyth/tests/compile_test_recordings
gmyth/tests/gmyth_test_connection.c
gmyth/tests/gmyth_test_epg.c
gmyth/tests/gmyth_test_http.c
gmyth/tests/gmyth_test_livetv.c
gmyth/tests/gmyth_test_recorder.c
gmyth/tests/gmyth_test_recordings.c
gmyth/tests/gmyth_test_transcode.c
gmyth/tests/gmyth_test_vlc.c
gmyth/tests/test_connection.py
gmyth/tests/test_epg.py
gmyth/tests/test_http.py
gmyth/tests/test_livetv.py
gmyth/tests/test_recorder.py
gmyth/tests/test_recordings.py
gmyth/tests/test_transcode.py
gmyth/tests/test_vlc.py
gmyth/tests/testing_tools.py
gmyth/tests/utils.py
     1.1 --- a/gmyth/tests/Makefile.am	Tue Apr 24 19:45:27 2007 +0100
     1.2 +++ b/gmyth/tests/Makefile.am	Wed Apr 25 01:07:56 2007 +0100
     1.3 @@ -27,14 +27,14 @@
     1.4  
     1.5  TESTS = \
     1.6  	test \
     1.7 -	gmyth_test_connection \
     1.8 -	gmyth_test_epg \
     1.9 -	gmyth_test_recorder \
    1.10 -	gmyth_test_recordings \
    1.11 -	gmyth_test_transcode \
    1.12 -	gmyth_test_vlc \
    1.13 -	gmyth_test_livetv \
    1.14 -	gmyth_test_http
    1.15 +	test_connection.py \
    1.16 +	test_epg.py \
    1.17 +	test_recorder.py \
    1.18 +	test_recordings.py \
    1.19 +	test_transcode.py \
    1.20 +	test_vlc.py \
    1.21 +	test_livetv.py \
    1.22 +	test_http.py
    1.23  
    1.24  #TESTS_ENVIRONMENT = top_srcdir=$(top_srcdir) @GLIB_LIBS@ @GOBJECT_LIBS@ @LIBCURL_LIBS@
    1.25  
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/gmyth/tests/common.h	Wed Apr 25 01:07:56 2007 +0100
     2.3 @@ -0,0 +1,2 @@
     2.4 +
     2.5 +#define SYNC_STRING "===SYNC===\n"
     3.1 --- a/gmyth/tests/compile	Tue Apr 24 19:45:27 2007 +0100
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,3 +0,0 @@
     3.4 -#!/bin/bash
     3.5 -gcc -g $1 -o $2 `pkg-config --cflags --libs gmyth-0.1 glib-2.0 gthread-2.0`
     3.6 -
     4.1 --- a/gmyth/tests/compile_file_exists	Tue Apr 24 19:45:27 2007 +0100
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,1 +0,0 @@
     4.4 -gcc -o test_file_exists test_file_exists.c -DBIG_JOINS=1 -I/usr/include/mysql -I/usr/local/include/gmyth -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include  -L/usr/local/lib -lmysqlclient -lz -lcrypt -lnsl -lm -lgmyth -lgobject-2.0 -lglib-2.0
     5.1 --- a/gmyth/tests/compile_test_connection	Tue Apr 24 19:45:27 2007 +0100
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,1 +0,0 @@
     5.4 -gcc -o gmyth_test_connection gmyth_test_connection.c `pkg-config --cflags --libs gmyth-0.1 glib-2.0`
     6.1 --- a/gmyth/tests/compile_test_epg	Tue Apr 24 19:45:27 2007 +0100
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,1 +0,0 @@
     6.4 -gcc -o gmyth_test_epg gmyth_test_epg.c `pkg-config --cflags --libs gmyth glib-2.0`
     7.1 --- a/gmyth/tests/compile_test_recorder	Tue Apr 24 19:45:27 2007 +0100
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,1 +0,0 @@
     7.4 -gcc -o gmyth_test_recorder gmyth_test_recorder.c `pkg-config --cflags --libs gmyth-0.1`
     8.1 --- a/gmyth/tests/compile_test_recordings	Tue Apr 24 19:45:27 2007 +0100
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,1 +0,0 @@
     8.4 -gcc -o gmyth_test_recordings gmyth_test_recordings.c `pkg-config --cflags --libs gmyth-0.1 glib-2.0`
     9.1 --- a/gmyth/tests/gmyth_test_connection.c	Tue Apr 24 19:45:27 2007 +0100
     9.2 +++ b/gmyth/tests/gmyth_test_connection.c	Wed Apr 25 01:07:56 2007 +0100
     9.3 @@ -1,10 +1,15 @@
     9.4  #include <glib-object.h>
     9.5  
     9.6 +#include <string.h>
     9.7 +#include <stdio.h>
     9.8 +
     9.9  #include "gmyth_uri.h"
    9.10  #include "gmyth_backendinfo.h"
    9.11  #include "gmyth_socket.h"
    9.12  #include "gmyth_query.h"
    9.13  
    9.14 +#include "common.h"
    9.15 +
    9.16  static gboolean
    9.17  test_backend_connection1 (GMythBackendInfo *backend_info)
    9.18  {
    9.19 @@ -67,6 +72,13 @@
    9.20      test_backend_connection1 (backend_info);
    9.21      test_backend_connection2 (backend_info);
    9.22      test_mysql_connection1 (backend_info);
    9.23 +
    9.24 +    fprintf(stdout, SYNC_STRING);
    9.25 +    fflush(NULL);
    9.26 +    getchar();
    9.27 +
    9.28 +    return (0);
    9.29 +
    9.30  }
    9.31  
    9.32  
    10.1 --- a/gmyth/tests/gmyth_test_epg.c	Tue Apr 24 19:45:27 2007 +0100
    10.2 +++ b/gmyth/tests/gmyth_test_epg.c	Wed Apr 25 01:07:56 2007 +0100
    10.3 @@ -2,6 +2,8 @@
    10.4  #include "gmyth_backendinfo.h"
    10.5  #include "gmyth_epg.h"
    10.6  
    10.7 +#include "common.h"
    10.8 +
    10.9  static gboolean
   10.10  test_epg_connection (GMythBackendInfo *backend_info)
   10.11  {
   10.12 @@ -104,10 +106,14 @@
   10.13  
   10.14      backend_info = gmyth_backend_info_new_with_uri (argv[1]);
   10.15  
   10.16 +    fprintf(stdout, SYNC_STRING);
   10.17 +    fflush(NULL);
   10.18 +    getchar();
   10.19 +
   10.20      test_epg_connection (backend_info);
   10.21      test_epg_get_channels (backend_info);
   10.22      test_epg_get_channel_icon (backend_info);
   10.23  
   10.24 -    return 0;
   10.25 +    return(0);
   10.26  }
   10.27  
    11.1 --- a/gmyth/tests/gmyth_test_http.c	Tue Apr 24 19:45:27 2007 +0100
    11.2 +++ b/gmyth/tests/gmyth_test_http.c	Wed Apr 25 01:07:56 2007 +0100
    11.3 @@ -2,6 +2,8 @@
    11.4  #include "gmyth.h"
    11.5  #include <glib.h>
    11.6  
    11.7 +#include "common.h"
    11.8 +
    11.9  int
   11.10  main (int args, const char **argv)
   11.11  {
   11.12 @@ -52,6 +54,9 @@
   11.13      gint ret =  gmyth_http_retrieve_job_status(backend_info, 1000, start);
   11.14      printf("Status: %d\n\n", ret);
   11.15  
   11.16 +    fprintf(stdout, SYNC_STRING);
   11.17 +    fflush(NULL);
   11.18 +    getchar();
   11.19  
   11.20 -    return 0;    
   11.21 +    return(0);
   11.22  }
    12.1 --- a/gmyth/tests/gmyth_test_livetv.c	Tue Apr 24 19:45:27 2007 +0100
    12.2 +++ b/gmyth/tests/gmyth_test_livetv.c	Wed Apr 25 01:07:56 2007 +0100
    12.3 @@ -1,5 +1,7 @@
    12.4  #include <glib-object.h>
    12.5  
    12.6 +#include "common.h"
    12.7 +
    12.8  #include "gmyth_uri.h"
    12.9  #include "gmyth_backendinfo.h"
   12.10  #include "gmyth_livetv.h"
   12.11 @@ -131,6 +133,12 @@
   12.12          g_debug ("Error when running LiveTV setup test script!");
   12.13      else
   12.14          g_debug ("LiveTV setup test script finished with success.");
   12.15 +
   12.16 +    fprintf(stdout, SYNC_STRING);
   12.17 +    fflush(NULL);
   12.18 +    getchar();
   12.19 +
   12.20 +    return(0);
   12.21  }
   12.22  
   12.23  
    13.1 --- a/gmyth/tests/gmyth_test_recorder.c	Tue Apr 24 19:45:27 2007 +0100
    13.2 +++ b/gmyth/tests/gmyth_test_recorder.c	Wed Apr 25 01:07:56 2007 +0100
    13.3 @@ -6,6 +6,7 @@
    13.4  #include "gmyth_epg.h"
    13.5  #include "gmyth_common.h"
    13.6  
    13.7 +#include "common.h"
    13.8  
    13.9  static gboolean
   13.10  test_recorder_availability (GMythBackendInfo *backend_info)
   13.11 @@ -102,7 +103,6 @@
   13.12  int
   13.13  main (int args, const char **argv)
   13.14  {
   13.15 -    const char* uri = argv[1];
   13.16  
   13.17      GMythBackendInfo *backend_info;
   13.18      g_type_init ();
   13.19 @@ -115,6 +115,13 @@
   13.20  
   13.21      printf ("******** Testing recorder check channels function ***********\n");
   13.22      test_recorder_check_channels (backend_info);
   13.23 +
   13.24 +    fprintf(stdout, SYNC_STRING);
   13.25 +    fflush(NULL);
   13.26 +    getchar();
   13.27 +
   13.28 +    return(0);
   13.29 +
   13.30  }
   13.31  
   13.32  
    14.1 --- a/gmyth/tests/gmyth_test_recordings.c	Tue Apr 24 19:45:27 2007 +0100
    14.2 +++ b/gmyth/tests/gmyth_test_recordings.c	Wed Apr 25 01:07:56 2007 +0100
    14.3 @@ -6,6 +6,8 @@
    14.4  #include "gmyth_epg.h"
    14.5  #include "gmyth_common.h"
    14.6  
    14.7 +#include "common.h"
    14.8 +
    14.9  static gboolean
   14.10  test_recording_list (GMythBackendInfo *backend_info)
   14.11  {
   14.12 @@ -44,16 +46,17 @@
   14.13  int
   14.14  main (int args, const char **argv)
   14.15  {
   14.16 -    const char* uri = argv[1];
   14.17 -
   14.18      GMythBackendInfo *backend_info;
   14.19      g_type_init ();
   14.20  
   14.21      backend_info = gmyth_backend_info_new_with_uri (argv[1]);
   14.22  
   14.23      test_recording_list (backend_info);
   14.24 +
   14.25 +    fprintf(stdout, SYNC_STRING);
   14.26 +    fflush(NULL);
   14.27 +    getchar();
   14.28 +
   14.29 +    return(0);
   14.30  }
   14.31  
   14.32 -
   14.33 -
   14.34 -
    15.1 --- a/gmyth/tests/gmyth_test_transcode.c	Tue Apr 24 19:45:27 2007 +0100
    15.2 +++ b/gmyth/tests/gmyth_test_transcode.c	Wed Apr 25 01:07:56 2007 +0100
    15.3 @@ -7,6 +7,8 @@
    15.4  #include <gmyth/gmyth_socket.h>
    15.5  #include <gmyth/gmyth_query.h>
    15.6  
    15.7 +#include "common.h"
    15.8 +
    15.9  int
   15.10  main (int args, const char **argv)
   15.11  {
   15.12 @@ -33,8 +35,11 @@
   15.13      teste = gmyth_jobqueue_change_cmd(transcode, "STOP", "JOB_TRANSCODE");
   15.14  
   15.15  
   15.16 +    fprintf(stdout, SYNC_STRING);
   15.17 +    fflush(NULL);
   15.18 +    getchar();
   15.19 +
   15.20 +    return(0);
   15.21 +
   15.22  }
   15.23  
   15.24 -
   15.25 -
   15.26 -
    16.1 --- a/gmyth/tests/gmyth_test_vlc.c	Tue Apr 24 19:45:27 2007 +0100
    16.2 +++ b/gmyth/tests/gmyth_test_vlc.c	Wed Apr 25 01:07:56 2007 +0100
    16.3 @@ -2,6 +2,8 @@
    16.4  #include "gmyth.h"
    16.5  #include <glib.h>
    16.6  
    16.7 +#include "common.h"
    16.8 +
    16.9  int
   16.10  main (int args, const char **argv)
   16.11  {
   16.12 @@ -30,6 +32,9 @@
   16.13  
   16.14      //gchar* teste = gmyth_http_retrieve_setting(backend_info, "RecordFilePrefix", "hmelo-desktop");
   16.15  
   16.16 +    fprintf(stdout, SYNC_STRING);
   16.17 +    fflush(NULL);
   16.18 +    getchar();
   16.19  
   16.20 -    return 0;    
   16.21 +    return(0);
   16.22  }
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/gmyth/tests/test_connection.py	Wed Apr 25 01:07:56 2007 +0100
    17.3 @@ -0,0 +1,11 @@
    17.4 +#!/usr/bin/python
    17.5 +
    17.6 +#doc: test gmyth_socket_connection_* methods
    17.7 +
    17.8 +from testing_tools import start, finish
    17.9 +import sys
   17.10 +
   17.11 +p = start('gmyth_test_connection', ['myth://192.168.3.165:6543/livetv?channel=1'])
   17.12 +#p = start('gmyth_test_connection', ['livetv'])
   17.13 +
   17.14 +sys.exit(finish(p))
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/gmyth/tests/test_epg.py	Wed Apr 25 01:07:56 2007 +0100
    18.3 @@ -0,0 +1,10 @@
    18.4 +#!/usr/bin/python
    18.5 +
    18.6 +#doc: test gmyth_epg_* methods
    18.7 +
    18.8 +from testing_tools import start, finish
    18.9 +import sys
   18.10 +
   18.11 +p = start('gmyth_test_epg', ['myth://mythtv:mythtv@192.168.3.165:6543/?mythconverg'])
   18.12 +
   18.13 +sys.exit(finish(p))
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/gmyth/tests/test_http.py	Wed Apr 25 01:07:56 2007 +0100
    19.3 @@ -0,0 +1,10 @@
    19.4 +#!/usr/bin/python
    19.5 +
    19.6 +#doc: test gmyth_http_* methods
    19.7 +
    19.8 +from testing_tools import start, finish
    19.9 +import sys
   19.10 +
   19.11 +p = start('gmyth_test_http')
   19.12 +
   19.13 +sys.exit(finish(p))
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/gmyth/tests/test_livetv.py	Wed Apr 25 01:07:56 2007 +0100
    20.3 @@ -0,0 +1,10 @@
    20.4 +#!/usr/bin/python
    20.5 +
    20.6 +#doc: test gmyth_livetv_* methods
    20.7 +
    20.8 +from testing_tools import start, finish
    20.9 +import sys
   20.10 +
   20.11 +p = start('gmyth_test_livetv')
   20.12 +
   20.13 +sys.exit(finish(p))
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/gmyth/tests/test_recorder.py	Wed Apr 25 01:07:56 2007 +0100
    21.3 @@ -0,0 +1,10 @@
    21.4 +#!/usr/bin/python
    21.5 +
    21.6 +#doc: test gmyth_recorder_* methods
    21.7 +
    21.8 +from testing_tools import start, finish
    21.9 +import sys
   21.10 +
   21.11 +p = start('gmyth_test_recorder', ['myth://mythtv:mythtv@192.168.3.165:6543/?mythconverg'])
   21.12 +
   21.13 +sys.exit(finish(p))
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/gmyth/tests/test_recordings.py	Wed Apr 25 01:07:56 2007 +0100
    22.3 @@ -0,0 +1,10 @@
    22.4 +#!/usr/bin/python
    22.5 +
    22.6 +#doc: test gmyth_epg_* methods
    22.7 +
    22.8 +from testing_tools import start, finish
    22.9 +import sys
   22.10 +
   22.11 +p = start('gmyth_test_recordings', ['myth://mythtv:mythtv@192.168.3.165:6543/?mythconverg'])
   22.12 +
   22.13 +sys.exit(finish(p))
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/gmyth/tests/test_transcode.py	Wed Apr 25 01:07:56 2007 +0100
    23.3 @@ -0,0 +1,10 @@
    23.4 +#!/usr/bin/python
    23.5 +
    23.6 +#doc: test gmyth_transcoder_* methods
    23.7 +
    23.8 +from testing_tools import start, finish
    23.9 +import sys
   23.10 +
   23.11 +p = start('gmyth_test_transcode')
   23.12 +
   23.13 +sys.exit(finish(p))
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/gmyth/tests/test_vlc.py	Wed Apr 25 01:07:56 2007 +0100
    24.3 @@ -0,0 +1,10 @@
    24.4 +#!/usr/bin/python
    24.5 +
    24.6 +#doc: test gmyth_vlc_* methods
    24.7 +
    24.8 +from testing_tools import start, finish
    24.9 +import sys
   24.10 +
   24.11 +p = start('gmyth_test_vlc')
   24.12 +
   24.13 +sys.exit(finish(p))
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/gmyth/tests/testing_tools.py	Wed Apr 25 01:07:56 2007 +0100
    25.3 @@ -0,0 +1,118 @@
    25.4 +import re
    25.5 +import os
    25.6 +import time
    25.7 +import signal
    25.8 +import sys
    25.9 +import popen2
   25.10 +from utils import wait_string, sync_string
   25.11 +
   25.12 +def wait(p):
   25.13 +    r = p.poll()
   25.14 +    if r != -1:
   25.15 +        return r
   25.16 +    for i in range(5):
   25.17 +        time.sleep(1)
   25.18 +        r = p.poll()
   25.19 +        if r != -1:
   25.20 +            return r
   25.21 +    print 'killed!'
   25.22 +    os.kill(p.pid, signal.SIGKILL)
   25.23 +    return p.wait()
   25.24 +
   25.25 +class executable:
   25.26 +    def __init__(self, cmd, ignore):
   25.27 +        #assert isinstance(cmd, list)
   25.28 +        self.p = popen2.Popen3(cmd, capturestderr = True)
   25.29 +	print "Executing command... [ %s ]\n" % cmd
   25.30 +        self.stdin = self.p.tochild
   25.31 +        self.stdout = self.p.fromchild
   25.32 +        self.stderr = self.p.childerr
   25.33 +        self.ignore = ignore
   25.34 +
   25.35 +    #returns True if completed successfully
   25.36 +    def finish(self):
   25.37 +        r = wait(self.p)
   25.38 +        return r == 0
   25.39 +
   25.40 +class simple_exe (executable):
   25.41 +    def __init__(self, exe, ignore):
   25.42 +        cmd = './' + exe
   25.43 +        executable.__init__(self, cmd, ignore)
   25.44 +
   25.45 +class mudflap_exe (executable):
   25.46 +    def __init__(self, exe, ignore):
   25.47 +        cmd = ['./' + exe]
   25.48 +        executable.__init__(self, cmd, ignore)
   25.49 +
   25.50 +    #returns True if completed successfully
   25.51 +    def finish(self):
   25.52 +        r = wait(self.p)
   25.53 +        data  = self.stderr.read()
   25.54 +        if r != 0:
   25.55 +            print data
   25.56 +            return False
   25.57 +        viols = filter (lambda x: "mudflap violation" in x, data.split('\n'))
   25.58 +        return len(viols) <= self.ignore
   25.59 +
   25.60 +class valgrind_exe (executable):
   25.61 +    def __init__(self, exe, ignore):
   25.62 +        suppressions = os.environ['top_srcdir'] + '/tests/regression/suppressions'
   25.63 +        cmd = ['/usr/bin/valgrind', '--suppressions=' + suppressions,
   25.64 +               '--leak-check=full', exe]
   25.65 +        executable.__init__(self, cmd, ignore)
   25.66 +
   25.67 +    #returns True if completed successfully
   25.68 +    def finish(self):
   25.69 +        r = wait(self.p)
   25.70 +        data = self.stderr.read()
   25.71 +        if r != 0:
   25.72 +            print data
   25.73 +            return False
   25.74 +        a = re.search('ERROR SUMMARY: *(.*) err.*', data)
   25.75 +        errors = int(a.groups()[0])
   25.76 +        a = re.search('definitely lost: (.*) bytes', data)
   25.77 +        if a:
   25.78 +            a = int(a.groups()[0])
   25.79 +            if a != 0:
   25.80 +                errors += 1
   25.81 +        if errors != 0:
   25.82 +            print data
   25.83 +        return errors == 0
   25.84 +
   25.85 +def get_gcda(exe):
   25.86 +    f = open(exe)
   25.87 +    data = f.read()
   25.88 +    f.close()
   25.89 +    a = re.search('/.*\.gcda', data)
   25.90 +    if a == None:
   25.91 +        return None
   25.92 +    return a.group()
   25.93 +
   25.94 +def is_coverage(exe):
   25.95 +    t = get_gcda(exe)
   25.96 +    return t != None
   25.97 +
   25.98 +def is_mudflap(exe):
   25.99 +    p = popen2.Popen3(['ldd', exe])
  25.100 +    data = p.fromchild.read()
  25.101 +    p.wait()
  25.102 +    return 'libmudflapth' in data
  25.103 +
  25.104 +def relink_name(exe):
  25.105 +    return '.libs/lt-' + exe
  25.106 +
  25.107 +def start(exe, params = [], ignore = 0):
  25.108 +    exe   = exe + ' ' +  ' '.join(params)
  25.109 +    print 'Executing the command line: ', exe
  25.110 +    p = simple_exe(exe, ignore)
  25.111 +    wait_string(p.stdout, sync_string)
  25.112 +    return p
  25.113 +
  25.114 +def finish(p):
  25.115 +    p.stdin.write('\n')
  25.116 +    p.stdin.flush()
  25.117 +    r = p.finish()
  25.118 +    if r == True:
  25.119 +        return 0
  25.120 +    else:
  25.121 +        return 1
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/gmyth/tests/utils.py	Wed Apr 25 01:07:56 2007 +0100
    26.3 @@ -0,0 +1,11 @@
    26.4 +import os
    26.5 +import signal
    26.6 +import time
    26.7 +
    26.8 +def wait_string(file, string):
    26.9 +    while True:
   26.10 +        line = file.readline().strip()
   26.11 +        if line == string:
   26.12 +            return
   26.13 +
   26.14 +sync_string = '===SYNC==='