From eaa24281325edf38b4d756d86cace6278bd8cc66 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=81ukasz=20Nowak?= <luke@nexedi.com>
Date: Fri, 11 Oct 2019 09:05:41 +0200
Subject: [PATCH] caddy-frontend/test: Switch to slapos.testing.testcase

---
 software/caddy-frontend/test/test.py  |  30 ++-
 software/caddy-frontend/test/utils.py | 327 --------------------------
 2 files changed, 14 insertions(+), 343 deletions(-)
 delete mode 100644 software/caddy-frontend/test/utils.py

diff --git a/software/caddy-frontend/test/test.py b/software/caddy-frontend/test/test.py
index 31330fe43..37bfef383 100644
--- a/software/caddy-frontend/test/test.py
+++ b/software/caddy-frontend/test/test.py
@@ -54,9 +54,6 @@ try:
 except ImportError:
     from backports import lzma
 
-from utils import SlapOSInstanceTestCase
-from utils import findFreeTCPPort
-
 import datetime
 
 from cryptography import x509
@@ -66,6 +63,13 @@ from cryptography.hazmat.primitives import serialization
 from cryptography.hazmat.primitives.asymmetric import rsa
 from cryptography.x509.oid import NameOID
 
+from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
+from slapos.testing.utils import findFreeTCPPort
+setUpModule, SlapOSInstanceTestCase = makeModuleSetUpAndTestCaseClass(
+    os.path.abspath(
+        os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
+
+
 SLAPOS_TEST_IPV4 = os.environ['SLAPOS_TEST_IPV4']
 SLAPOS_TEST_IPV6 = os.environ['SLAPOS_TEST_IPV6']
 
@@ -467,12 +471,6 @@ class HttpFrontendTestCase(SlapOSInstanceTestCase):
   # show full diffs, as it is required for proper analysis of problems
   maxDiff = None
 
-  @classmethod
-  def getSoftwareURLList(cls):
-    return (
-      os.path.abspath(
-        os.path.join(os.path.dirname(__file__), '..', 'software.cfg')), )
-
   @classmethod
   def setUpClass(cls):
     super(HttpFrontendTestCase, cls).setUpClass()
@@ -797,8 +795,8 @@ class SlaveHttpFrontendTestCase(HttpFrontendTestCase):
         return False
     for slave_reference, partition_parameter_kw in cls\
             .getSlaveParameterDictDict().items():
-      parameter_dict = cls.slapos_controler.slap.registerOpenOrder().request(
-        software_release=cls.software_url_list[0],
+      parameter_dict = cls.request(
+        software_release=cls.getSoftwareURL(),
         partition_reference=slave_reference,
         partition_parameter_kw=partition_parameter_kw,
         shared=True
@@ -815,11 +813,11 @@ class SlaveHttpFrontendTestCase(HttpFrontendTestCase):
   @classmethod
   def setUpSlaves(cls):
     cls.slave_connection_parameter_dict_dict = {}
-    request = cls.slapos_controler.slap.registerOpenOrder().request
+    request = cls.slap.request
     for slave_reference, partition_parameter_kw in cls\
             .getSlaveParameterDictDict().items():
       slave_instance = request(
-        software_release=cls.software_url_list[0],
+        software_release=cls.getSoftwareURL(),
         partition_reference=slave_reference,
         partition_parameter_kw=partition_parameter_kw,
         shared=True
@@ -830,7 +828,7 @@ class SlaveHttpFrontendTestCase(HttpFrontendTestCase):
     for slave_reference, partition_parameter_kw in cls\
             .getSlaveParameterDictDict().items():
       slave_instance = request(
-        software_release=cls.software_url_list[0],
+        software_release=cls.getSoftwareURL(),
         partition_reference=slave_reference,
         partition_parameter_kw=partition_parameter_kw,
         shared=True
@@ -5917,8 +5915,8 @@ class TestSlaveSlapOSMasterCertificateCompatibility(
       ssl_ca_crt=ca.certificate_pem,
     )
 
-    self.slapos_controler.slap.registerOpenOrder().request(
-        software_release=self.software_url_list[0],
+    self.request(
+        software_release=self.cls.getSoftwareURL(),
         partition_reference='custom_domain_ssl_crt_ssl_key_ssl_ca_crt',
         partition_parameter_kw=slave_parameter_dict,
         shared=True
diff --git a/software/caddy-frontend/test/utils.py b/software/caddy-frontend/test/utils.py
deleted file mode 100644
index 85867b0fd..000000000
--- a/software/caddy-frontend/test/utils.py
+++ /dev/null
@@ -1,327 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2018 Nexedi SA and Contributors. All Rights Reserved.
-#
-# WARNING: This program as such is intended to be used by professional
-# programmers who take the whole responsibility of assessing all potential
-# consequences resulting from its eventual inadequacies and bugs
-# End users who are looking for a ready-to-use solution with commercial
-# guarantees and support are strongly adviced to contract a Free Software
-# Service Company
-#
-# 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-#
-##############################################################################
-
-import unittest
-import os
-import socket
-from contextlib import closing
-import logging
-import StringIO
-import xmlrpclib
-
-import supervisor.xmlrpc
-from erp5.util.testnode.SlapOSControler import SlapOSControler
-from erp5.util.testnode.ProcessManager import ProcessManager
-
-
-# Utility functions
-def findFreeTCPPort(ip=''):
-  """Find a free TCP port to listen to.
-  """
-  family = socket.AF_INET6 if ':' in ip else socket.AF_INET
-  with closing(socket.socket(family, socket.SOCK_STREAM)) as s:
-    s.bind((ip, 0))
-    return s.getsockname()[1]
-
-
-# TODO:
-#  - allow requesting multiple instances ?
-
-class SlapOSInstanceTestCase(unittest.TestCase):
-  """Install one slapos instance.
-
-  This test case install software(s) and request one instance during
-  `setUpClass` and destroy the instance during `tearDownClass`.
-
-  Software Release URL, Instance Software Type and Instance Parameters can be
-  defined on the class.
-
-  All tests from the test class will run with the same instance.
-
-  The following class attributes are available:
-
-    * `computer_partition`:  the computer partition instance, implementing
-    `slapos.slap.interface.slap.IComputerPartition`.
-
-    * `computer_partition_root_path`: the path of the instance root directory.
-
-  """
-
-  # Methods to be defined by subclasses.
-  @classmethod
-  def getSoftwareURLList(cls):
-    """Return URL of software releases to install.
-
-    To be defined by subclasses.
-    """
-    raise NotImplementedError()
-
-  @classmethod
-  def getInstanceParameterDict(cls):
-    """Return instance parameters
-
-    To be defined by subclasses if they need to request instance with specific
-    parameters.
-    """
-    return {}
-
-  @classmethod
-  def getInstanceSoftwareType(cls):
-    """Return software type for instance, default "default"
-
-    To be defined by subclasses if they need to request instance with specific
-    software type.
-    """
-    return "default"
-
-  # Utility methods.
-  @classmethod
-  def getSupervisorRPCServer(cls):
-    """Returns a XML-RPC connection to the supervisor used by slapos node
-
-    Refer to http://supervisord.org/api.html for details of available methods.
-    """
-    # xmlrpc over unix socket https://stackoverflow.com/a/11746051/7294664
-    return xmlrpclib.ServerProxy(
-       'http://slapos-supervisor',
-       transport=supervisor.xmlrpc.SupervisorTransport(
-           None,
-           None,
-           # XXX hardcoded socket path
-           serverurl="unix://{working_directory}/inst/supervisord.socket".format(
-             **cls.config)))
-
-  # Unittest methods
-  @classmethod
-  def setUpClass(cls):
-    """Setup the class, build software and request an instance.
-
-    If you have to override this method, do not forget to call this method on
-    parent class.
-    """
-    try:
-      cls.setUpWorkingDirectory()
-      cls.setUpConfig()
-      cls.setUpSlapOSController()
-
-      cls.runSoftwareRelease()
-      # XXX instead of "runSoftwareRelease", it would be better to be closer to slapos usage:
-      # cls.supplySoftwares()
-      # cls.installSoftwares()
-
-      cls.runComputerPartition()
-      # XXX instead of "runComputerPartition", it would be better to be closer to slapos usage:
-      # cls.requestInstances()
-      # cls.createInstances()
-      # cls.requestInstances()
-
-    except Exception:
-      cls.stopSlapOSProcesses()
-      raise
-
-  @classmethod
-  def tearDownClass(cls):
-    """Tear down class, stop the processes and destroy instance.
-    """
-    cls.stopSlapOSProcesses()
-
-  # Implementation
-  @classmethod
-  def stopSlapOSProcesses(cls):
-    if hasattr(cls, '_process_manager'):
-      cls._process_manager.killPreviousRun()
-
-  @classmethod
-  def setUpWorkingDirectory(cls):
-    """Initialise the directories"""
-    cls.working_directory = os.environ.get(
-        'SLAPOS_TEST_WORKING_DIR',
-        os.path.join(os.path.dirname(__file__), '.slapos'))
-    # To prevent error: Cannot open an HTTP server: socket.error reported
-    # AF_UNIX path too long This `working_directory` should not be too deep.
-    # Socket path is 108 char max on linux
-    # https://github.com/torvalds/linux/blob/3848ec5/net/unix/af_unix.c#L234-L238
-    # Supervisord socket name contains the pid number, which is why we add
-    # .xxxxxxx in this check.
-    if len(cls.working_directory + '/inst/supervisord.socket.xxxxxxx') > 108:
-      raise RuntimeError('working directory ( {} ) is too deep, try setting '
-              'SLAPOS_TEST_WORKING_DIR'.format(cls.working_directory))
-
-    if not os.path.exists(cls.working_directory):
-      os.mkdir(cls.working_directory)
-
-  @classmethod
-  def setUpConfig(cls):
-    """Create slapos configuration"""
-    cls.config = {
-      "working_directory": cls.working_directory,
-      "slapos_directory": cls.working_directory,
-      "log_directory": cls.working_directory,
-      "computer_id": 'slapos.test',  # XXX
-      'proxy_database': os.path.join(cls.working_directory, 'proxy.db'),
-      'partition_reference': 'T',  # minimise path length, see https://github.com/apache/trafficserver/issues/2421
-      # "proper" slapos command must be in $PATH
-      'slapos_binary': 'slapos',
-      'node_quantity': '3',
-    }
-    # Some tests are expecting that local IP is not set to 127.0.0.1
-    ipv4_address = os.environ.get('SLAPOS_TEST_IPV4', '127.0.1.1')
-    ipv6_address = os.environ['SLAPOS_TEST_IPV6']
-
-    cls.config['proxy_host'] = cls.config['ipv4_address'] = ipv4_address
-    cls.config['ipv6_address'] = ipv6_address
-    cls.config['proxy_port'] = findFreeTCPPort(ipv4_address)
-    cls.config['master_url'] = 'http://{proxy_host}:{proxy_port}'.format(
-      **cls.config)
-
-  @classmethod
-  def setUpSlapOSController(cls):
-    """Create the a "slapos controller" and supply softwares from `getSoftwareURLList`.
-
-    This is equivalent to:
-
-    slapos proxy start
-    for sr in getSoftwareURLList; do
-      slapos supply $SR $COMP
-    done
-    """
-    cls._process_manager = ProcessManager()
-
-    # XXX this code is copied from testnode code
-    cls.slapos_controler = SlapOSControler(
-        cls.working_directory,
-        cls.config
-    )
-
-    slapproxy_log = os.path.join(cls.config['log_directory'], 'slapproxy.log')
-    logger = logging.getLogger(__name__)
-    logger.debug('Configured slapproxy log to %r', slapproxy_log)
-
-    cls.software_url_list = cls.getSoftwareURLList()
-    cls.slapos_controler.initializeSlapOSControler(
-        slapproxy_log=slapproxy_log,
-        process_manager=cls._process_manager,
-        reset_software=False,
-        software_path_list=cls.software_url_list)
-
-    # XXX we should check *earlier* if that pidfile exist and if supervisord
-    # process still running, because if developer started supervisord (or bugs?)
-    # then another supervisord will start and starting services a second time
-    # will fail.
-    cls._process_manager.supervisord_pid_file = os.path.join(
-      cls.slapos_controler.instance_root, 'var', 'run', 'supervisord.pid')
-
-  @classmethod
-  def runSoftwareRelease(cls):
-    """Run all the software releases that were supplied before.
-
-    This is the equivalent of `slapos node software`.
-
-    The tests will be marked file if software building fail.
-    """
-    logger = logging.getLogger()
-    logger.level = logging.DEBUG
-    stream = StringIO.StringIO()
-    stream_handler = logging.StreamHandler(stream)
-    logger.addHandler(stream_handler)
-
-    try:
-      cls.software_status_dict = cls.slapos_controler.runSoftwareRelease(
-        cls.config, environment=os.environ)
-      stream.seek(0)
-      stream.flush()
-      message = ''.join(stream.readlines()[-100:])
-      assert cls.software_status_dict['status_code'] == 0, message
-    finally:
-      logger.removeHandler(stream_handler)
-      del stream
-
-
-  @classmethod
-  def runComputerPartition(cls, max_quantity=None):
-    """Instanciate the software.
-
-    This is the equivalent of doing:
-
-    slapos request --type=getInstanceSoftwareType --parameters=getInstanceParameterDict
-    slapos node instance
-
-    and return the slapos request instance parameters.
-
-    This can be called by tests to simulate re-request with different parameters.
-    """
-    run_cp_kw = {}
-    if max_quantity is not None:
-      run_cp_kw['max_quantity'] = max_quantity
-    logger = logging.getLogger()
-    logger.level = logging.DEBUG
-    stream = StringIO.StringIO()
-    stream_handler = logging.StreamHandler(stream)
-    logger.addHandler(stream_handler)
-
-    if cls.getInstanceSoftwareType() != 'default':
-      raise NotImplementedError
-
-    instance_parameter_dict = cls.getInstanceParameterDict()
-    try:
-      cls.instance_status_dict = cls.slapos_controler.runComputerPartition(
-        cls.config,
-        cluster_configuration=instance_parameter_dict,
-        environment=os.environ,
-        **run_cp_kw)
-      stream.seek(0)
-      stream.flush()
-      message = ''.join(stream.readlines()[-100:])
-      assert cls.instance_status_dict['status_code'] == 0, message
-    finally:
-      logger.removeHandler(stream_handler)
-      del stream
-
-    # FIXME: similar to test node, only one (root) partition is really
-    #        supported for now.
-    computer_partition_list = []
-    for i in range(len(cls.software_url_list)):
-      computer_partition_list.append(
-          cls.slapos_controler.slap.registerOpenOrder().request(
-            cls.software_url_list[i],
-            # This is how testnode's SlapOSControler name created partitions
-            partition_reference='testing partition {i}'.format(
-              i=i, **cls.config),
-            partition_parameter_kw=instance_parameter_dict))
-
-    # expose some class attributes so that tests can use them:
-    # the ComputerPartition instances, to getInstanceParameterDict
-    cls.computer_partition = computer_partition_list[0]
-
-    # the path of the instance on the filesystem, for low level inspection
-    cls.computer_partition_root_path = os.path.join(
-        cls.config['working_directory'],
-        'inst',
-        cls.computer_partition.getId())
-
-
-
-- 
2.30.9