Пример #1
0
def test_two_ensembles_memory_usage(tmp_path, empty_ensemble):
    """
    :tmp_path: https://docs.pytest.org/en/stable/tmpdir.html
    """
    assert len(joshua_model.list_active_ensembles()) == 0
    ensemble_id = joshua_model.create_ensemble("joshua", {
        "max_runs": 1,
        "timeout": 1
    }, open(empty_ensemble, "rb"))
    agent = threading.Thread(
        target=joshua_agent.agent,
        args=(),
        kwargs={
            "work_dir": tmp_path,
            "agent_idle_timeout": 1,
        },
    )
    agent.setDaemon(True)
    agent.start()

    # Ensemble one should eventually end
    joshua.tail_ensemble(ensemble_id, username="******")

    # Start ensemble two
    ensemble_id = joshua_model.create_ensemble("joshua", {
        "max_runs": 1,
        "timeout": 1
    }, open(empty_ensemble, "rb"))

    # Ensemble two should eventually end
    joshua.tail_ensemble(ensemble_id, username="******")
    agent.join()
Пример #2
0
def test_dead_agent(tmp_path, empty_ensemble):
    """
    :tmp_path: https://docs.pytest.org/en/stable/tmpdir.html
    """
    assert len(joshua_model.list_active_ensembles()) == 0
    ensemble_id = joshua_model.create_ensemble("joshua", {
        "max_runs": 1,
        "timeout": 1
    }, open(empty_ensemble, "rb"))

    # simulate another agent dying after starting a test
    assert joshua_model.try_starting_test(ensemble_id, 12345)

    agent = threading.Thread(
        target=joshua_agent.agent,
        args=(),
        kwargs={
            "work_dir": tmp_path,
            "agent_idle_timeout": 1,
        },
    )
    agent.setDaemon(True)
    agent.start()

    # Ensemble should still eventually end
    joshua.tail_ensemble(ensemble_id, username="******")
    agent.join()
Пример #3
0
def upload():
    if request.method == 'POST' and not current_user.is_authenticated:
        return redirect(url_for('main.index'))

    form = UploadJobForm()
    if form.validate_on_submit():
        filename = secure_filename(form.file.data.filename)
        filepath = os.path.join(app.config['JOSHUA_UPLOAD_FOLDER'],
                                secure_filename(current_user.username))
        if not os.path.exists(filepath):
            os.mkdir(filepath, 0o755)
        saved_file = os.path.join(filepath, filename)
        form.file.data.save(saved_file)
        properties = form.get_properties()
        flash('Uploaded:  user: {}   package: {}'.format(
            current_user.username, filename))
        app.logger.info('Uploaded:  user: {}   package: {}'.format(
            current_user.username, filename))
        # convert to non-unicode string for username
        properties['username'] = str(current_user.username)
        # if not form.allow_multiple.data:
        #    joshua.stop_ensemble(username=current_user.username, sanity=form.sanity.data)

        with open(saved_file, "rb") as tarfile:
            tarfile.seek(0, os.SEEK_END)
            size = tarfile.tell()
            tarfile.seek(0, os.SEEK_SET)
            properties['data_size'] = size

        ensemble_id = joshua_model.create_ensemble(properties['username'],
                                                   properties, tarfile, False)
        app.logger.info('Ensemble {} created with properties: {}!'.format(
            ensemble_id, properties))
        flash('Ensemble {} created!'.format(ensemble_id))
    return render_template('upload.html', user=current_user, form=form)
Пример #4
0
def test_delete_ensemble(tmp_path, empty_ensemble_timeout):
    ensemble_id = joshua_model.create_ensemble(
        "joshua", {
            "max_runs": 10,
            "timeout": 1
        }, open(empty_ensemble_timeout, "rb"))
    agents = []
    for rank in range(10):
        agent = threading.Thread(
            target=joshua_agent.agent,
            args=(),
            kwargs={
                "work_dir": os.path.join(tmp_path, str(rank)),
                "agent_idle_timeout": 1,
            },
        )
        agent.setDaemon(True)
        agent.start()
        agents.append(agent)
    time.sleep(0.5)  # Give the agents some time to start
    joshua_model.delete_ensemble(ensemble_id)
    time.sleep(1)  # Wait for long enough that agents timeout
    assert len(joshua_model.list_all_ensembles()) == 0

    for agent in agents:
        agent.join()
Пример #5
0
def test_two_agents_large_ensemble(monkeypatch, tmp_path, empty_ensemble):
    """
    :monkeypatch: https://docs.pytest.org/en/stable/monkeypatch.html
    :tmp_path: https://docs.pytest.org/en/stable/tmpdir.html
    """

    # Make downloading an ensemble take an extra second, and increment
    # downloads_started at the beginning of downloading
    downloads_started = ThreadSafeCounter()

    def ensure_state_test_delay():
        downloads_started.increment()
        time.sleep(1)

    monkeypatch.setattr(joshua_agent, "ensure_state_test_delay",
                        ensure_state_test_delay)

    @fdb.transactional
    def get_started(tr):
        return joshua_model._get_snap_counter(tr, ensemble_id, "started")

    assert len(joshua_model.list_active_ensembles()) == 0
    ensemble_id = joshua_model.create_ensemble("joshua", {
        "max_runs": 1,
        "timeout": 1
    }, open(empty_ensemble, "rb"))

    agents = []
    for rank in range(2):
        agent = threading.Thread(
            target=joshua_agent.agent,
            args=(),
            kwargs={
                "work_dir": os.path.join(tmp_path, str(rank)),
                "agent_idle_timeout": 1,
            },
        )
        agent.setDaemon(True)
        agent.start()
        agents.append(agent)
        while True:
            # Wait until the first agent has begun downloading before starting the second agent
            if downloads_started.get() > 0:
                break
            time.sleep(0.01)

    joshua.tail_ensemble(ensemble_id, username="******")

    @fdb.transactional
    def get_started(tr):
        return joshua_model._get_snap_counter(tr, ensemble_id, "started")

    assert get_started(joshua_model.db) == 1

    for agent in agents:
        agent.join()
