diff options
| -rw-r--r-- | LICENSE | 4 | ||||
| -rw-r--r-- | changes/feature_add_mail_ui | 1 | ||||
| -rw-r--r-- | data/images/mail-locked.png | bin | 0 -> 2326 bytes | |||
| -rw-r--r-- | data/images/mail-unlocked.png | bin | 0 -> 2791 bytes | |||
| -rw-r--r-- | data/resources/icons.qrc | 2 | ||||
| -rwxr-xr-x | setup.py | 2 | ||||
| -rw-r--r-- | src/leap/bitmask/gui/mainwindow.py | 2 | ||||
| -rw-r--r-- | src/leap/bitmask/gui/statuspanel.py | 243 | ||||
| -rw-r--r-- | src/leap/bitmask/gui/ui/statuspanel.ui | 220 | ||||
| -rw-r--r-- | src/leap/bitmask/services/eip/tests/test_eipconfig.py | 3 | ||||
| -rw-r--r-- | src/leap/bitmask/services/eip/tests/test_providerbootstrapper.py | 24 | ||||
| -rw-r--r-- | src/leap/bitmask/services/eip/tests/test_vpngatewayselector.py | 15 | ||||
| -rw-r--r-- | src/leap/bitmask/util/tests/test_streamtologger.py | 4 | 
13 files changed, 455 insertions, 65 deletions
@@ -694,5 +694,9 @@ WebSite: http://www.everaldo.com/  ---  data/images/oxygen-icons/ +The following icons were created based on 'mail-unread.png' from oxygen: +data/images/mail-locked.png +data/images/mail-unlocked.png +  License: LGPL - http://www.gnu.org/licenses/lgpl.html  Website: http://www.oxygen-icons.org/ diff --git a/changes/feature_add_mail_ui b/changes/feature_add_mail_ui new file mode 100644 index 00000000..c7c0f2ce --- /dev/null +++ b/changes/feature_add_mail_ui @@ -0,0 +1 @@ +  o Add first draft of the UI for Encrypted Mail. Closes #3499.
\ No newline at end of file diff --git a/data/images/mail-locked.png b/data/images/mail-locked.png Binary files differnew file mode 100644 index 00000000..2108ca1c --- /dev/null +++ b/data/images/mail-locked.png diff --git a/data/images/mail-unlocked.png b/data/images/mail-unlocked.png Binary files differnew file mode 100644 index 00000000..fc3c11b0 --- /dev/null +++ b/data/images/mail-unlocked.png diff --git a/data/resources/icons.qrc b/data/resources/icons.qrc index 6a6de9e6..1cc574e2 100644 --- a/data/resources/icons.qrc +++ b/data/resources/icons.qrc @@ -1,5 +1,7 @@  <RCC>    <qresource prefix="/"> +    <file>../images/mail-locked.png</file> +    <file>../images/mail-unlocked.png</file>      <file>../images/light/16/down-arrow.png</file>      <file>../images/light/16/up-arrow.png</file>      <file>../images/light/64/network-eip-acquiring.png</file> @@ -19,7 +19,7 @@ import versioneer  versioneer.versionfile_source = 'src/leap/bitmask/_version.py'  versioneer.versionfile_build = 'leap/bitmask/_version.py'  versioneer.tag_prefix = ''  # tags are like 1.2.0 -#versioneer.parentdir_prefix = 'bitmask-' +versioneer.parentdir_prefix = 'leap.bitmask-'  #from setuptools import Command diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index ef39181b..e84b7a7b 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1090,8 +1090,6 @@ class MainWindow(QtGui.QMainWindow):                  #self._status_panel.set_eip_status(                  #    self.tr("MX is disabled")) - -      def _get_socket_host(self):          """          Returns the socket and port to be used for VPN diff --git a/src/leap/bitmask/gui/statuspanel.py b/src/leap/bitmask/gui/statuspanel.py index eb731927..f5c74bed 100644 --- a/src/leap/bitmask/gui/statuspanel.py +++ b/src/leap/bitmask/gui/statuspanel.py @@ -28,7 +28,9 @@ from PySide import QtCore, QtGui  from leap.bitmask.services.eip.vpnprocess import VPNManager  from leap.bitmask.platform_init import IS_WIN, IS_LINUX  from leap.bitmask.util import first -from leap.common.check import leap_assert_type +from leap.common.check import leap_assert, leap_assert_type +from leap.common.events import register +from leap.common.events import events_pb2 as proto  from ui_statuspanel import Ui_StatusPanel @@ -116,6 +118,14 @@ class StatusPanelWidget(QtGui.QWidget):      RATE_STR = "%14.2f KB/s"      TOTAL_STR = "%14.2f Kb" +    MAIL_OFF_ICON = ":/images/mail-unlocked.png" +    MAIL_ON_ICON = ":/images/mail-locked.png" + +    _soledad_event = QtCore.Signal(object) +    _smtp_event = QtCore.Signal(object) +    _imap_event = QtCore.Signal(object) +    _keymanager_event = QtCore.Signal(object) +      def __init__(self, parent=None):          QtGui.QWidget.__init__(self, parent) @@ -143,6 +153,73 @@ class StatusPanelWidget(QtGui.QWidget):          self._set_traffic_rates()          self._make_status_clickable() +        register(signal=proto.KEYMANAGER_LOOKING_FOR_KEY, +                 callback=self._mail_handle_keymanager_events, +                 reqcbk=lambda req, resp: None) + +        register(signal=proto.KEYMANAGER_KEY_FOUND, +                 callback=self._mail_handle_keymanager_events, +                 reqcbk=lambda req, resp: None) + +        # register(signal=proto.KEYMANAGER_KEY_NOT_FOUND, +        #          callback=self._mail_handle_keymanager_events, +        #          reqcbk=lambda req, resp: None) + +        register(signal=proto.KEYMANAGER_STARTED_KEY_GENERATION, +                 callback=self._mail_handle_keymanager_events, +                 reqcbk=lambda req, resp: None) + +        register(signal=proto.KEYMANAGER_FINISHED_KEY_GENERATION, +                 callback=self._mail_handle_keymanager_events, +                 reqcbk=lambda req, resp: None) + +        register(signal=proto.KEYMANAGER_DONE_UPLOADING_KEYS, +                 callback=self._mail_handle_keymanager_events, +                 reqcbk=lambda req, resp: None) + +        register(signal=proto.SOLEDAD_DONE_DOWNLOADING_KEYS, +                 callback=self._mail_handle_soledad_events, +                 reqcbk=lambda req, resp: None) + +        register(signal=proto.SOLEDAD_DONE_UPLOADING_KEYS, +                 callback=self._mail_handle_soledad_events, +                 reqcbk=lambda req, resp: None) + +        register(signal=proto.SMTP_SERVICE_STARTED, +                 callback=self._mail_handle_smtp_events, +                 reqcbk=lambda req, resp: None) + +        register(signal=proto.SMTP_SERVICE_FAILED_TO_START, +                 callback=self._mail_handle_smtp_events, +                 reqcbk=lambda req, resp: None) + +        register(signal=proto.IMAP_SERVICE_STARTED, +                 callback=self._mail_handle_imap_events, +                 reqcbk=lambda req, resp: None) + +        register(signal=proto.IMAP_SERVICE_FAILED_TO_START, +                 callback=self._mail_handle_imap_events, +                 reqcbk=lambda req, resp: None) + +        register(signal=proto.IMAP_UNREAD_MAIL, +                 callback=self._mail_handle_imap_events, +                 reqcbk=lambda req, resp: None) + +        self._set_long_mail_status("") +        self.ui.lblUnread.setVisible(False) + +        self._smtp_started = False +        self._imap_started = False + +        self._soledad_event.connect( +            self._mail_handle_soledad_events_slot) +        self._imap_event.connect( +            self._mail_handle_imap_events_slot) +        self._smtp_event.connect( +            self._mail_handle_smtp_events_slot) +        self._keymanager_event.connect( +            self._mail_handle_keymanager_events_slot) +      def _make_status_clickable(self):          """          Makes upload and download figures clickable. @@ -460,3 +537,167 @@ class StatusPanelWidget(QtGui.QWidget):      def set_provider(self, provider):          self.ui.lblProvider.setText(provider) + +    def _mail_handle_soledad_events(self, req): +        """ +        Callback for ... + +        :param req: Request type +        :type req: leap.common.events.events_pb2.SignalRequest +        """ +        self._soledad_event.emit(req) + +    def _mail_handle_soledad_events_slot(self, req): +        """ +        SLOT +        TRIGGER: _mail_handle_soledad_events + +        Reacts to an Soledad event + +        :param req: Request type +        :type req: leap.common.events.events_pb2.SignalRequest +        """ +        self.ui.lblMailStatus.setText(self.tr("Starting...")) + +        ext_status = "" + +        if req.event == proto.SOLEDAD_DONE_UPLOADING_KEYS: +            ext_status = self.tr("Soledad has started...") +        elif req.event == proto.SOLEDAD_DONE_DOWNLOADING_KEYS: +            ext_status = self.tr("Soledad is starting, please wait...") +        else: +            leap_assert(False, +                        "Don't know how to handle this state: %s" +                        % (req.event)) + +        self._set_long_mail_status(ext_status) + +    def _mail_handle_keymanager_events(self, req): +        """ +        Callback for the KeyManager events + +        :param req: Request type +        :type req: leap.common.events.events_pb2.SignalRequest +        """ +        self._keymanager_event.emit(req) + +    def _mail_handle_keymanager_events_slot(self, req): +        """ +        SLOT +        TRIGGER: _mail_handle_keymanager_events + +        Reacts to an KeyManager event + +        :param req: Request type +        :type req: leap.common.events.events_pb2.SignalRequest +        """ +        self.ui.lblMailStatus.setText(self.tr("Starting...")) + +        ext_status = "" + +        if req.event == proto.KEYMANAGER_LOOKING_FOR_KEY: +            ext_status = self.tr("Looking for key for this user") +        elif req.event == proto.KEYMANAGER_KEY_FOUND: +            ext_status = self.tr("Found key! Starting mail...") +        # elif req.event == proto.KEYMANAGER_KEY_NOT_FOUND: +        #     ext_status = self.tr("Key not found!") +        elif req.event == proto.KEYMANAGER_STARTED_KEY_GENERATION: +            ext_status = self.tr("Generating new key, please wait...") +        elif req.event == proto.KEYMANAGER_FINISHED_KEY_GENERATION: +            ext_status = self.tr("Finished generating key!") +        elif req.event == proto.KEYMANAGER_DONE_UPLOADING_KEYS: +            ext_status = self.tr("Starting mail...") +        else: +            leap_assert(False, +                        "Don't know how to handle this state: %s" +                        % (req.event)) + +        self._set_long_mail_status(ext_status) + +    def _mail_handle_smtp_events(self, req): +        """ +        Callback for the SMTP events + +        :param req: Request type +        :type req: leap.common.events.events_pb2.SignalRequest +        """ +        self._smtp_event.emit(req) + +    def _mail_handle_smtp_events_slot(self, req): +        """ +        SLOT +        TRIGGER: _mail_handle_smtp_events + +        Reacts to an SMTP event + +        :param req: Request type +        :type req: leap.common.events.events_pb2.SignalRequest +        """ +        ext_status = "" + +        if req.event == proto.SMTP_SERVICE_STARTED: +            ext_status = self.tr("SMTP has started...") +            self._smtp_started = True +            if self._smtp_started and self._imap_started: +                self.ui.lblMailStatus.setText(self.tr("ON")) +                self.ui.lblMailIcon.setPixmap(QtGui.QPixmap(self.MAIL_ON_ICON)) +                self.ui.lblMailIcon.setPixmap(QtGui.QPixmap(":/images/mail-locked.png")) +                ext_status = "" +        elif req.event == proto.SMTP_SERVICE_FAILED_TO_START: +            ext_status = self.tr("SMTP failed to start, check the logs.") +            self.ui.lblMailStatus.setText(self.tr("Failed")) +        else: +            leap_assert(False, +                        "Don't know how to handle this state: %s" +                        % (req.event)) + +        self._set_long_mail_status(ext_status) + +    def _mail_handle_imap_events(self, req): +        """ +        Callback for the IMAP events + +        :param req: Request type +        :type req: leap.common.events.events_pb2.SignalRequest +        """ +        self._imap_event.emit(req) + +    def _mail_handle_imap_events_slot(self, req): +        """ +        SLOT +        TRIGGER: _mail_handle_imap_events + +        Reacts to an IMAP event + +        :param req: Request type +        :type req: leap.common.events.events_pb2.SignalRequest +        """ +        ext_status = None + +        if req.event == proto.IMAP_SERVICE_STARTED: +            ext_status = self.tr("IMAP has started...") +            self._imap_started = True +            if self._smtp_started and self._imap_started: +                self.ui.lblMailStatus.setText(self.tr("ON")) +                self.ui.lblMailIcon.setPixmap(QtGui.QPixmap(self.MAIL_ON_ICON)) +                ext_status = "" +        elif req.event == proto.IMAP_SERVICE_FAILED_TO_START: +            ext_status = self.tr("IMAP failed to start, check the logs.") +            self.ui.lblMailStatus.setText(self.tr("Failed")) +        elif req.event == proto.IMAP_UNREAD_MAIL: +            if self._smtp_started and self._imap_started: +                self.ui.lblUnread.setText(self.tr("%s Unread Emails") % (req.content)) +                self.ui.lblUnread.setVisible(req.content != "0") +                self.ui.lblMailStatus.setText(self.tr("ON")) +                self.ui.lblMailIcon.setPixmap(QtGui.QPixmap(self.MAIL_ON_ICON)) +        else: +            leap_assert(False, +                        "Don't know how to handle this state: %s" +                        % (req.event)) + +        if ext_status is not None: +            self._set_long_mail_status(ext_status) + +    def _set_long_mail_status(self, ext_status): +        self.ui.lblLongMailStatus.setText(ext_status) +        self.ui.grpMailStatus.setVisible(len(ext_status) > 0) diff --git a/src/leap/bitmask/gui/ui/statuspanel.ui b/src/leap/bitmask/gui/ui/statuspanel.ui index 39992e1a..d77af1da 100644 --- a/src/leap/bitmask/gui/ui/statuspanel.ui +++ b/src/leap/bitmask/gui/ui/statuspanel.ui @@ -6,7 +6,7 @@     <rect>      <x>0</x>      <y>0</y> -    <width>384</width> +    <width>470</width>      <height>477</height>     </rect>    </property> @@ -36,36 +36,40 @@        <string notr="true"/>       </property>       <layout class="QGridLayout" name="gridLayout"> -      <item row="0" column="1"> -       <layout class="QHBoxLayout" name="eip_controls"> -        <item> -         <widget class="QLabel" name="label"> +      <item row="5" column="1"> +       <layout class="QGridLayout" name="gridLayout_3"> +        <item row="1" column="0" colspan="3"> +         <widget class="QLabel" name="lblUnread">            <property name="text"> -           <string>Encrypted Internet: </string> +           <string>0 Unread Emails</string>            </property>           </widget>          </item> -        <item> -         <widget class="QLabel" name="lblEIPStatus"> +        <item row="0" column="1"> +         <widget class="QLabel" name="lblMailStatus">            <property name="styleSheet">             <string notr="true">font: bold;</string>            </property>            <property name="text"> -           <string>Off</string> -          </property> -          <property name="textFormat"> -           <enum>Qt::AutoText</enum> +           <string>Disabled</string>            </property> -          <property name="alignment"> -           <set>Qt::AlignCenter</set> +         </widget> +        </item> +        <item row="0" column="0"> +         <widget class="QLabel" name="label_4"> +          <property name="sizePolicy"> +           <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +            <horstretch>0</horstretch> +            <verstretch>0</verstretch> +           </sizepolicy>            </property> -          <property name="wordWrap"> -           <bool>false</bool> +          <property name="text"> +           <string>Encrypted Mail:</string>            </property>           </widget>          </item> -        <item> -         <spacer name="horizontalSpacer"> +        <item row="0" column="2"> +         <spacer name="horizontalSpacer_4">            <property name="orientation">             <enum>Qt::Horizontal</enum>            </property> @@ -77,50 +81,21 @@            </property>           </spacer>          </item> -        <item> -         <widget class="QPushButton" name="btnEipStartStop"> -          <property name="text"> -           <string>Turn On</string> +        <item row="2" column="0" colspan="3"> +         <spacer name="verticalSpacer_3"> +          <property name="orientation"> +           <enum>Qt::Vertical</enum>            </property> -         </widget> +          <property name="sizeHint" stdset="0"> +           <size> +            <width>20</width> +            <height>1</height> +           </size> +          </property> +         </spacer>          </item>         </layout>        </item> -      <item row="2" column="0"> -       <spacer name="verticalSpacer_2"> -        <property name="orientation"> -         <enum>Qt::Vertical</enum> -        </property> -        <property name="sizeType"> -         <enum>QSizePolicy::Preferred</enum> -        </property> -        <property name="sizeHint" stdset="0"> -         <size> -          <width>0</width> -          <height>11</height> -         </size> -        </property> -       </spacer> -      </item> -      <item row="0" column="0" rowspan="2"> -       <widget class="QLabel" name="lblVPNStatusIcon"> -        <property name="maximumSize"> -         <size> -          <width>64</width> -          <height>64</height> -         </size> -        </property> -        <property name="text"> -         <string/> -        </property> -        <property name="pixmap"> -         <pixmap resource="../../../../../data/resources/icons.qrc">:/images/light/64/network-eip-down.png</pixmap> -        </property> -        <property name="alignment"> -         <set>Qt::AlignCenter</set> -        </property> -       </widget> -      </item>        <item row="1" column="1">         <layout class="QHBoxLayout" name="eip_bandwidth">          <property name="spacing"> @@ -242,6 +217,85 @@          </item>         </layout>        </item> +      <item row="2" column="0"> +       <spacer name="verticalSpacer_2"> +        <property name="orientation"> +         <enum>Qt::Vertical</enum> +        </property> +        <property name="sizeType"> +         <enum>QSizePolicy::Preferred</enum> +        </property> +        <property name="sizeHint" stdset="0"> +         <size> +          <width>0</width> +          <height>11</height> +         </size> +        </property> +       </spacer> +      </item> +      <item row="0" column="0" rowspan="2"> +       <widget class="QLabel" name="lblVPNStatusIcon"> +        <property name="maximumSize"> +         <size> +          <width>64</width> +          <height>64</height> +         </size> +        </property> +        <property name="text"> +         <string/> +        </property> +        <property name="pixmap"> +         <pixmap resource="../../../../../data/resources/icons.qrc">:/images/light/64/network-eip-down.png</pixmap> +        </property> +        <property name="alignment"> +         <set>Qt::AlignCenter</set> +        </property> +       </widget> +      </item> +      <item row="4" column="0" rowspan="2"> +       <widget class="QLabel" name="lblMailIcon"> +        <property name="sizePolicy"> +         <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +          <horstretch>0</horstretch> +          <verstretch>0</verstretch> +         </sizepolicy> +        </property> +        <property name="minimumSize"> +         <size> +          <width>64</width> +          <height>64</height> +         </size> +        </property> +        <property name="maximumSize"> +         <size> +          <width>64</width> +          <height>999</height> +         </size> +        </property> +        <property name="text"> +         <string/> +        </property> +        <property name="pixmap"> +         <pixmap resource="../../../../../data/resources/icons.qrc">:/images/mail-unlocked.png</pixmap> +        </property> +       </widget> +      </item> +      <item row="7" column="0" colspan="2"> +       <widget class="QGroupBox" name="grpMailStatus"> +        <property name="title"> +         <string/> +        </property> +        <layout class="QVBoxLayout" name="verticalLayout_2"> +         <item> +          <widget class="QLabel" name="lblLongMailStatus"> +           <property name="text"> +            <string>...</string> +           </property> +          </widget> +         </item> +        </layout> +       </widget> +      </item>        <item row="3" column="0" colspan="2">         <widget class="QGroupBox" name="globalStatusBox">          <property name="enabled"> @@ -264,6 +318,56 @@          </layout>         </widget>        </item> +      <item row="0" column="1"> +       <layout class="QHBoxLayout" name="eip_controls"> +        <item> +         <widget class="QLabel" name="label"> +          <property name="text"> +           <string>Encrypted Internet: </string> +          </property> +         </widget> +        </item> +        <item> +         <widget class="QLabel" name="lblEIPStatus"> +          <property name="styleSheet"> +           <string notr="true">font: bold;</string> +          </property> +          <property name="text"> +           <string>Off</string> +          </property> +          <property name="textFormat"> +           <enum>Qt::AutoText</enum> +          </property> +          <property name="alignment"> +           <set>Qt::AlignCenter</set> +          </property> +          <property name="wordWrap"> +           <bool>false</bool> +          </property> +         </widget> +        </item> +        <item> +         <spacer name="horizontalSpacer"> +          <property name="orientation"> +           <enum>Qt::Horizontal</enum> +          </property> +          <property name="sizeHint" stdset="0"> +           <size> +            <width>40</width> +            <height>20</height> +           </size> +          </property> +         </spacer> +        </item> +        <item> +         <widget class="QPushButton" name="btnEipStartStop"> +          <property name="text"> +           <string>Turn On</string> +          </property> +         </widget> +        </item> +       </layout> +      </item>       </layout>      </widget>     </item> diff --git a/src/leap/bitmask/services/eip/tests/test_eipconfig.py b/src/leap/bitmask/services/eip/tests/test_eipconfig.py index f8489e07..76305e83 100644 --- a/src/leap/bitmask/services/eip/tests/test_eipconfig.py +++ b/src/leap/bitmask/services/eip/tests/test_eipconfig.py @@ -30,8 +30,7 @@ from mock import Mock  sample_config = { -    "gateways": [ -    { +    "gateways": [{          "capabilities": {              "adblock": False,              "filter_dns": True, diff --git a/src/leap/bitmask/services/eip/tests/test_providerbootstrapper.py b/src/leap/bitmask/services/eip/tests/test_providerbootstrapper.py index 93467d3a..b0685676 100644 --- a/src/leap/bitmask/services/eip/tests/test_providerbootstrapper.py +++ b/src/leap/bitmask/services/eip/tests/test_providerbootstrapper.py @@ -64,7 +64,10 @@ class ProviderBootstrapperTest(BaseLeapTest):          self.pb._check_name_resolution()          # Something highly likely to fail          self.pb._domain = "uquhqweuihowquie.abc.def" -        with self.assertRaises(socket.gaierror): + +        # In python 2.7.4 raises socket.error +        # In python 2.7.5 raises socket.gaierror +        with self.assertRaises((socket.gaierror, socket.error)):              self.pb._check_name_resolution()      @deferred() @@ -441,6 +444,25 @@ class ProviderBootstrapperActiveTest(unittest.TestCase):          self.assertFalse(ProviderConfig.save.called)      @mock.patch( +        'leap.bitmask.config.providerconfig.ProviderConfig.get_domain', +        lambda x: where('testdomain.com')) +    def test_download_provider_info_not_modified_and_no_cacert(self): +        self._setup_provider_config_with("1", tempfile.mkdtemp()) +        self._setup_providerbootstrapper(True) +        provider_path = self._produce_dummy_provider_json() + +        # set mtime to something really new +        os.utime(provider_path, (-1, time.time())) + +        with mock.patch.object( +                ProviderConfig, 'get_api_uri', +                return_value="https://localhost:%s" % (self.https_port,)): +            self.pb._download_provider_info() +        # we check that it doesn't save the provider +        # config, because it's new enough +        self.assertFalse(ProviderConfig.save.called) + +    @mock.patch(          'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path',          lambda x: where('cacert.pem'))      def test_download_provider_info_modified(self): diff --git a/src/leap/bitmask/services/eip/tests/test_vpngatewayselector.py b/src/leap/bitmask/services/eip/tests/test_vpngatewayselector.py index f9a177a9..36f8a076 100644 --- a/src/leap/bitmask/services/eip/tests/test_vpngatewayselector.py +++ b/src/leap/bitmask/services/eip/tests/test_vpngatewayselector.py @@ -19,6 +19,7 @@ tests for vpngatewayselector  """  import unittest +import time  from leap.bitmask.services.eip.eipconfig import EIPConfig, VPNGatewaySelector  from leap.common.testing.basetest import BaseLeapTest @@ -128,5 +129,19 @@ class VPNGatewaySelectorTest(BaseLeapTest):          self.assertEqual(gateways, [ips[4], ips[2], ips[3], ips[1]]) +class VPNGatewaySelectorDSTTest(VPNGatewaySelectorTest): +    """ +    VPNGatewaySelector's tests. +    It uses the opposite value of the current DST. +    """ +    def setUp(self): +        self._original_daylight = time.daylight +        time.daylight = not time.daylight +        VPNGatewaySelectorTest.setUp(self) + +    def tearDown(self): +        VPNGatewaySelectorTest.tearDown(self) +        time.daylight = self._original_daylight +  if __name__ == "__main__":      unittest.main() diff --git a/src/leap/bitmask/util/tests/test_streamtologger.py b/src/leap/bitmask/util/tests/test_streamtologger.py index c4e55b3a..fc97b794 100644 --- a/src/leap/bitmask/util/tests/test_streamtologger.py +++ b/src/leap/bitmask/util/tests/test_streamtologger.py @@ -117,6 +117,10 @@ class StreamToLoggerTest(BaseLeapTest):          self.assertEqual(log, message)          self.assertEqual(log_level, logging.ERROR) +    def test_twisted_log(self): +        from twisted.python import log +        log.startLogging(sys.stdout) +  if __name__ == "__main__":      unittest.main(verbosity=2)  | 
