slap.py 44.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
##############################################################################
#
# Copyright (c) 2010 Vifib SARL 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.
#
##############################################################################
27

Bryton Lacquement's avatar
Bryton Lacquement committed
28 29
from __future__ import print_function

30
import logging
31
import os
32
import unittest
Bryton Lacquement's avatar
Bryton Lacquement committed
33
from six.moves.urllib import parse
34
import tempfile
35

36 37
import httmock

38
import slapos.slap
Bryton Lacquement's avatar
Bryton Lacquement committed
39
from slapos.util import dumps
40

41 42 43 44

class UndefinedYetException(Exception):
  """To catch exceptions which are not yet defined"""

45

46 47
class SlapMixin(unittest.TestCase):
  """
48
  Useful methods for slap tests
49 50 51 52 53 54 55
  """
  def setUp(self):
    self._server_url = os.environ.get('TEST_SLAP_SERVER_URL', None)
    if self._server_url is None:
      self.server_url = 'http://localhost/'
    else:
      self.server_url = self._server_url
Bryton Lacquement's avatar
Bryton Lacquement committed
56
    print('Testing against SLAP server %r' % self.server_url)
57 58
    self.slap = slapos.slap.slap()
    self.partition_id = 'PARTITION_01'
Bryton Lacquement's avatar
Bryton Lacquement committed
59
    os.environ.pop('SLAPGRID_INSTANCE_ROOT', None)
60 61

  def tearDown(self):
62
    pass
63

64 65 66 67 68 69
  def _getTestComputerId(self):
    """
    Returns the computer id used by the test
    """
    return self.id()

70

71 72 73 74 75 76 77
class TestSlap(SlapMixin):
  """
  Test slap against slap server
  """

  def test_slap_initialisation(self):
    """
78
    Asserts that slap initialisation works properly in case of
79 80 81 82
    passing correct url
    """
    slap_instance = slapos.slap.slap()
    slap_instance.initializeConnection(self.server_url)
83
    self.assertEqual(slap_instance._connection_helper.slapgrid_uri, self.server_url)
84

85 86
  def test_slap_initialisation_ipv6_and_port(self):
    slap_instance = slapos.slap.slap()
87
    slap_instance.initializeConnection("http://fe80:1234:1234:1234:1:1:1:1:5000/foo/")
88 89
    self.assertEqual(
        slap_instance._connection_helper.slapgrid_uri,
90
        "http://[fe80:1234:1234:1234:1:1:1:1]:5000/foo/"
91 92 93 94
    )

  def test_slap_initialisation_ipv6_without_port(self):
    slap_instance = slapos.slap.slap()
95
    slap_instance.initializeConnection("http://fe80:1234:1234:1234:1:1:1:1/foo/")
96 97
    self.assertEqual(
        slap_instance._connection_helper.slapgrid_uri,
98
        "http://[fe80:1234:1234:1234:1:1:1:1]/foo/"
99 100 101 102
    )

  def test_slap_initialisation_ipv6_with_bracket(self):
    slap_instance = slapos.slap.slap()
103
    slap_instance.initializeConnection("http://[fe80:1234:1234:1234:1:1:1:1]:5000/foo/")
104 105
    self.assertEqual(
        slap_instance._connection_helper.slapgrid_uri,
106
        "http://[fe80:1234:1234:1234:1:1:1:1]:5000/foo/"
107 108 109 110 111 112 113 114 115 116 117
    )

  def test_slap_initialisation_ipv4(self):
    slap_instance = slapos.slap.slap()
    slap_instance.initializeConnection("http://127.0.0.1:5000/foo/")
    self.assertEqual(
        slap_instance._connection_helper.slapgrid_uri,
        "http://127.0.0.1:5000/foo/"
    )

  def test_slap_initialisation_hostname(self):
118
    # XXX this really opens a connection !
119
    slap_instance = slapos.slap.slap()
120
    slap_instance.initializeConnection("http://example.com:80/foo/")
121 122
    self.assertEqual(
        slap_instance._connection_helper.slapgrid_uri,
123
        "http://example.com:80/foo/"
124 125
    )

126 127
  def test_registerComputer_with_new_guid(self):
    """
128
    Asserts that calling slap.registerComputer with new guid returns
129 130 131 132 133 134
    Computer object
    """
    computer_guid = self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
    computer = self.slap.registerComputer(computer_guid)
Marco Mariani's avatar
Marco Mariani committed
135
    self.assertIsInstance(computer, slapos.slap.Computer)
136 137 138

  def test_registerComputer_with_existing_guid(self):
    """
139
    Asserts that calling slap.registerComputer with already used guid
140 141 142 143 144 145
    returns Computer object
    """
    computer_guid = self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
    computer = self.slap.registerComputer(computer_guid)
Marco Mariani's avatar
Marco Mariani committed
146
    self.assertIsInstance(computer, slapos.slap.Computer)
147 148

    computer2 = self.slap.registerComputer(computer_guid)
Marco Mariani's avatar
Marco Mariani committed
149
    self.assertIsInstance(computer2, slapos.slap.Computer)
150 151 152 153 154

  # XXX: There is naming conflict in slap library.
  # SoftwareRelease is currently used as suboject of Slap transmission object
  def test_registerSoftwareRelease_with_new_uri(self):
    """
155
    Asserts that calling slap.registerSoftwareRelease with new guid
156 157 158 159 160 161
    returns SoftwareRelease object
    """
    software_release_uri = 'http://server/' + self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
    software_release = self.slap.registerSoftwareRelease(software_release_uri)
Marco Mariani's avatar
Marco Mariani committed
162
    self.assertIsInstance(software_release, slapos.slap.SoftwareRelease)
