def test_custom_error_retryable(): """ Custom errors status codes are handled as expected. """ graph = create_object_graph(name="example", testing=True) @graph.app.route("/conflict") @graph.audit def conflict(): raise MyConflictError("Conflict") client = graph.app.test_client() response = client.get("/conflict") assert_that(response.status_code, is_(equal_to(409))) data = response.json assert_that(data, is_(equal_to({ "code": 409, "message": "Conflict", "retryable": True, "context": { "errors": [{ "message": "Banana!", }] }, })))
def produce(): """ Produce test messages. """ parser = ArgumentParser() parser.add_argument("--count", default=1, type=int) parser.add_argument("--message") parser.add_argument("--message-type", default="test") parser.add_argument("--topic-arn", required=True) args = parser.parse_args() def load_config(metadata): return dict( pubsub_message_codecs=dict( default=SimpleSchema, ), sns_topic_arns=dict( default=args.topic_arn, ), ) graph = create_object_graph("example", loader=load_config) for _ in range(args.count): message_id = graph.sns_producer.produce( args.message_type, message=args.message or uuid4().hex, timestamp=time(), ) print message_id # noqa
def test_configure_sessionmaker(): """ Should create the `SQLAlchemy` sessionmaker """ graph = create_object_graph(name="example", testing=True) assert_that(graph.sessionmaker, is_(instance_of(sessionmaker)))
def test_error_wrap(): """ Wrapped errors work properly. """ graph = create_object_graph(name="example", testing=True) def fail(): raise Exception("fail") @graph.app.route("/wrap") @graph.audit def wrap(): try: fail() except Exception as error: raise Exception(error) client = graph.app.test_client() response = client.get("/wrap") assert_that(response.status_code, is_(equal_to(500))) data = response.json assert_that(data, is_(equal_to({ "code": 500, "message": "fail", "retryable": False, "context": {"errors": []} })))
def test_configure_flywheel_engine(): """ Should create the `flywheel` engine """ graph = create_object_graph(name="example", testing=True, import_name="microcosm_dynamodb") assert_that(graph.dynamodb, is_(instance_of(Engine)))
def test_override_default_limit_from_request_header(): graph = create_object_graph(name="example", testing=True) with graph.flask.test_request_context(headers={"X-Request-Limit": "2"}): page = OffsetLimitPage.from_dict(dict(foo="bar")) assert_that(page.offset, is_(equal_to(0))) assert_that(page.limit, is_(equal_to(2))) assert_that(page.kwargs, has_entry("foo", "bar"))
def test_werkzeug_http_error(): """ Explicit HTTP errors are reported as expected. """ graph = create_object_graph(name="example", testing=True) @graph.app.route("/not_found") @graph.audit def not_found(): raise NotFound client = graph.app.test_client() response = client.get("/not_found") assert_that(response.status_code, is_(equal_to(404))) data = response.json assert_that(data, is_(equal_to({ "code": 404, "context": { "errors": [], }, "message": "The requested URL was not found on the server. " "If you entered the URL manually please check your spelling and try again.", "retryable": False, })))
def test_configure_flask(): """ Should create the `Flask` application. """ graph = create_object_graph(name="example", testing=True) assert_that(graph.app, is_(instance_of(Flask)))
def test_configure_elasticsearch_client_with_defaults(): """ Default configuration works and returns client. """ graph = create_object_graph(name="test", testing=True) assert_that(graph.elasticsearch_client, is_(instance_of(Elasticsearch)))
def test_health_check_custom_check(): """ Should return Custom health check results. """ loader = load_from_dict( health_convention=dict( include_build_info="false", ), ) graph = create_object_graph(name="example", testing=True, loader=loader) graph.use("health_convention") client = graph.flask.test_client() graph.health_convention.checks["foo"] = lambda graph: "hi" response = client.get("/api/health") assert_that(response.status_code, is_(equal_to(200))) data = loads(response.get_data().decode("utf-8")) assert_that(data, is_(equal_to({ "name": "example", "ok": True, "checks": { "foo": { "message": "hi", "ok": True, }, }, })))
def test_health_check_custom_check_failed(): """ Should return 503 on health check failure. """ loader = load_from_dict( health_convention=dict( include_build_info="false", ), ) graph = create_object_graph(name="example", testing=True, loader=loader) graph.use("health_convention") client = graph.flask.test_client() def fail(graph): raise Exception("failure!") graph.health_convention.checks["foo"] = fail response = client.get("/api/health") assert_that(response.status_code, is_(equal_to(503))) data = loads(response.get_data().decode("utf-8")) assert_that(data, is_(equal_to({ "name": "example", "ok": False, "checks": { "foo": { "message": "failure!", "ok": False, }, }, })))
def test_produce_custom_topic(): """ Producer delegates to SNS client. """ def loader(metadata): return dict( pubsub_message_codecs=dict( default=FooSchema, ), sns_topic_arns=dict( default=None, mappings={ FOO_MEDIA_TYPE: FOO_TOPIC, }, ) ) graph = create_object_graph("example", testing=True, loader=loader) # set up response graph.sns_producer.sns_client.publish.return_value = dict(MessageId=MESSAGE_ID) message_id = graph.sns_producer.produce(FOO_MEDIA_TYPE, bar="baz") assert_that(graph.sns_producer.sns_client.publish.call_count, is_(equal_to(1))) assert_that(graph.sns_producer.sns_client.publish.call_args[1]["TopicArn"], is_(equal_to(FOO_TOPIC))) assert_that(loads(graph.sns_producer.sns_client.publish.call_args[1]["Message"]), is_(equal_to({ "bar": "baz", "mediaType": "application/vnd.globality.pubsub.foo", }))) assert_that(message_id, is_(equal_to(MESSAGE_ID)))
def test_codec_sqs_envelope(): graph = create_object_graph("example", testing=True) consumer = None message_id = "message_id" receipt_handle = "receipt_handle" envelope = CodecSQSEnvelope(graph) media_type = created("foo") uri = "http://foo/id" sqs_message = envelope.parse_raw_message(consumer, dict( MessageId=message_id, ReceiptHandle=receipt_handle, Body=dumps(dict( Message=dumps(dict( mediaType=media_type, foo="bar", uri=uri, )), )), )) assert_that(sqs_message.content, is_(equal_to(dict( # NB: no foo key here because it's not part of the schema media_type=media_type, uri=uri, )))) assert_that(sqs_message.media_type, is_(equal_to(media_type))) assert_that(sqs_message.message_id, is_(equal_to(message_id))) assert_that(sqs_message.receipt_handle, is_(equal_to(receipt_handle)))
def test_deferred_production_decorator(): """ Deferred production can be used to decorate a function """ def loader(metadata): return dict( sns_topic_arns=dict( default="topic", ) ) class Foo: def __init__(self, graph): self.graph = graph self.sns_producer = graph.sns_producer def bar(self): assert isinstance(self.sns_producer, DeferredProducer) self.sns_producer.produce(DerivedSchema.MEDIA_TYPE, data="data") assert_that(graph.sns_producer.sns_client.publish.call_count, is_(equal_to(0))) graph = create_object_graph("example", testing=True, loader=loader) foo = Foo(graph) func = deferred(foo)(foo.bar) func() assert_that(graph.sns_producer.sns_client.publish.call_count, is_(equal_to(1)))
def test_publish_batch_with_no_topic_fails(): """ Require explicit configuration of a topic for batch messages. """ def loader(metadata): return dict( sns_topic_arns=dict( default="topic", ) ) graph = create_object_graph("example", testing=True, loader=loader) graph.use("opaque") # set up response graph.sns_producer.sns_client.publish.return_value = dict(MessageId=MESSAGE_ID) assert_that( calling(graph.sns_producer.produce).with_args( MessageBatchSchema.MEDIA_TYPE, messages=[] ), raises(TopicNotDefinedError) )
def test_configure_logging_with_custom_library_levels(): """ Logging levels can be configured. """ def loader(metadata): return dict( logging=dict( level=INFO, levels=dict( default=dict( debug=["foo", "bar"], ), override=dict( warn=["foo"], ) ) ) ) graph = create_object_graph(name="test", testing=True, loader=loader) graph.use("logger") assert_that(getLogger("foo").getEffectiveLevel(), is_(equal_to(WARN))) assert_that(getLogger("bar").getEffectiveLevel(), is_(equal_to(DEBUG))) getLogger("bar").info("Bar should be visible at info") getLogger("foo").info("Foo should not be visible at info") getLogger("foo").warn("Foo should be visible at warn")
def test_produce_custom_topic(): """ Producer delegates to SNS client. """ def loader(metadata): return dict( sns_topic_arns=dict( default=None, mappings={ DerivedSchema.MEDIA_TYPE: "special-topic", }, ) ) graph = create_object_graph("example", testing=True, loader=loader) graph.use("opaque") # set up response graph.sns_producer.sns_client.publish.return_value = dict(MessageId=MESSAGE_ID) message_id = graph.sns_producer.produce(DerivedSchema.MEDIA_TYPE, data="data") assert_that(graph.sns_producer.sns_client.publish.call_count, is_(equal_to(1))) assert_that(graph.sns_producer.sns_client.publish.call_args[1]["TopicArn"], is_(equal_to("special-topic"))) assert_that(loads(graph.sns_producer.sns_client.publish.call_args[1]["Message"]), is_(equal_to({ "data": "data", "mediaType": DerivedSchema.MEDIA_TYPE, "opaqueData": {}, }))) assert_that(message_id, is_(equal_to(MESSAGE_ID)))
def test_configure_engine(): """ Engine factory should work with zero configuration. """ graph = create_object_graph(name="example", testing=True) engine = graph.postgres assert_that(engine, is_(instance_of(Engine))) # engine has expected configuration assert_that( str(engine.url), starts_with("postgresql://example:@"), ) assert_that( str(engine.url), ends_with(":5432/example_test_db"), ) # engine supports connections with engine.connect() as connection: row = connection.execute("SELECT 1;").fetchone() assert_that(row[0], is_(equal_to(1)))
def test_discovery(): graph = create_object_graph(name="example", testing=True) graph.use("discovery_convention") ns = Namespace("foo") @graph.route(ns.collection_path, Operation.Search, ns) def search_foo(): pass client = graph.flask.test_client() response = client.get("/api") assert_that(response.status_code, is_(equal_to(200))) data = loads(response.get_data().decode("utf-8")) assert_that(data, is_(equal_to({ "_links": { "search": [{ "href": "http://localhost/api/foo?offset=0&limit=20", "type": "foo", }], "self": { "href": "http://localhost/api?offset=0&limit=20", }, } })))
def test_basic_auth_custom_credentials(): """ Basic auth default credentials work. """ config = dict( basic_auth=dict( credentials=dict( username="******", ) ) ) graph = create_object_graph(name="example", testing=True, loader=lambda metadata: config) @graph.app.route("/ok") @graph.audit @graph.basic_auth.required def unauthorized(): return "OK" client = graph.app.test_client() response = client.get("/ok", headers={ "Authorization": encode_basic_auth("username", "password"), }) assert_that(response.status_code, is_(equal_to(200)))
def setup(self): self.graph = create_object_graph("test") self.graph.use( "pubsub_message_schema_registry", "pubsub_lifecycle_change", ) self.graph.lock()
def test_ack(): """ Consumer delegates to SQS client. """ def loader(metadata): return dict( sqs_consumer=dict( sqs_queue_url=FOO_QUEUE_URL, ), pubsub_message_codecs=dict( default=FooSchema, ), ) graph = create_object_graph("example", testing=True, loader=loader) message = SQSMessage( consumer=graph.sqs_consumer, message_id=MESSAGE_ID, receipt_handle=RECEIPT_HANDLE, content=None, ) message.ack() graph.sqs_consumer.sqs_client.delete_message.assert_called_with( QueueUrl='foo-queue-url', ReceiptHandle=RECEIPT_HANDLE, )
def test_basic_auth_default_realm(): """ Basic auth uses the convention that the metadata's name is the realm. """ graph = create_object_graph(name="example", testing=True) @graph.app.route("/unauthorized") @graph.audit @graph.basic_auth.required def unauthorized(): raise Exception("Should not be raised!") client = graph.app.test_client() response = client.get("/unauthorized") assert_that(response.status_code, is_(equal_to(401))) data = loads(response.get_data().decode("utf-8")) assert_that(data, is_(equal_to({ "code": 401, "message": "The server could not verify that you are authorized to access the URL requested. " "You either supplied the wrong credentials (e.g. a bad password), or your browser " "doesn't understand how to supply the credentials required.", "retryable": False, "context": {"errors": []}, }))) assert_that(response.headers["WWW-Authenticate"], is_(equal_to('Basic realm="example"')))
def setup(self): self.graph = create_object_graph(name="example", testing=True, import_name="microcosm_postgres") self.company_store = self.graph.company_store self.context = SessionContext(self.graph) self.context.recreate_all() self.context.open()
def setup(self): loaders = load_each( load_from_dict( multi_tenant_key_registry=dict( context_keys=[ "private", ], key_ids=[ "key_id", ], ), ), load_from_environ, ) self.graph = create_object_graph( name="example", testing=True, import_name="microcosm_postgres", loader=loaders, ) self.encryptable_store = self.graph.encryptable_store self.encrypted_store = self.graph.encrypted_store self.json_encryptable_store = self.graph.json_encryptable_store self.json_encrypted_store = self.graph.json_encrypted_store self.nullable_encryptable_store = self.graph.nullable_encryptable_store self.nullable_encrypted_store = self.graph.nullable_encrypted_store self.encryptor = self.graph.multi_tenant_encryptor with SessionContext(self.graph) as context: context.recreate_all()
def setup(self): self.graph = create_object_graph( name="example", testing=True, import_name="microcosm_postgres", ) self.company_store = self.graph.company_store self.companies = [ Company( name="name1", type=CompanyType.private, ), Company( name="name2", type=CompanyType.private, ), Company( name="name3", type=CompanyType.private, ), ] with SessionContext(self.graph) as context: context.recreate_all()
def setup(self): self.graph = create_object_graph(name="example", testing=True) self.ns = Namespace(subject="file") self.relation_ns = Namespace(subject=Person, object_="file") self.controller = FileController() UPLOAD_MAPPINGS = { Operation.Upload: EndpointDefinition( func=self.controller.upload, request_schema=FileExtraSchema(), ), } UPLOAD_FOR_MAPPINGS = { Operation.UploadFor: EndpointDefinition( func=self.controller.upload_for_person, request_schema=FileExtraSchema(), response_schema=FileResponseSchema(), ), } configure_upload(self.graph, self.ns, UPLOAD_MAPPINGS) configure_upload(self.graph, self.relation_ns, UPLOAD_FOR_MAPPINGS) configure_swagger(self.graph) self.client = self.graph.flask.test_client()
def test_encode_missing_field(): """ An invalid message will raise errors. """ graph = create_object_graph("example", testing=True) codec = graph.pubsub_message_schema_registry.find(DerivedSchema.MEDIA_TYPE) assert_that(calling(codec.encode), raises(ValidationError))
def test_custom_schema(): """ A configured message type will use its schema. """ graph = create_object_graph("example", testing=True) codec = graph.pubsub_message_schema_registry.find(DerivedSchema.MEDIA_TYPE) assert_that(codec.schema, is_(instance_of(DerivedSchema)))
def test_name_for_testing(): graph = create_object_graph("example", testing=True) graph.lock() assert_that(IndexRegistry.name_for(graph), is_(equal_to("example_test"))) assert_that(IndexRegistry.name_for(graph, name="foo"), is_(equal_to("foo_test"))) assert_that(IndexRegistry.name_for(graph, version="v1"), is_(equal_to("example_v1_test"))) assert_that(IndexRegistry.name_for(graph, name="foo", version="v2"), is_(equal_to("foo_v2_test")))
def test_paginated_list_relation_to_dict(): graph = create_object_graph(name="example", testing=True) ns = Namespace(subject="foo", object_="bar") @graph.route(ns.relation_path, Operation.SearchFor, ns) def search_foo(): pass paginated_list = PaginatedList( ns, Page(2, 2), ["1", "2"], 10, operation=Operation.SearchFor, foo_id="FOO_ID", ) with graph.flask.test_request_context(): assert_that( paginated_list.to_dict(), is_( equal_to({ "count": 10, "items": [ "1", "2", ], "offset": 2, "limit": 2, "_links": { "self": { "href": "http://localhost/api/foo/FOO_ID/bar?offset=2&limit=2", }, "next": { "href": "http://localhost/api/foo/FOO_ID/bar?offset=4&limit=2", }, "prev": { "href": "http://localhost/api/foo/FOO_ID/bar?offset=0&limit=2", }, } })))
def test_basic_auth_default_credentials(): """ Basic auth default credentials work. """ graph = create_object_graph(name="example", testing=True) @graph.app.route("/ok") @graph.audit @graph.basic_auth.required def unauthorized(): return "OK" client = graph.app.test_client() response = client.get("/ok", headers={ "Authorization": encode_basic_auth("default", "secret"), }) assert_that(response.status_code, is_(equal_to(200)))
def test_qualified_operation_href_for(): """ Qualified operations add to the URI. """ graph = create_object_graph(name="example", testing=True) ns = Namespace(subject="foo", qualifier="bar", version="v1") @graph.route(ns.collection_path, Operation.Search, ns) def search_foo(): pass @graph.route(ns.instance_path, Operation.Retrieve, ns) def get_foo(foo_id): pass with graph.app.test_request_context(): url = ns.href_for(Operation.Retrieve, foo_id="baz") assert_that(url, is_(equal_to("http://localhost/api/v1/bar/foo/baz")))
def test_namespace_accepts_controller(): """ Namespaces may optionally contain a controller. """ graph = create_object_graph(name="example", testing=True) controller = Mock() ns = Namespace(subject="foo", controller=controller) @graph.route(ns.collection_path, Operation.Search, ns) def search_foo(): pass with graph.app.test_request_context(): url = ns.href_for(Operation.Search) assert_that(url, is_(equal_to("http://localhost/api/foo"))) url = ns.url_for(Operation.Search) assert_that(url, is_(equal_to("http://localhost/api/foo"))) assert_that(ns.controller, is_(equal_to(controller)))
def test_publish_batch_with_no_topic_fails(): """ Require explicit configuration of a topic for batch messages. """ def loader(metadata): return dict(sns_topic_arns=dict(default="topic", )) graph = create_object_graph("example", testing=True, loader=loader) graph.use("opaque") # set up response graph.sns_producer.sns_client.publish.return_value = dict( MessageId=MESSAGE_ID) assert_that( calling(graph.sns_producer.produce).with_args( MessageBatchSchema.MEDIA_TYPE, messages=[]), raises(TopicNotDefinedError))
def test_get_resource_empty_headers(self): graph = create_object_graph("microcosm") graph.use( "opaque", "sqs_message_context", ) graph.lock() uri = "http://localhost" message = dict(uri=uri, ) with patch("microcosm_pubsub.handlers.uri_handler.get") as mocked_get: handler = URIHandler(graph) handler.get_resource(message, uri) mocked_get.assert_called_with( uri, headers=dict(), )
def setup(self): try: import microcosm_metrics # noqa except ImportError: raise SkipTest self.graph = create_object_graph("example", testing=True) self.graph.use( "datadog_statsd", "flask", "route", ) self.client = self.graph.flask.test_client() self.ns = Namespace( enable_metrics=True, subject="foo", version="v1", )
def read(args): loader = load_from_dict(sqs_consumer=dict( profile_name=args.profile, region_name=args.region, sqs_queue_url=args.queue_url, ), ) graph = create_object_graph("pubsub", debug=args.debug, loader=loader) graph.use("sqs_consumer") graph.lock() for message in graph.sqs_consumer.consume(): print("Read SQS message: {} ({})".format( # noqa message.message_id, message.approximate_receive_count, )) if args.nack: message.nack(args.nack_timeout) else: message.ack()
def test_scoped_to(): """ Factory can be scoped to a specific value. """ loader = load_from_dict( bar=dict( adder=dict( first=3, ), ), ) graph = create_object_graph("example", testing=True, loader=loader) with graph.adder.scoped_to("bar"): assert_that(graph.adder(), is_(equal_to(5))) with graph.adder.scoped_to("baz"): assert_that(graph.adder(), is_(equal_to(3)))
def setup(self): self.graph = create_object_graph("example", testing=True) self.circle_store = self.graph.circle_store self.shape_store = self.graph.shape_store self.square_store = self.graph.square_store self.graph.elasticsearch_index_registry.createall(force=True) self.circle = Circle( id="circle", circumfrance=20, ) self.shape = Shape( id="shape", area=10, ) self.square = Square( id="square", perimeter=30, )
def test_custom_headers(): """ Custom headers are sent to the client """ graph = create_object_graph(name="example", testing=True) @graph.app.route("/foo") @graph.audit def foo(): raise AuthenticationError() client = graph.app.test_client() response = client.get("/foo") data = response.json assert_that(data, has_entry("message", AuthenticationError.description)) www_authenticate = response.headers.get('www-authenticate') assert_that(www_authenticate, equal_to('Basic realm=outer-zone'))
def test_health_check(): """ Default health check returns OK. """ loader = load_from_dict(health_convention=dict( include_build_info="false", ), ) graph = create_object_graph(name="example", testing=True, loader=loader) graph.use("health_convention") client = graph.flask.test_client() response = client.get("/api/health") assert_that(response.status_code, is_(equal_to(200))) data = loads(response.get_data().decode("utf-8")) assert_that(data, is_(equal_to({ "name": "example", "ok": True, })))
def test_collaboration(): """ All microcosm collaborators should have access to the same opaque context. """ # set up a parent collaborator that uses a child collaborator @binding("parent_collaborator") class Parent: def __init__(self, graph): self.child_collaborator = graph.child_collaborator def __call__(self): return self.child_collaborator() @binding("child_collaborator") class Child: def __init__(self, graph): self.opaque = graph.opaque def __call__(self): return self.opaque.as_dict() # create the object graph with both collaborators and opaque data graph = create_object_graph( "test", testing=True, loader=load_from_dict(opaque={THIS: VALUE})) graph.use( "child_collaborator", "opaque", "parent_collaborator", ) graph.lock() # we should be able to initialize the opaque data and observe it from the collaborators decorated_func = graph.opaque.initialize( example_func, OTHER, OTHER )(graph.parent_collaborator.__call__) assert_that(graph.opaque.as_dict(), is_(equal_to({THIS: VALUE}))) assert_that(decorated_func(), is_(equal_to(example_func(OTHER, OTHER)))) assert_that(graph.opaque.as_dict(), is_(equal_to({THIS: VALUE})))
def test_get_whitelisted_resource_with_cache_enabled_and_cache_hit(self): config = dict( resource_cache=dict( enabled=True, ), ) graph = create_object_graph("microcosm", testing=True, loader=load_from_dict(config)) graph.use( "opaque", "resource_cache", "sqs_message_context", ) graph.lock() uri = "https://service.env.globality.io/api/v2/project_event/0598355c-5b19-49bd-a755-146204220a5b" media_type = "application/vnd.globality.pubsub._.created.project_event.project_brief_submitted" message = dict( uri=uri, mediaType=media_type, ) json_data = dict(foo="bar", bar="baz") with patch("microcosm_pubsub.handlers.uri_handler.get") as mocked_get: mocked_get.return_value = MockResponse( status_code=200, json_data=json_data, ) handler = URIHandler(graph) with patch.object(handler.resource_cache, "get") as mocked_cache_get: mocked_cache_get.return_value = json_data with patch.object(handler.resource_cache, "set") as mocked_cache_set: handler.get_resource(message, uri) # Nb. cache get was attempted mocked_cache_get.assert_called_with( uri, ) # Nb. actual resource HTTP retrieve not called since cache was hit assert_that(mocked_get.called, is_(equal_to(False))) # Nb. cache set was not called due to cache hit assert_that(mocked_cache_set.called, is_(equal_to(False)))
def test_raw_sqs_envelope(): graph = create_object_graph("example", testing=True) consumer = None message_id = "message_id" receipt_handle = "receipt_handle" envelope = RawSQSEnvelope(graph) sqs_message = envelope.parse_raw_message( consumer, dict( MessageId=message_id, ReceiptHandle=receipt_handle, Body=dumps(dict(foo="bar", )), )) assert_that(sqs_message.content, is_(equal_to(dict(foo="bar")))) assert_that(sqs_message.media_type, is_(equal_to("application/json"))) assert_that(sqs_message.message_id, is_(equal_to(message_id))) assert_that(sqs_message.receipt_handle, is_(equal_to(receipt_handle)))
def test_configure_logging_with_invalid_token(): """ Enabling loggly. """ def loader(metadata): return dict( logging=dict( loggly=dict( token=environ.get("LOGGLY_TOKEN", "TOKEN"), environment="unittest", ) ) ) graph = create_object_graph(name="test", loader=loader) graph.use("logger") graph.logger.info("Info will appear in loggly if LOGGLY_TOKEN is set correctly.")
def test_publish_by_uri_convention(): """ Message publishing can use this convention. """ def loader(metadata): return dict(sns_topic_arns=dict(default="default", )) graph = create_object_graph("example", testing=True, loader=loader) published_time = str(time()) with patch("microcosm_pubsub.producer.time") as mocked_time: mocked_time.return_value = published_time graph.sns_producer.produce(created("foo"), uri="http://example.com", opaque_data=dict()) assert_that(graph.sns_producer.sns_client.publish.call_count, is_(equal_to(1))) assert_that(graph.sns_producer.sns_client.publish.call_args[1]["TopicArn"], is_(equal_to("default"))) assert_that( loads(graph.sns_producer.sns_client.publish.call_args[1]["Message"]), is_( equal_to({ "mediaType": "application/vnd.globality.pubsub._.created.foo", "uri": "http://example.com", "opaqueData": { "X-Request-Published": published_time, }, }))) assert_that( graph.sns_producer.sns_client.publish.call_args[1] ["MessageAttributes"], is_( equal_to({ "media_type": { "DataType": "String", "StringValue": "application/vnd.globality.pubsub._.created.foo" }, })))
def test_basic_auth(): """ Basic auth prevents resource access. """ config = { "BASIC_AUTH_REALM": "microcosm", } graph = create_object_graph(name="example", testing=True, loader=lambda metadata: config) @graph.app.route("/unauthorized") @graph.audit @graph.basic_auth.required def unauthorized(): raise Exception("Should not be raised!") client = graph.app.test_client() response = client.get("/unauthorized") assert_that(response.status_code, is_(equal_to(401))) data = loads(response.get_data().decode("utf-8")) assert_that( data, is_( equal_to({ "code": 401, "message": "The server could not verify that you are authorized to access the URL requested. " "You either supplied the wrong credentials (e.g. a bad password), or your browser " "doesn't understand how to supply the credentials required.", "retryable": False, "context": { "errors": [] }, }))) assert_that(response.headers["WWW-Authenticate"], is_(equal_to('Basic realm="microcosm"')))
def test_no_prefix_no_version_path(): loader = load_from_dict( dict( # We want our routes to come directly after the root / build_route_path=dict(prefix=""), )) graph = create_object_graph(name="example", testing=True, loader=loader) ns = Namespace( subject=Person, version="", ) configure_crud(graph, ns, PERSON_MAPPINGS) with graph.flask.test_request_context(): operations = list(iter_endpoints(graph, match_function)) swagger_schema = build_swagger(graph, ns, operations) # Test that in a no prefix, no version case we still get a leading slash in our paths assert_that("/person" in swagger_schema["paths"]) assert_that(swagger_schema["basePath"], equal_to("/"))
def setup(self): self.example_tmp_file = NamedTemporaryFile() loader = load_from_dict( sqlite=dict( paths=dict( # NB using a file instead of ':memory:' path # to preserve data after SQLAlchemy engine disposal. example=self.example_tmp_file.name, ), ), ) self.graph = create_object_graph( "example", testing=True, loader=loader, ) self.foo_store = FooStore() self.foo = Foo(id=1) Foo.recreate_all(self.graph) Bar.recreate_all(self.graph) Baz.recreate_all(self.graph) Foo2.recreate_all(self.graph)
def test_make_response(): graph = create_object_graph(name="example", testing=True) formatter = JSONFormatter() with graph.app.test_request_context(): response = formatter(dict(foo="bar")) assert_that(response.data, is_(equal_to(b'{"foo":"bar"}\n'))) assert_that(response.content_type, is_(equal_to("application/json"))) assert_that( response.headers, contains_inanyorder( ("Content-Type", "application/json"), ("Content-Length", "14"), ("ETag", etag_for( md5_hash='"2f8acf3fe5e5c2839a04b7677d9399b8"', spooky_hash='"af072b51e1eb2a8d7b2ab84dab972674"', )), ))
def test_nack_when_404(self): graph = create_object_graph("microcosm") graph.use( "opaque", "sqs_message_context", ) graph.lock() uri = "http://localhost" message = dict( uri=uri, ) with patch("microcosm_pubsub.handlers.uri_handler.get") as mocked_get: mocked_get.return_value = MockResponse(dict(), 404) handler = URIHandler(graph) assert_that( calling(handler.get_resource).with_args(message, uri), raises(Nack), )
def setup(self): self.graph = create_object_graph(name="example", testing=True, import_name="microcosm_postgres") self.company_store = self.graph.company_store self.employee_store = self.graph.employee_store with SessionContext(self.graph) as context: context.recreate_all() with transaction(): self.company = Company( name="name", type=CompanyType.private, ).create() self.employee = Employee( first="first", last="last", company_id=self.company.id, ).create()
def setup(self): # override configuration to use "query" operations for swagger def loader(metadata): return dict( swagger_convention=dict( # default behavior appends this list to defaults; use a tuple to override operations=["command"], version="v1", ), ) self.graph = create_object_graph(name="example", testing=True, loader=loader) self.graph.use("swagger_convention") self.ns = Namespace(subject="foo") make_command(self.graph, self.ns, CommandArgumentSchema(), CommandResultSchema()) self.client = self.graph.flask.test_client()
def test_configure_logging_with_custom_library_levels(): """ Logging levels can be configured. """ def loader(metadata): return dict( logging=dict(level=INFO, levels=dict(default=dict(debug=["foo", "bar"], ), override=dict(warn=["foo"], )))) graph = create_object_graph(name="test", testing=True, loader=loader) graph.use("logger") assert_that(getLogger("foo").getEffectiveLevel(), is_(equal_to(WARN))) assert_that(getLogger("bar").getEffectiveLevel(), is_(equal_to(DEBUG))) getLogger("bar").info("Bar should be visible at info") getLogger("foo").info("Foo should not be visible at info") getLogger("foo").warn("Foo should be visible at warn")
def setup(self): self.graph = create_object_graph( "microcosm_eventsource", root_path=join(dirname(__file__), pardir), testing=True, ) self.graph.use( "task_store", "task_event_store", "activity_store", "activity_event_store", ) self.store = self.graph.task_event_store self.context = SessionContext(self.graph) self.context.recreate_all() self.context.open() with transaction(): self.task = Task().create()
def test_offset_limit_page_to_paginated_list(): graph = create_object_graph(name="example", testing=True) ns = Namespace("foo") @graph.flask.route("/", methods=["GET"], endpoint="foo.search.v1") def search(): pass with graph.flask.test_request_context(): page = OffsetLimitPage( offset=10, limit=10, foo="bar", ) result = [], 0 paginated_list, headers = page.to_paginated_list( result, _ns=ns, _operation=Operation.Search) schema_cls = page.make_paginated_list_schema_class(ns, Schema()) data = schema_cls().dump(paginated_list).data assert_that( data, is_( equal_to( dict( offset=10, limit=10, count=0, items=[], _links=dict( self=dict( href= "http://localhost/?offset=10&limit=10&foo=bar", ), prev=dict( href= "http://localhost/?offset=0&limit=10&foo=bar", ), ), ))))
def test_produce_custom_topic(): """ Producer delegates to SNS client. """ def loader(metadata): return dict(sns_topic_arns=dict( default=None, mappings={ DerivedSchema.MEDIA_TYPE: "special-topic", }, )) graph = create_object_graph("example", testing=True, loader=loader) graph.use("opaque") # set up response graph.sns_producer.sns_client.publish.return_value = dict( MessageId=MESSAGE_ID) published_time = str(time()) with patch("microcosm_pubsub.producer.time") as mocked_time: mocked_time.return_value = published_time message_id = graph.sns_producer.produce(DerivedSchema.MEDIA_TYPE, data="data") assert_that(graph.sns_producer.sns_client.publish.call_count, is_(equal_to(1))) assert_that(graph.sns_producer.sns_client.publish.call_args[1]["TopicArn"], is_(equal_to("special-topic"))) assert_that( loads(graph.sns_producer.sns_client.publish.call_args[1]["Message"]), is_( equal_to({ "data": "data", "mediaType": DerivedSchema.MEDIA_TYPE, "opaqueData": { "X-Request-Published": published_time, }, }))) assert_that(message_id, is_(equal_to(MESSAGE_ID)))
def test_config_discovery(): """ Config-minus secrets is shareable. """ config = load_from_dict(config_convention=dict(enabled="true", ), ) secrets = load_from_dict(config_convention=dict(enabled="true", ), ) paritioned_loader = load_config_and_secrets(config, secrets) graph = create_object_graph(name="example", testing=True, loader=paritioned_loader) graph.use("config_convention") client = graph.flask.test_client() response = client.get("/api/config", ) assert_that(response.status_code, is_(equal_to(200))) data = loads(response.get_data().decode("utf-8")) assert_that(data, has_entries(config_convention=dict(enabled="true")))
def test_threading(): with NamedTemporaryFile() as tmp_file: loader = load_from_dict(sqlite=dict(paths=dict( example=tmp_file.name, ), ), ) graph = create_object_graph("example", testing=True, loader=loader) store = PersonStore() Person.recreate_all(graph) with SessionContext(graph, Example) as context: gw = store.create(Person(id=1, first="George", last="Washington"), ) tj = store.create(Person(id=2, first="Thomas", last="Jefferson"), ) context.commit() pool = ThreadPool(2) store.get_session = GetOrCreateSession(graph) people = pool.map(lambda index: store.search()[index], range(2)) assert_that(people, contains(gw, tj))