def test_double_start(start_stop_agent, mock_cloud_client): # pylint:disable=redefined-outer-name Service.start(Serializer.serialize(mock_cloud_client)) assert Service.is_running() with pytest.raises(RuntimeError) as excinfo: Service.start(Serializer.serialize(mock_cloud_client)) assert "Running already" in str(excinfo.value)
def test_start_submit(pre_post_tests): # pylint: disable=unused-argument,redefined-outer-name # Patch CloudClient as it connects to cloud at start-up with mock.patch(BUILD_CLOUD_CLIENT_PATCH_PATH) as mock_build_cloud_client: mock_cloud_client = PicklableMock() mock_build_cloud_client.return_value = mock_cloud_client # Mock notify service start, enough for start-up mock_cloud_client.notify_service_start.return_value = None mock_cloud_client.post_payload.return_value = None start_result = run_cli(args=['start']) assert start_result.exit_code == 0, "`start` should run smoothly" assert Service.is_running(), "Service should be running after `start`" submit_result = run_cli( args='echo Hello' ) # if it works without the `submit`, it will work with it assert submit_result.exit_code == 0, "`submit` is expected to succeed" stdout_pattern = r"Job\s(\d+)\ssubmitted\ssuccessfully\swith\sID\s([\w-]+)" match = re.match(stdout_pattern, submit_result.stdout) job_number = int(match.group(1)) assert job_number == 1, "Submitted job should have a HID of 1 (first job submitted)" job_uuid = match.group(2) assert uuid.UUID( job_uuid ), "Job UUID should be a valid UUID and match the regex pattern" assert Service.is_running(), "Service should still be running!" list_result = run_cli(args='list') # Better testing at some point. assert list_result.exit_code == 0, "`list` is expected to succeed" def verify_finished(out): out = out.split("\n") # Split per line line = [x for x in out if job_uuid in x] # Find the one relevant job_id assert len( line) == 1, "There should be only one line with the given job id" return "FINISHED" in line[0] list_result = run_cli(args='list') while not verify_finished(list_result.stdout): time.sleep(0.2) # Hacky way to give some time for finishing the task list_result = run_cli(args='list') # Check stdout and stderr exist assert meeshkan.config.JOBS_DIR.joinpath(job_uuid, 'stdout').is_file(), "stdout file is expected to exist after " \ "job is finished" assert meeshkan.config.JOBS_DIR.joinpath(job_uuid, 'stderr').is_file(), "stderr file is expected to exist after " \ "job is finished"
def test_start_stop(pre_post_tests): # pylint: disable=unused-argument,redefined-outer-name # Patch CloudClient as it connects to cloud at start-up # Lots of reverse-engineering happening here... with mock.patch(BUILD_CLOUD_CLIENT_PATCH_PATH) as mock_build_cloud_client: mock_cloud_client = PicklableMock() mock_build_cloud_client.return_value = mock_cloud_client mock_cloud_client.notify_service_start.return_value = None start_result = run_cli('start') assert start_result.exit_code == 0 assert Service.is_running( ), "Service should be running after using `meeshkan start`" stop_result = run_cli(args=['stop']) assert not Service.is_running( ), "Service should NOT be running after using `meeshkan stop`" assert start_result.exit_code == 0, "`meeshkan start` is expected to run without errors" assert stop_result.exit_code == 0, "`meeshkan stop` is expected to run without errors" assert mock_cloud_client.notify_service_start.call_count == 1, "`notify_service_start` is expected " \ "to be called only once."
def test_empty_list(pre_post_tests): # pylint: disable=unused-argument,redefined-outer-name with mock.patch(BUILD_CLOUD_CLIENT_PATCH_PATH) as mock_build_cloud_client: mock_cloud_client = PicklableMock() mock_build_cloud_client.return_value = mock_cloud_client # Mock notify service start, enough for start-up mock_cloud_client.notify_service_start.return_value = None mock_cloud_client.post_payload.return_value = None run_cli(args=['start']) list_result = run_cli(args=['list']) assert Service.is_running( ), "Service should be running after running `start`" assert list_result.exit_code == 0, "`list` is expected to succeed" assert list_result.stdout == "No jobs submitted yet.\n", "`list` output message should match"
def test_start_fail(pre_post_tests): # pylint: disable=unused-argument,redefined-outer-name def fail_notify_start(*args, **kwargs): # pylint: disable=unused-argument,redefined-outer-name raise RuntimeError("Mocking notify service start failure") with mock.patch(BUILD_CLOUD_CLIENT_PATCH_PATH) as mock_build_cloud_client: mock_cloud_client = PicklableMock() mock_build_cloud_client.return_value = mock_cloud_client mock_cloud_client.notify_service_start.side_effect = fail_notify_start start_result = run_cli('start') assert "Starting the Meeshkan agent failed" in start_result.stdout,\ "`meeshkan start` is expected to fail with error message" assert start_result.exit_code == 1, "`meeshkan start` exit code should be non-zero upon failure" assert not Service.is_running(), "Service should not be running!"
def test_double_start(pre_post_tests): # pylint: disable=unused-argument,redefined-outer-name with mock.patch(BUILD_CLOUD_CLIENT_PATCH_PATH) as mock_build_cloud_client: mock_cloud_client = PicklableMock() mock_build_cloud_client.return_value = mock_cloud_client mock_cloud_client.notify_service_start.return_value = None start_result = run_cli('start') assert Service.is_running( ), "Service should be running after using `meeshkan start`" double_start_result = run_cli('start') assert double_start_result.stdout == "Service is already running.\n", "Service should already be running" assert start_result.exit_code == 0, "`meeshkan start` should succeed by default" assert double_start_result.exit_code == 0, "Consecutive calls to `meeshkan start`are allowed" assert mock_cloud_client.notify_service_start.call_count == 1, "`notify_service_start` is expected " \ "to be called only once"
def test_start_with_401_fails(pre_post_tests): # pylint: disable=unused-argument,redefined-outer-name # Patch CloudClient as it connects to cloud at start-up with mock.patch(BUILD_CLOUD_CLIENT_PATCH_PATH) as mock_build_cloud_client: mock_cloud_client = PicklableMock() mock_build_cloud_client.return_value = mock_cloud_client # Raise Unauthorized exception when service start notified def side_effect(*args, **kwargs): # pylint: disable=unused-argument raise meeshkan.exceptions.UnauthorizedRequestException() mock_cloud_client.notify_service_start.side_effect = side_effect start_result = run_cli('--silent start') assert start_result.exit_code == 1, "`meeshkan start` is expected to fail with UnauthorizedRequestException and " \ "return a non-zero exit code" assert start_result.stdout == UnauthorizedRequestException().message + '\n', "stdout when running `meeshkan " \ "start` should match the error " \ "message in " \ "UnauthorizedRequestException" assert not Service.is_running( ), "Service should not be running after a failed `start`" assert mock_cloud_client.notify_service_start.call_count == 1, "`notify_service_start` should be " \ "called once (where it fails)"
def test_getting_api_before_start_raises_exception(): # pylint:disable=redefined-outer-name assert not Service.is_running() with pytest.raises(AgentNotAvailableException): Service.api()
def test_start_stop(start_stop_agent, mock_cloud_client): # pylint:disable=redefined-outer-name Service.start(Serializer.serialize(mock_cloud_client)) assert Service.is_running()
def start_stop_agent(): stop_if_running() assert not Service.is_running() yield stop_if_running() assert not Service.is_running()
def stop_if_running(): if Service.is_running(): with Service.api() as api: api.stop()