163 164 165

  def test_registerSoftwareRelease_with_existing_uri(self):
    """
166
    Asserts that calling slap.registerSoftwareRelease with already
167 168 169 170 171 172
    used guid returns SoftwareRelease object
    """
    software_release_uri = 'http://server/' + self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
    software_release = self.slap.registerSoftwareRelease(software_release_uri)
Marco Mariani's avatar
Marco Mariani committed
173
    self.assertIsInstance(software_release, slapos.slap.SoftwareRelease)
174 175

    software_release2 = self.slap.registerSoftwareRelease(software_release_uri)
Marco Mariani's avatar
Marco Mariani committed
176
    self.assertIsInstance(software_release2, slapos.slap.SoftwareRelease)
177 178 179

  def test_registerComputerPartition_new_partition_id_known_computer_guid(self):
    """
180
    Asserts that calling slap.registerComputerPartition on known computer
181 182
    returns ComputerPartition object
    """
183 184
    computer_guid = self._getTestComputerId()
    partition_id = self.partition_id
185
    self.slap.initializeConnection(self.server_url)
186 187
    self.slap.registerComputer(computer_guid)

188
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
189
      qs = parse.parse_qs(url.query)
190 191 192 193 194 195 196 197
      if (url.path == '/registerComputerPartition'
            and qs == {
                'computer_reference': [computer_guid],
                'computer_partition_reference': [partition_id]
                }):
        partition = slapos.slap.ComputerPartition(computer_guid, partition_id)
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
198
                'content': dumps(partition)
199
                }
200
      else:
201 202 203
        return {'status_code': 400}

    self._handler = handler
204

205 206 207
    with httmock.HTTMock(handler):
      partition = self.slap.registerComputerPartition(computer_guid, partition_id)
      self.assertIsInstance(partition, slapos.slap.ComputerPartition)
208 209 210

  def test_registerComputerPartition_existing_partition_id_known_computer_guid(self):
    """
211
    Asserts that calling slap.registerComputerPartition on known computer
212 213 214
    returns ComputerPartition object
    """
    self.test_registerComputerPartition_new_partition_id_known_computer_guid()
215 216 217 218
    with httmock.HTTMock(self._handler):
      partition = self.slap.registerComputerPartition(self._getTestComputerId(),
                                                      self.partition_id)
      self.assertIsInstance(partition, slapos.slap.ComputerPartition)
219 220 221

  def test_registerComputerPartition_unknown_computer_guid(self):
    """
222
    Asserts that calling slap.registerComputerPartition on unknown
223
    computer raises NotFoundError exception
224 225 226 227 228
    """
    computer_guid = self._getTestComputerId()
    self.slap.initializeConnection(self.server_url)
    partition_id = 'PARTITION_01'

229
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
230
      qs = parse.parse_qs(url.query)
231 232 233 234 235 236
      if (url.path == '/registerComputerPartition'
            and qs == {
                'computer_reference': [computer_guid],
                'computer_partition_reference': [partition_id]
                }):
        return {'status_code': 404}
237
      else:
238 239 240 241 242 243
        return {'status_code': 0}

    with httmock.HTTMock(handler):
      self.assertRaises(slapos.slap.NotFoundError,
                        self.slap.registerComputerPartition,
                        computer_guid, partition_id)
244

245

246 247 248 249 250 251 252
  def test_getFullComputerInformation_empty_computer_guid(self):
    """
    Asserts that calling getFullComputerInformation with empty computer_id
    raises early, before calling master.
    """
    self.slap.initializeConnection(self.server_url)

253
    def handler(url, req):
254 255
      # Shouldn't even be called
      self.assertFalse(True)
256

257 258 259 260
    with httmock.HTTMock(handler):
      self.assertRaises(slapos.slap.NotFoundError,
                        self.slap._connection_helper.getFullComputerInformation,
                        None)
261 262 263 264 265 266 267 268

  def test_registerComputerPartition_empty_computer_guid(self):
    """
    Asserts that calling registerComputerPartition with empty computer_id
    raises early, before calling master.
    """
    self.slap.initializeConnection(self.server_url)

269
    def handler(url, req):
270 271
      # Shouldn't even be called
      self.assertFalse(True)
272

273 274 275 276
    with httmock.HTTMock(handler):
      self.assertRaises(slapos.slap.NotFoundError,
                        self.slap.registerComputerPartition,
                        None, 'PARTITION_01')
277 278 279 280 281 282 283 284

  def test_registerComputerPartition_empty_computer_partition_id(self):
    """
    Asserts that calling registerComputerPartition with empty
    computer_partition_id raises early, before calling master.
    """
    self.slap.initializeConnection(self.server_url)

285
    def handler(url, req):
286 287
      # Shouldn't even be called
      self.assertFalse(True)
288

289 290 291 292
    with httmock.HTTMock(handler):
      self.assertRaises(slapos.slap.NotFoundError,
                        self.slap.registerComputerPartition,
                        self._getTestComputerId(), None)
293 294 295 296 297 298 299 300

  def test_registerComputerPartition_empty_computer_guid_empty_computer_partition_id(self):
    """
    Asserts that calling registerComputerPartition with empty
    computer_partition_id raises early, before calling master.
    """
    self.slap.initializeConnection(self.server_url)

301
    def handler(url, req):
302 303
      # Shouldn't even be called
      self.assertFalse(True)
304

305 306 307 308
    with httmock.HTTMock(handler):
      self.assertRaises(slapos.slap.NotFoundError,
                        self.slap.registerComputerPartition,
                        None, None)
309

310

