test_algorithms.py 7.05 KB
Newer Older
André Anjos's avatar
André Anjos committed
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 27 28 29 30 31
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :

###############################################################################
#                                                                             #
# Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/           #
# Contact: beat.support@idiap.ch                                              #
#                                                                             #
# This file is part of the beat.cmdline module of the BEAT platform.          #
#                                                                             #
# Commercial License Usage                                                    #
# Licensees holding valid commercial BEAT licenses may use this file in       #
# accordance with the terms contained in a written agreement between you      #
# and Idiap. For further information contact tto@idiap.ch                     #
#                                                                             #
# Alternatively, this file may be used under the terms of the GNU Affero      #
# Public License version 3 as published by the Free Software and appearing    #
# in the file LICENSE.AGPL included in the packaging of this file.            #
# The BEAT platform 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.                                        #
#                                                                             #
# You should have received a copy of the GNU Affero Public License along      #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/.           #
#                                                                             #
###############################################################################


# Basic tests for the command line beat program: algorithms

import nose.tools
32
import os
33 34
import click
from click.testing import CliRunner
35
import shutil
36
import json
André Anjos's avatar
André Anjos committed
37 38 39

from beat.core.test.utils import slow, cleanup, skipif
from beat.core.algorithm import Storage
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
from beat.cmdline.scripts import main_cli

from .. import common

from . import platform, disconnected, prefix, tmp_prefix, user, token, temp_cwd


def setup():
  """Create default dataformat for algorithm prototype loading"""

  from .test_dataformats import test_create as df_test_create
  from .test_dataformats import call as df_call
  obj = 'user/integers/1'

  nose.tools.eq_(df_call('create', obj, prefix=tmp_prefix), 0)
  nose.tools.eq_(df_call('push', obj, prefix=tmp_prefix), 0)
André Anjos's avatar
André Anjos committed
56 57 58 59 60 61 62


def call(*args, **kwargs):
  '''A central mechanism to call the main routine with the right parameters'''

  use_prefix = kwargs.get('prefix', prefix)
  use_platform = kwargs.get('platform', platform)
63
  use_cache = kwargs.get('cache', 'cache')
André Anjos's avatar
André Anjos committed
64

65 66 67 68 69 70
  runner = CliRunner()
  with runner.isolated_filesystem():
    result = runner.invoke(
        main_cli.main,
        ['--platform', use_platform, '--user', user, '--token', token,
         '--prefix', use_prefix, '--cache', use_cache, '--test-mode',
71 72
         'algorithms'] + list(args),
         catch_exceptions=False
73 74
    )
    return result.exit_code, result.output
André Anjos's avatar
André Anjos committed
75 76 77 78 79 80


@slow
@nose.tools.with_setup(teardown=cleanup)
@skipif(disconnected, "missing test platform (%s)" % platform)
def test_remote_list():
81 82
  exit_code, outputs = call('list', '--remote')
  nose.tools.eq_(exit_code, 0, msg=outputs)
André Anjos's avatar
André Anjos committed
83 84 85 86


@nose.tools.with_setup(teardown=cleanup)
def test_local_list():
87
  exit_code, outputs = call('list')
88
  nose.tools.eq_(exit_code, 0, outputs)
André Anjos's avatar
André Anjos committed
89 90 91 92 93 94


@slow
@nose.tools.with_setup(teardown=cleanup)
@skipif(disconnected, "missing test platform (%s)" % platform)
def test_pull_one():
95
  obj = 'user/integers_add/1'
96 97
  exit_code, outputs = call('pull', obj, prefix=tmp_prefix)
  nose.tools.eq_(exit_code, 0, outputs)
André Anjos's avatar
André Anjos committed
98 99 100 101 102 103 104 105
  s = Storage(tmp_prefix, obj)
  assert s.exists()


@slow
@nose.tools.with_setup(teardown=cleanup)
@skipif(disconnected, "missing test platform (%s)" % platform)
def test_pull_all():
106 107
  exit_code, outputs = call('pull', prefix=tmp_prefix)
  nose.tools.eq_(exit_code, 0, outputs)
André Anjos's avatar
André Anjos committed
108 109 110 111 112 113


@slow
@nose.tools.with_setup(teardown=cleanup)
@skipif(disconnected, "missing test platform (%s)" % platform)
def test_diff():
114
  obj = 'user/integers_add/1'
115 116
  exit_code, outputs = call('pull', obj, prefix=tmp_prefix)
  nose.tools.eq_(exit_code, 0, outputs)
André Anjos's avatar
André Anjos committed
117 118 119 120 121

  # quickly modify the user algorithm by emptying it
  storage = Storage(tmp_prefix, obj)
  storage.code.save('class Algorithm:\n  pass')