Пример #6
0
def upload_ensemble():
    request_data = request.form.to_dict()
    request_files = request.files.to_dict()
    if not request_data:
        app.logger.info('api_upload: No form data')
        return {"error": 'api_upload: No form data'}, 400
    if not request_files:
        app.logger.info('api_upload: Missing uploaded file')
        return {
            "message":
            'api_upload: Missing uploaded file  request: {}'.format(
                request_data)
        }, 400
    schema = UploadJobForm()
    try:
        properties = schema.load(request_data)
    except Exception as err:
        app.logger.info('api_upload: Validation error: {}'.format(err))
        return {
            "message":
            'api_upload: Post field validation error: {}'.format(err)
        }, 422
    fileobj = request_files['file']
    filename = secure_filename(fileobj.filename)
    filepath = os.path.join(app.config['JOSHUA_UPLOAD_FOLDER'],
                            secure_filename(properties['username']))
    if not os.path.exists(filepath):
        os.mkdir(filepath, 0o755)
    saved_file = os.path.join(filepath, filename)
    fileobj.save(saved_file)
    if not tarfile.is_tarfile(saved_file):
        os.remove(saved_file)
        app.logger.info(
            'api_upload: not a valid tar file: {}'.format(saved_file))
        return {"error": 'api_upload: not a valid tar file'}, 400

    # convert to non-unicode string for username
    properties['username'] = str(properties['username'])

    with open(saved_file, "rb") as file:
        file.seek(0, os.SEEK_END)
        size = file.tell()
        file.seek(0, os.SEEK_SET)
        properties['data_size'] = size
        ensemble_id = joshua_model.create_ensemble(properties['username'],
                                                   properties, file, False)
        app.logger.info('Ensemble {} created with properties: {}'.format(
            ensemble_id, properties))
    # Delete the file
    os.remove(saved_file)
    return jsonify(ensemble_id), 200
Пример #7
0
def test_two_agents(tmp_path, empty_ensemble):
    """
    :tmp_path: https://docs.pytest.org/en/stable/tmpdir.html
    """
    @fdb.transactional
    def get_started(tr):
        return joshua_model._get_snap_counter(tr, ensemble_id, "started")

    assert len(joshua_model.list_active_ensembles()) == 0
    ensemble_id = joshua_model.create_ensemble("joshua", {
        "max_runs": 1,
        "timeout": 1
    }, open(empty_ensemble, "rb"))

    agents = []
    for rank in range(2):
        agent = threading.Thread(
            target=joshua_agent.agent,
            args=(),
            kwargs={
                "work_dir": os.path.join(tmp_path, str(rank)),
                "agent_idle_timeout": 1,
            },
        )
        agent.setDaemon(True)
        agent.start()
        agents.append(agent)
        # before starting agent two, wait until agent one has started on this ensemble
        while get_started(joshua_model.db) != 1:
            time.sleep(0.001)

    joshua.tail_ensemble(ensemble_id, username="******")

    @fdb.transactional
    def get_started(tr):
        return joshua_model._get_snap_counter(tr, ensemble_id, "started")

    # The second agent won't have started this ensemble (unless somehow > 10
    # seconds passed without the first agent completing the ensemble)
    assert get_started(joshua_model.db) == 1

    for agent in agents:
        agent.join()
Пример #8
0
def test_ensemble_fails(tmp_path, empty_ensemble_fail):
    ensemble_id = joshua_model.create_ensemble(
        "joshua", {"max_runs": 1, "timeout": 1}, open(empty_ensemble_fail, "rb")
    )
    agent = threading.Thread(
        target=joshua_agent.agent,
        args=(),
        kwargs={
            "work_dir": tmp_path,
            "agent_idle_timeout": 1,
        },
    )
    agent.setDaemon(True)
    agent.start()
    joshua.tail_ensemble(ensemble_id, username="******")
    agent.join()

    assert get_passes(joshua_model.db, ensemble_id) == 0
    assert get_fails(joshua_model.db, ensemble_id) >= 1
Пример #9
0
def test_stop_ensemble(tmp_path, empty_ensemble):
    """
    :tmp_path: https://docs.pytest.org/en/stable/tmpdir.html
    """
    assert len(joshua_model.list_active_ensembles()) == 0
    ensemble_id = joshua_model.create_ensemble(
        "joshua", {"max_runs": 1e12}, open(empty_ensemble, "rb")
    )
    agent = threading.Thread(
        target=joshua_agent.agent,
        args=(),
        kwargs={
            "work_dir": tmp_path,
            "agent_idle_timeout": 1,
        },
    )
    agent.setDaemon(True)
    agent.start()
    while len(joshua_model.show_in_progress(ensemble_id)) == 0:
        time.sleep(0.001)
    joshua.stop_ensemble(ensemble_id, username="******")
    assert joshua_model.show_in_progress(ensemble_id) == []
    joshua.tail_ensemble(ensemble_id, username="******")
    agent.join()
Пример #10
0
def test_create_ensemble():
    assert len(joshua_model.list_active_ensembles()) == 0
    ensemble_id = joshua_model.create_ensemble("joshua", {}, io.BytesIO())
    assert len(joshua_model.list_active_ensembles()) > 0