311 312 313 314 315 316 317 318 319 320
  def test_getSoftwareReleaseListFromSoftwareProduct_software_product_reference(self):
    """
    Check that slap.getSoftwareReleaseListFromSoftwareProduct calls
    "/getSoftwareReleaseListFromSoftwareProduct" URL with correct parameters,
    with software_product_reference parameter being specified.
    """
    self.slap.initializeConnection(self.server_url)
    software_product_reference = 'random_reference'
    software_release_url_list = ['1', '2']

321
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
322
      qs = parse.parse_qs(url.query)
323 324 325 326
      if (url.path == '/getSoftwareReleaseListFromSoftwareProduct'
            and qs == {'software_product_reference': [software_product_reference]}):
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
327
                'content': dumps(software_release_url_list)
328 329 330 331 332
                }

    with httmock.HTTMock(handler):
      self.assertEqual(
        self.slap.getSoftwareReleaseListFromSoftwareProduct(
333
          software_product_reference=software_product_reference),
334 335
        software_release_url_list
      )
336 337 338 339 340 341 342 343 344 345 346

  def test_getSoftwareReleaseListFromSoftwareProduct_software_release_url(self):
    """
    Check that slap.getSoftwareReleaseListFromSoftwareProduct calls
    "/getSoftwareReleaseListFromSoftwareProduct" URL with correct parameters,
    with software_release_url parameter being specified.
    """
    self.slap.initializeConnection(self.server_url)
    software_release_url = 'random_url'
    software_release_url_list = ['1', '2']

347
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
348
      qs = parse.parse_qs(url.query)
349 350 351 352
      if (url.path == '/getSoftwareReleaseListFromSoftwareProduct'
         and qs == {'software_release_url': [software_release_url]}):
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
353
                'content': dumps(software_release_url_list)
354 355 356 357 358 359 360 361
                }

    with httmock.HTTMock(handler):
      self.assertEqual(
        self.slap.getSoftwareReleaseListFromSoftwareProduct(
            software_release_url=software_release_url),
        software_release_url_list
      )
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382

  def test_getSoftwareReleaseListFromSoftwareProduct_too_many_parameters(self):
    """
    Check that slap.getSoftwareReleaseListFromSoftwareProduct raises if
    both parameters are set.
    """
    self.assertRaises(
      AttributeError,
      self.slap.getSoftwareReleaseListFromSoftwareProduct, 'foo', 'bar'
    )

  def test_getSoftwareReleaseListFromSoftwareProduct_no_parameter(self):
    """
    Check that slap.getSoftwareReleaseListFromSoftwareProduct raises if
    both parameters are either not set or None.
    """
    self.assertRaises(
      AttributeError,
      self.slap.getSoftwareReleaseListFromSoftwareProduct
    )

383 384 385 386 387 388
  def test_initializeConnection_getHateoasUrl(self):
    """
    Test that by default, slap will try to fetch Hateoas URL from XML/RPC URL.
    """
    hateoas_url = 'foo'
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
389
      qs = parse.parse_qs(url.query)
390 391 392 393 394 395 396
      if (url.path == '/getHateoasUrl'):
        return {
                'status_code': 200,
                'content': hateoas_url
                }

    with httmock.HTTMock(handler):
397
      self.slap.initializeConnection('http://%s' % self.id())
398 399 400 401 402 403 404 405 406 407 408 409
    self.assertEqual(
        self.slap._hateoas_navigator.slapos_master_hateoas_uri,
        hateoas_url
    )

  def test_initializeConnection_specifiedHateoasUrl(self):
    """
    Test that if rest URL is specified, slap will NOT try to fetch
    Hateoas URL from XML/RPC URL.
    """
    hateoas_url = 'foo'
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
410
      qs = parse.parse_qs(url.query)
411 412 413 414
      if (url.path == '/getHateoasUrl'):
        self.fail('slap should not have contacted master to get Hateoas URL.')

    with httmock.HTTMock(handler):
415
      self.slap.initializeConnection('http://%s' % self.id(), slapgrid_rest_uri=hateoas_url)
416 417 418 419 420 421 422 423 424 425 426 427
    self.assertEqual(
        self.slap._hateoas_navigator.slapos_master_hateoas_uri,
        hateoas_url
    )

  def test_initializeConnection_noHateoasUrl(self):
    """
    Test that if no rest URL is specified and master does not know about rest,
    it still work.
    """
    hateoas_url = 'foo'
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
428
      qs = parse.parse_qs(url.query)
429 430 431 432 433 434
      if (url.path == '/getHateoasUrl'):
        return {
                'status_code': 404,
                }

    with httmock.HTTMock(handler):
435
      self.slap.initializeConnection('http://%s' % self.id())
436 437
    self.assertEqual(None, getattr(self.slap, '_hateoas_navigator', None))

438

439 440 441 442 443 444 445 446 447 448
class TestComputer(SlapMixin):
  """
  Tests slapos.slap.slap.Computer class functionality
  """

  def test_computer_getComputerPartitionList_no_partition(self):
    """
    Asserts that calling Computer.getComputerPartitionList without Computer
    Partitions returns empty list
    """
449 450 451
    computer_guid = self._getTestComputerId()
    slap = self.slap
    slap.initializeConnection(self.server_url)
452

453
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
454
      qs = parse.parse_qs(url.query)
455 456 457
      if (url.path == '/registerComputerPartition'
              and 'computer_reference' in qs
              and 'computer_partition_reference' in qs):
458
        slap_partition = slapos.slap.ComputerPartition(
459 460 461 462
            qs['computer_reference'][0],
            qs['computer_partition_reference'][0])
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
463
                'content': dumps(slap_partition)
464 465 466 467
                }
      elif (url.path == '/getFullComputerInformation'
              and 'computer_id' in qs):
        slap_computer = slapos.slap.Computer(qs['computer_id'][0])
468 469
        slap_computer._software_release_list = []
        slap_computer._computer_partition_list = []