122 123
  exit_code, outputs = call('diff', obj, prefix=tmp_prefix)
  nose.tools.eq_(exit_code, 0, outputs)
André Anjos's avatar
André Anjos committed
124 125 126 127 128 129 130 131


@slow
@nose.tools.with_setup(teardown=cleanup)
@skipif(disconnected, "missing test platform (%s)" % platform)
def test_status():
  test_diff()
  test_pull_one()
132 133
  exit_code, outputs = call('status', prefix=tmp_prefix)
  nose.tools.eq_(exit_code, 0, outputs)
André Anjos's avatar
André Anjos committed
134 135 136


def test_check_valid():
137
  obj = 'legacy/valid_algorithm/1'
138 139
  exit_code, outputs = call('check', obj)
  nose.tools.eq_(exit_code, 0, outputs)
André Anjos's avatar
André Anjos committed
140 141 142


def test_check_invalid():
143
  obj = 'legacy/no_inputs_declarations/1'
144 145
  exit_code, outputs = call('check', obj)
  nose.tools.eq_(exit_code, 1, outputs)
André Anjos's avatar
André Anjos committed
146 147


148
@nose.tools.with_setup(setup=setup, teardown=cleanup)
André Anjos's avatar
André Anjos committed
149
def test_create(obj=None):
150
  obj = obj or 'legacy/algorithm/1'
151 152
  exit_code, outputs = call('create', obj, prefix=tmp_prefix)
  nose.tools.eq_(exit_code, 0, outputs)
André Anjos's avatar
André Anjos committed
153 154 155 156 157
  s = Storage(tmp_prefix, obj)
  assert s.exists()
  return s


158
@nose.tools.with_setup(setup=setup, teardown=cleanup)
André Anjos's avatar
André Anjos committed
159
def test_new_version():
160
  obj = 'legacy/algorithm/1'
André Anjos's avatar
André Anjos committed
161
  test_create(obj)
162
  obj2 = 'legacy/algorithm/2'
163 164
  exit_code, outputs = call('version', obj, prefix=tmp_prefix)
  nose.tools.eq_(exit_code, 0, outputs)
André Anjos's avatar
André Anjos committed
165 166 167 168
  s = Storage(tmp_prefix, obj2)
  assert s.exists()

  # check version status
169
  with common.Selector(tmp_prefix) as selector:
André Anjos's avatar
André Anjos committed
170 171 172
    assert selector.version_of('algorithm', obj2) == obj


173
@nose.tools.with_setup(setup=setup, teardown=cleanup)
André Anjos's avatar
André Anjos committed
174
def test_fork():
175
  obj = 'legacy/algorithm/1'
André Anjos's avatar
André Anjos committed
176
  test_create(obj)
177
  obj2 = 'legacy/different/1'
178 179
  exit_code, outputs = call('fork', obj, obj2, prefix=tmp_prefix)
  nose.tools.eq_(exit_code, 0, outputs)
André Anjos's avatar
André Anjos committed
180 181 182 183
  s = Storage(tmp_prefix, obj2)
  assert s.exists()

  # check fork status
184
  with common.Selector(tmp_prefix) as selector:
André Anjos's avatar
André Anjos committed
185 186 187
    assert selector.forked_from('algorithm', obj2) == obj


188
@nose.tools.with_setup(setup=setup, teardown=cleanup)
André Anjos's avatar
André Anjos committed
189
def test_delete_local():
190
  obj = 'legacy/algorithm/1'
André Anjos's avatar
André Anjos committed
191 192 193 194 195 196
  storage = test_create(obj)

  # quickly make sure it exists
  storage = Storage(tmp_prefix, obj)
  assert storage.exists()

197 198
  exit_code, outputs = call('rm', obj, prefix=tmp_prefix)
  nose.tools.eq_(exit_code, 0, outputs)
André Anjos's avatar
André Anjos committed
199 200 201
  assert not storage.exists()


202
@nose.tools.with_setup(setup=setup, teardown=cleanup)
André Anjos's avatar
André Anjos committed
203 204
@skipif(disconnected, "missing test platform (%s)" % platform)
def test_push_and_delete():
205
  obj = 'user/newobject/1'
André Anjos's avatar
André Anjos committed
206 207 208
  test_create(obj)

  # now push the new object and then delete it remotely
209 210 211 212
  exit_code, outputs = call('push', obj, prefix=tmp_prefix)
  nose.tools.eq_(exit_code, 0, outputs)
  exit_code, outputs = call('rm', '--remote', obj, prefix=tmp_prefix)
  nose.tools.eq_(exit_code, 0, outputs)