470 471
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
472
                'content': dumps(slap_computer)
473 474 475
                }
      elif url.path == '/requestComputerPartition':
        return {'status_code': 408}
476
      else:
477
        return {'status_code': 404}
478

479 480 481
    with httmock.HTTMock(handler):
      computer = self.slap.registerComputer(computer_guid)
      self.assertEqual(computer.getComputerPartitionList(), [])
482

483 484 485 486 487 488 489
  def _test_computer_empty_computer_guid(self, computer_method):
    """
    Helper method checking if calling Computer method with empty id raises
    early.
    """
    self.slap.initializeConnection(self.server_url)

490
    def handler(url, req):
491 492
      # Shouldn't even be called
      self.assertFalse(True)
493

494 495 496 497
    with httmock.HTTMock(handler):
      computer = self.slap.registerComputer(None)
      self.assertRaises(slapos.slap.NotFoundError,
                        getattr(computer, computer_method))
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512

  def test_computer_getComputerPartitionList_empty_computer_guid(self):
    """
    Asserts that calling getComputerPartitionList with empty
    computer_guid raises early, before calling master.
    """
    self._test_computer_empty_computer_guid('getComputerPartitionList')

  def test_computer_getSoftwareReleaseList_empty_computer_guid(self):
    """
    Asserts that calling getSoftwareReleaseList with empty
    computer_guid raises early, before calling master.
    """
    self._test_computer_empty_computer_guid('getSoftwareReleaseList')

513 514
  def test_computer_getComputerPartitionList_only_partition(self):
    """
515
    Asserts that calling Computer.getComputerPartitionList with only
516 517 518 519 520 521
    Computer Partitions returns empty list
    """
    self.computer_guid = self._getTestComputerId()
    partition_id = 'PARTITION_01'
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
522 523

    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
524
      qs = parse.parse_qs(url.query)
525 526 527 528 529 530 531 532
      if (url.path == '/registerComputerPartition'
            and qs == {
                'computer_reference': [self.computer_guid],
                'computer_partition_reference': [partition_id]
                }):
        partition = slapos.slap.ComputerPartition(self.computer_guid, partition_id)
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
533
                'content': dumps(partition)
534 535 536 537 538 539 540
                }
      elif (url.path == '/getFullComputerInformation'
              and 'computer_id' in qs):
        slap_computer = slapos.slap.Computer(qs['computer_id'][0])
        slap_computer._computer_partition_list = []
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
541
                'content': dumps(slap_computer)
542 543 544 545 546 547 548 549 550
                }
      else:
        return {'status_code': 400}

    with httmock.HTTMock(handler):
      self.computer = self.slap.registerComputer(self.computer_guid)
      self.partition = self.slap.registerComputerPartition(self.computer_guid,
                                                           partition_id)
      self.assertEqual(self.computer.getComputerPartitionList(), [])
551

552
  @unittest.skip("Not implemented")
553 554
  def test_computer_reportUsage_non_valid_xml_raises(self):
    """
555
    Asserts that calling Computer.reportUsage with non DTD
556 557
    (not defined yet) XML raises (not defined yet) exception
    """
558

559 560 561 562 563 564 565
    self.computer_guid = self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
    self.computer = self.slap.registerComputer(self.computer_guid)
    non_dtd_xml = """<xml>
<non-dtd-parameter name="xerxes">value<non-dtd-parameter name="xerxes">
</xml>"""
566 567 568
    self.assertRaises(UndefinedYetException,
                      self.computer.reportUsage,
                      non_dtd_xml)
569

570
  @unittest.skip("Not implemented")
571 572
  def test_computer_reportUsage_valid_xml_invalid_partition_raises(self):
    """
573
    Asserts that calling Computer.reportUsage with DTD (not defined
574 575 576 577 578 579 580 581 582
    yet) XML which refers to invalid partition raises (not defined yet)
    exception
    """
    self.computer_guid = self._getTestComputerId()
    partition_id = 'PARTITION_01'
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
    self.computer = self.slap.registerComputer(self.computer_guid)
    self.partition = self.slap.registerComputerPartition(self.computer_guid,
583
                                                         partition_id)
584 585 586 587
    # XXX: As DTD is not defined currently proper XML is not known
    bad_partition_dtd_xml = """<xml>
<computer-partition id='ANOTHER_PARTITION>96.5% CPU</computer-partition>
</xml>"""
588 589 590 591
    self.assertRaises(UndefinedYetException,
                      self.computer.reportUsage,
                      bad_partition_dtd_xml)

592 593 594 595

class RequestWasCalled(Exception):
  pass

596

597 598 599 600 601 602 603
class TestComputerPartition(SlapMixin):
  """
  Tests slapos.slap.slap.ComputerPartition class functionality
  """

  def test_request_sends_request(self):
    partition_id = 'PARTITION_01'
604

605
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
606
      qs = parse.parse_qs(url.query)
607 608 609
      if (url.path == '/registerComputerPartition'
              and 'computer_reference' in qs
              and 'computer_partition_reference' in qs):
610
        slap_partition = slapos.slap.ComputerPartition(
611 612 613 614
            qs['computer_reference'][0],
            qs['computer_partition_reference'][0])
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
615
                'content': dumps(slap_partition)
616 617 618 619
                }
      elif (url.path == '/getComputerInformation'
              and 'computer_id' in qs):
        slap_computer = slapos.slap.Computer(qs['computer_id'][0])
620 621
        slap_computer._software_release_list = []
        slap_partition = slapos.slap.ComputerPartition(
622
            qs['computer_id'][0],
623
            partition_id)
624
        slap_computer._computer_partition_list = [slap_partition]
625 626
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
627
                'content': dumps(slap_computer)
628 629
                }
      elif url.path == '/requestComputerPartition':
630 631
        raise RequestWasCalled
      else:
632 633 634 635 636 637 638 639 640 641 642 643 644 645
        return {
                'status_code': 404
                }

    with httmock.HTTMock(handler):
      self.computer_guid = self._getTestComputerId()
      self.slap = slapos.slap.slap()
      self.slap.initializeConnection(self.server_url)
      computer_partition = self.slap.registerComputerPartition(
          self.computer_guid, partition_id)
      self.assertRaises(RequestWasCalled,
                        computer_partition.request,
                        'http://server/new/' + self._getTestComputerId(),
                        'software_type', 'myref')
646 647 648

  def test_request_not_raises(self):
    partition_id = 'PARTITION_01'
649

650
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
651
      qs = parse.parse_qs(url.query)
652 653 654
      if (url.path == '/registerComputerPartition'
              and 'computer_reference' in qs
              and 'computer_partition_reference' in qs):
655
        slap_partition = slapos.slap.ComputerPartition(
656 657 658 659
            qs['computer_reference'][0],
            qs['computer_partition_reference'][0])
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
660
                'content': dumps(slap_partition)
661 662 663 664
                }
      elif (url.path == '/getComputerInformation'
              and 'computer_id' in qs):
        slap_computer = slapos.slap.Computer(qs['computer_id'][0])
665 666
        slap_computer._software_release_list = []
        slap_partition = slapos.slap.ComputerPartition(
667
            qs['computer_id'][0],
668
            partition_id)
669
        slap_computer._computer_partition_list = [slap_partition]
670 671
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
672
                'content': dumps(slap_computer)
673 674 675
                }
      elif url.path == '/requestComputerPartition':
        return {'status_code': 408}
676
      else:
677
        return {'status_code': 404}
678

679 680 681
    self.computer_guid = self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
682 683 684 685 686 687 688 689
    with httmock.HTTMock(handler):
      computer_partition = self.slap.registerComputerPartition(
          self.computer_guid, partition_id)
      requested_partition = computer_partition.request(
          'http://server/new/' + self._getTestComputerId(),
          'software_type',
          'myref')
      self.assertIsInstance(requested_partition, slapos.slap.ComputerPartition)
690 691 692

  def test_request_raises_later(self):
    partition_id = 'PARTITION_01'
693

694
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
695
      qs = parse.parse_qs(url.query)
696 697 698
      if (url.path == '/registerComputerPartition' and
              'computer_reference' in qs and
              'computer_partition_reference' in qs):
699
        slap_partition = slapos.slap.ComputerPartition(
700 701 702 703
            qs['computer_reference'][0],
            qs['computer_partition_reference'][0])
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
704
                'content': dumps(slap_partition)
705 706 707 708
                }
      elif (url.path == '/getComputerInformation'
              and 'computer_id' in qs):
        slap_computer = slapos.slap.Computer(qs['computer_id'][0])
709 710
        slap_computer._software_release_list = []
        slap_partition = slapos.slap.ComputerPartition(
711
            qs['computer_id'][0],
712
            partition_id)
713
        slap_computer._computer_partition_list = [slap_partition]
714 715
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
716
                'content': dumps(slap_computer)
717 718 719
                }
      elif url.path == '/requestComputerPartition':
        return {'status_code': 408}
720
      else:
721
        return {'status_code': 404}
722

723 724 725
    self.computer_guid = self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
726 727 728 729 730 731 732 733 734 735 736
    with httmock.HTTMock(handler):
      computer_partition = self.slap.registerComputerPartition(
          self.computer_guid, partition_id)
      requested_partition = computer_partition.request(
          'http://server/new/' + self._getTestComputerId(),
          'software_type',
          'myref')
      self.assertIsInstance(requested_partition, slapos.slap.ComputerPartition)
      # as request method does not raise, accessing data raises
      self.assertRaises(slapos.slap.ResourceNotReady,
                        requested_partition.getId)
737 738 739 740 741

  def test_request_fullfilled_work(self):
    partition_id = 'PARTITION_01'
    requested_partition_id = 'PARTITION_02'
    computer_guid = self._getTestComputerId()
742

743
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
744
      qs = parse.parse_qs(url.query)
745 746 747
      if (url.path == '/registerComputerPartition' and
              'computer_reference' in qs and
              'computer_partition_reference' in qs):
748
        slap_partition = slapos.slap.ComputerPartition(
749 750 751 752
            qs['computer_reference'][0],
            qs['computer_partition_reference'][0])
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
753
                'content': dumps(slap_partition)
754 755 756
                }
      elif (url.path == '/getComputerInformation' and 'computer_id' in qs):
        slap_computer = slapos.slap.Computer(qs['computer_id'][0])
757 758
        slap_computer._software_release_list = []
        slap_partition = slapos.slap.ComputerPartition(
759
            qs['computer_id'][0],
760
            partition_id)
761
        slap_computer._computer_partition_list = [slap_partition]
762 763
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
764
                'content': dumps(slap_computer)
765 766
                }
      elif url.path == '/requestComputerPartition':
767 768
        from slapos.slap.slap import SoftwareInstance
        slap_partition = SoftwareInstance(
769 770
            slap_computer_id=computer_guid,
            slap_computer_partition_id=requested_partition_id)
771 772
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
773
                'content': dumps(slap_partition)
774
                }
775
      else:
776 777
        return {'status_code': 404}

778

779 780
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
781 782 783 784 785 786 787 788 789 790 791 792

    with httmock.HTTMock(handler):
      computer_partition = self.slap.registerComputerPartition(
          computer_guid, partition_id)
      requested_partition = computer_partition.request(
          'http://server/new/' + self._getTestComputerId(),
          'software_type',
          'myref')
      self.assertIsInstance(requested_partition, slapos.slap.ComputerPartition)
      # as request method does not raise, accessing data in case when
      # request was done works correctly
      self.assertEqual(requested_partition_id, requested_partition.getId())
793

794 795 796 797 798 799 800 801 802 803 804
  def test_request_with_slapgrid_request_transaction(self):
    from slapos.slap.slap import COMPUTER_PARTITION_REQUEST_LIST_TEMPLATE_FILENAME
    partition_id = 'PARTITION_01'
    instance_root = tempfile.mkdtemp()
    partition_root = os.path.join(instance_root, partition_id)
    os.mkdir(partition_root)
    os.environ['SLAPGRID_INSTANCE_ROOT'] = instance_root
    transaction_file_name = COMPUTER_PARTITION_REQUEST_LIST_TEMPLATE_FILENAME % partition_id
    transaction_file_path = os.path.join(partition_root, transaction_file_name)

    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
805
      qs = parse.parse_qs(url.query)
806 807 808 809 810 811 812 813
      if (url.path == '/registerComputerPartition'
              and 'computer_reference' in qs
              and 'computer_partition_reference' in qs):
        slap_partition = slapos.slap.ComputerPartition(
            qs['computer_reference'][0],
            qs['computer_partition_reference'][0])
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
814
                'content': dumps(slap_partition)
815 816 817 818 819 820 821 822 823 824 825
                }
      elif (url.path == '/getComputerInformation'
              and 'computer_id' in qs):
        slap_computer = slapos.slap.Computer(qs['computer_id'][0])
        slap_computer._software_release_list = []
        slap_partition = slapos.slap.ComputerPartition(
            qs['computer_id'][0],
            partition_id)
        slap_computer._computer_partition_list = [slap_partition]
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
826
                'content': dumps(slap_computer)
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
                }
      elif url.path == '/requestComputerPartition':
        raise RequestWasCalled
      else:
        return {
                'status_code': 404
                }

    with httmock.HTTMock(handler):
      self.computer_guid = self._getTestComputerId()
      self.slap = slapos.slap.slap()
      self.slap.initializeConnection(self.server_url)
      computer_partition = self.slap.registerComputerPartition(
          self.computer_guid, partition_id)

      self.assertTrue(os.path.exists(transaction_file_path))
      with open(transaction_file_path, 'r') as f:
        content = f.read()
        self.assertEqual(content, '')
      self.assertRaises(RequestWasCalled,
                        computer_partition.request,
                        'http://server/new/' + self._getTestComputerId(),
                        'software_type', 'myref')
      self.assertTrue(os.path.exists(transaction_file_path))
      with open(transaction_file_path, 'r') as f:
Bryton Lacquement's avatar
Bryton Lacquement committed
852
        content_list = f.read().splitlines()
853 854 855 856 857 858 859
        self.assertEqual(content_list, ['myref'])

      # Not override
      computer_partition = self.slap.registerComputerPartition(
          self.computer_guid, partition_id)
      self.assertTrue(os.path.exists(transaction_file_path))
      with open(transaction_file_path, 'r') as f:
Bryton Lacquement's avatar
Bryton Lacquement committed
860
        content_list = f.read().splitlines()
861 862 863 864 865 866 867 868
        self.assertEqual(content_list, ['myref'])

      # Request a second instance
      self.assertRaises(RequestWasCalled,
                        computer_partition.request,
                        'http://server/new/' + self._getTestComputerId(),
                        'software_type', 'mysecondref')
      with open(transaction_file_path, 'r') as f:
Bryton Lacquement's avatar
Bryton Lacquement committed
869 870
        content_list = f.read().splitlines()
        self.assertEqual(sorted(content_list), ['myref', 'mysecondref'])
871

872 873
  def _test_new_computer_partition_state(self, state):
    """
874
    Helper method to automate assertions of failing states on new Computer
875 876
    Partition
    """
877
    computer_guid = self._getTestComputerId()
878
    partition_id = 'PARTITION_01'
879 880 881
    slap = self.slap
    slap.initializeConnection(self.server_url)

882
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
883
      qs = parse.parse_qs(url.query)
884 885 886
      if (url.path == '/registerComputerPartition' and
              qs['computer_reference'][0] == computer_guid and
              qs['computer_partition_reference'][0] == partition_id):
887 888
        partition = slapos.slap.ComputerPartition(
            computer_guid, partition_id)
889 890
        return {
                'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
891
                'content': dumps(partition)
892
                }
893
      else:
894 895
        return {'status_code': 404}

896

897 898 899 900 901
    with httmock.HTTMock(handler):
      computer_partition = self.slap.registerComputerPartition(
          computer_guid, partition_id)
      self.assertRaises(slapos.slap.NotFoundError,
                        getattr(computer_partition, state))
902 903 904

  def test_started_new_ComputerPartition_raises(self):
    """
905
    Asserts that calling ComputerPartition.started on new partition raises
906 907 908 909 910 911
    (not defined yet) exception
    """
    self._test_new_computer_partition_state('started')

  def test_stopped_new_ComputerPartition_raises(self):
    """
912
    Asserts that calling ComputerPartition.stopped on new partition raises
913 914 915 916 917 918 919 920
    (not defined yet) exception
    """
    self._test_new_computer_partition_state('stopped')

  def test_error_new_ComputerPartition_works(self):
    """
    Asserts that calling ComputerPartition.error on new partition works
    """
921
    computer_guid = self._getTestComputerId()
922
    partition_id = 'PARTITION_01'
923 924 925
    slap = self.slap
    slap.initializeConnection(self.server_url)

926
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
927
      qs = parse.parse_qs(url.query)
928 929 930
      if (url.path == '/registerComputerPartition' and
              qs['computer_reference'][0] == computer_guid and
              qs['computer_partition_reference'][0] == partition_id):
931 932
        partition = slapos.slap.ComputerPartition(
            computer_guid, partition_id)
933 934
        return {
                'statu_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
935
                'content': dumps(partition)
936 937
                }
      elif url.path == '/softwareInstanceError':
Bryton Lacquement's avatar
Bryton Lacquement committed
938
        parsed_qs_body = parse.parse_qs(req.body)
939 940 941
        # XXX: why do we have computer_id and not computer_reference?
        # XXX: why do we have computer_partition_id and not
        # computer_partition_reference?
942 943 944
        if (parsed_qs_body['computer_id'][0] == computer_guid and
                parsed_qs_body['computer_partition_id'][0] == partition_id and
                parsed_qs_body['error_log'][0] == 'some error'):
945
          return {'status_code': 200}
946

947
      return {'status_code': 404}
948

949 950 951 952 953 954

    with httmock.HTTMock(handler):
      computer_partition = slap.registerComputerPartition(
          computer_guid, partition_id)
      # XXX: Interface does not define return value
      computer_partition.error('some error')
955

956

957 958 959 960 961 962 963
class TestSoftwareRelease(SlapMixin):
  """
  Tests slap.SoftwareRelease class functionality
  """

  def _test_new_software_release_state(self, state):
    """
964
    Helper method to automate assertions of failing states on new Software
965 966 967 968 969 970 971 972
    Release
    """
    self.software_release_uri = 'http://server/' + self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
    software_release = self.slap.registerSoftwareRelease(
        self.software_release_uri)
    method = getattr(software_release, state)
973
    self.assertRaises(NameError, method)
974 975 976

  def test_available_new_SoftwareRelease_raises(self):
    """
977
    Asserts that calling SoftwareRelease.available on new software release
978
    raises NameError exception
979 980 981 982 983
    """
    self._test_new_software_release_state('available')

  def test_building_new_SoftwareRelease_raises(self):
    """
984
    Asserts that calling SoftwareRelease.building on new software release
985
    raises NameError exception
986 987 988 989 990
    """
    self._test_new_software_release_state('building')

  def test_error_new_SoftwareRelease_works(self):
    """
991
    Asserts that calling SoftwareRelease.error on software release works
992
    """
993 994 995 996 997
    computer_guid = self._getTestComputerId()
    software_release_uri = 'http://server/' + self._getTestComputerId()
    slap = self.slap
    slap.initializeConnection(self.server_url)

998
    def handler(url, req):
Bryton Lacquement's avatar
Bryton Lacquement committed
999
      qs = parse.parse_qs(req.body)
1000 1001 1002 1003 1004 1005 1006 1007
      if (url.path == '/softwareReleaseError' and
              qs['computer_id'][0] == computer_guid and
              qs['url'][0] == software_release_uri and
              qs['error_log'][0] == 'some error'):
        return {
                'status_code': 200
                }
      return {'status_code': 404}
1008

1009

1010 1011 1012 1013
    with httmock.HTTMock(handler):
      software_release = self.slap.registerSoftwareRelease(software_release_uri)
      software_release._computer_guid = computer_guid
      software_release.error('some error')
1014

1015

1016 1017 1018 1019 1020 1021 1022
class TestOpenOrder(SlapMixin):
  def test_request_sends_request(self):
    software_release_uri = 'http://server/new/' + self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
    # XXX: Interface lack registerOpenOrder method declaration
    open_order = self.slap.registerOpenOrder()
1023

1024 1025
    def handler(url, req):
      if url.path == '/requestComputerPartition':
1026
        raise RequestWasCalled
1027

1028 1029 1030 1031
    with httmock.HTTMock(handler):
      self.assertRaises(RequestWasCalled,
                        open_order.request,
                        software_release_uri, 'myrefe')
1032

1033
  @unittest.skip('unclear what should be returned')
1034 1035 1036 1037 1038
  def test_request_not_raises(self):
    software_release_uri = 'http://server/new/' + self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
    # XXX: Interface lack registerOpenOrder method declaration
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048

    def handler(url, req):
      if url.path == '/requestComputerPartition':
        pass
        # XXX what to do here?

    with httmock.HTTMock(handler):
      open_order = self.slap.registerOpenOrder()
      computer_partition = open_order.request(software_release_uri, 'myrefe')
      self.assertIsInstance(computer_partition, slapos.slap.ComputerPartition)
1049 1050 1051 1052 1053 1054 1055

  def test_request_raises_later(self):
    software_release_uri = 'http://server/new/' + self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
    # XXX: Interface lack registerOpenOrder method declaration
    open_order = self.slap.registerOpenOrder()
1056

1057 1058
    def handler(url, req):
      return {'status_code': 408}
1059

1060 1061 1062
    with httmock.HTTMock(handler):
      computer_partition = open_order.request(software_release_uri, 'myrefe')
      self.assertIsInstance(computer_partition, slapos.slap.ComputerPartition)
1063

1064 1065
      self.assertRaises(slapos.slap.ResourceNotReady,
                        computer_partition.getId)
1066 1067 1068 1069 1070 1071 1072 1073 1074

  def test_request_fullfilled_work(self):
    software_release_uri = 'http://server/new/' + self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
    # XXX: Interface lack registerOpenOrder method declaration
    open_order = self.slap.registerOpenOrder()
    computer_guid = self._getTestComputerId()
    requested_partition_id = 'PARTITION_01'
1075

1076
    def handler(url, req):
1077 1078
      from slapos.slap.slap import SoftwareInstance
      slap_partition = SoftwareInstance(
1079 1080
          slap_computer_id=computer_guid,
          slap_computer_partition_id=requested_partition_id)
1081 1082
      return {
              'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
1083
              'content': dumps(slap_partition)
1084
              }
1085

1086 1087 1088 1089
    with httmock.HTTMock(handler):
      computer_partition = open_order.request(software_release_uri, 'myrefe')
      self.assertIsInstance(computer_partition, slapos.slap.ComputerPartition)
      self.assertEqual(requested_partition_id, computer_partition.getId())
1090

1091

1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
  def test_request_getConnectionParameter(self):
    """ Backward compatibility API for slapproxy older them 1.0.1 """
    software_release_uri = 'http://server/new/' + self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
    # XXX: Interface lack registerOpenOrder method declaration
    open_order = self.slap.registerOpenOrder()
    computer_guid = self._getTestComputerId()
    requested_partition_id = 'PARTITION_01'

1102
    def handler(url, req):
1103 1104 1105 1106 1107
      from slapos.slap.slap import SoftwareInstance
      slap_partition = SoftwareInstance(
          _connection_dict = {"url": 'URL_CONNECTION_PARAMETER'},
          slap_computer_id=computer_guid,
          slap_computer_partition_id=requested_partition_id)
1108 1109
      return {
              'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
1110
              'content': dumps(slap_partition)
1111
              }
1112 1113


1114 1115 1116 1117
    with httmock.HTTMock(handler):
      computer_partition = open_order.request(software_release_uri, 'myrefe')
      self.assertIsInstance(computer_partition, slapos.slap.ComputerPartition)
      self.assertEqual(requested_partition_id, computer_partition.getId())
1118
      self.assertEqual("URL_CONNECTION_PARAMETER",
1119
                       computer_partition.getConnectionParameter('url'))
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131


  def test_request_connection_dict_backward_compatibility(self):
    """ Backward compatibility API for slapproxy older them 1.0.1 """
    software_release_uri = 'http://server/new/' + self._getTestComputerId()
    self.slap = slapos.slap.slap()
    self.slap.initializeConnection(self.server_url)
    # XXX: Interface lack registerOpenOrder method declaration
    open_order = self.slap.registerOpenOrder()
    computer_guid = self._getTestComputerId()
    requested_partition_id = 'PARTITION_01'

1132
    def handler(url, req):
1133 1134 1135 1136 1137 1138 1139 1140
      from slapos.slap.slap import SoftwareInstance
      slap_partition = SoftwareInstance(
          connection_xml="""<?xml version='1.0' encoding='utf-8'?>
<instance>
  <parameter id="url">URL_CONNECTION_PARAMETER</parameter>
</instance>""",
          slap_computer_id=computer_guid,
          slap_computer_partition_id=requested_partition_id)
1141 1142
      return {
              'status_code': 200,
Bryton Lacquement's avatar
Bryton Lacquement committed
1143
              'content': dumps(slap_partition)
1144 1145 1146 1147 1148 1149
              }

    with httmock.HTTMock(handler):
      computer_partition = open_order.request(software_release_uri, 'myrefe')
      self.assertIsInstance(computer_partition, slapos.slap.ComputerPartition)
      self.assertEqual(requested_partition_id, computer_partition.getId())
1150
      self.assertEqual("URL_CONNECTION_PARAMETER",
1151
                       computer_partition.getConnectionParameter('url'))
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195


class TestSoftwareProductCollection(SlapMixin):
  def setUp(self):
    SlapMixin.setUp(self)
    self.real_getSoftwareReleaseListFromSoftwareProduct =\
        slapos.slap.slap.getSoftwareReleaseListFromSoftwareProduct

    def fake_getSoftwareReleaseListFromSoftwareProduct(inside_self, software_product_reference):
      return self.getSoftwareReleaseListFromSoftwareProduct_response
    slapos.slap.slap.getSoftwareReleaseListFromSoftwareProduct =\
        fake_getSoftwareReleaseListFromSoftwareProduct

    self.product_collection = slapos.slap.SoftwareProductCollection(
        logging.getLogger(), slapos.slap.slap())

  def tearDown(self):
    slapos.slap.slap.getSoftwareReleaseListFromSoftwareProduct =\
        self.real_getSoftwareReleaseListFromSoftwareProduct

  def test_get_product(self):
    """
    Test that the get method (aliased to __getattr__) returns the first element
    of the list given by getSoftwareReleaseListFromSoftwareProduct (i.e the
    best one).
    """
    self.getSoftwareReleaseListFromSoftwareProduct_response = ['0', '1', '2']
    self.assertEqual(
      self.product_collection.get('random_reference'),
      self.getSoftwareReleaseListFromSoftwareProduct_response[0]
    )

  def test_get_product_empty_product(self):
    """
    Test that the get method (aliased to __getattr__) raises if no
    Software Release is related to the Software Product, or if the
    Software Product does not exist.
    """
    self.getSoftwareReleaseListFromSoftwareProduct_response = []
    self.assertRaises(
      AttributeError,
      self.product_collection.get, 'random_reference',
    )

1196
  def test_get_product_getattr(self):
1197 1198 1199
    """
    Test that __getattr__ method is bound to get() method.
    """
1200 1201
    self.getSoftwareReleaseListFromSoftwareProduct_response = ['0']
    self.product_collection.foo
1202 1203 1204 1205
    self.assertEqual(
      self.product_collection.__getattr__,
      self.product_collection.get
    )
1206
    self.assertEqual(self.product_collection.foo, '0')
1207

1208
if __name__ == '__main__':
Bryton Lacquement's avatar
Bryton Lacquement committed
1209 1210
  print('You can point to any SLAP server by setting TEST_SLAP_SERVER_URL'
        ' environment variable')
1211
  unittest.main()
1212