def test_sync(client: Client, receiver_address, receiver_privkey): c = client.get_suitable_channel(receiver_address, 5, initial_deposit=lambda x: x) assert c is not None assert c in client.channels assert c.deposit == 5 assert len(client.channels) == 1 # Check if channel is still valid after sync. client.sync_channels() assert c in client.channels assert len(client.channels) == 1 # Check if client handles topup events on sync. c_topup = client.get_suitable_channel(receiver_address, 7, topup_deposit=lambda x: 2) assert c is not None assert c_topup == c assert len(client.channels) == 1 assert c.deposit == 7 # Check if channel can be resynced after data loss. client.channels = [] client.sync_channels() assert len(client.channels) == 1 c = client.channels[0] assert c.deposit == 7 # Check if channel is forgotten on resync after closure. close_channel_cooperatively(c, receiver_privkey, client.context.channel_manager.address) client.sync_channels() assert c not in client.channels
def test_sync(client: Client, receiver_address, receiver_privkey): c = client.get_suitable_channel(receiver_address, 5, initial_deposit=lambda x: x) assert c in client.channels assert c.deposit == 5 assert len(client.channels) == 1 # Check if channel is still valid after sync. client.sync_channels() assert c in client.channels assert len(client.channels) == 1 # Check if client handles topup events on sync. c_topup = client.get_suitable_channel(receiver_address, 7, topup_deposit=lambda x: 2) assert c_topup == c assert len(client.channels) == 1 assert c.deposit == 7 # Check if channel can be resynced after data loss. client.channels = [] client.sync_channels() assert len(client.channels) == 1 c = client.channels[0] assert c.deposit == 7 # Check if channel is forgotten on resync after closure. close_channel_cooperatively(c, receiver_privkey, client.context.channel_manager.address) client.sync_channels() assert c not in client.channels
def test_static_price(empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks, receiver_privkey: str): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address content = PaywalledContent( 'resource', price=3, get_fn=lambda url: ('SUCCESS', 200), ) proxy.add_content(content) response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 channel = client.get_suitable_channel(headers.receiver_address, 3) wait_for_blocks(6) channel.balance = 3 headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 assert response.text.strip() == '"SUCCESS"' close_channel_cooperatively(channel, receiver_privkey, client.channel_manager_address, 0)
def test_integrity(client: Client, receiver_address): c = client.get_suitable_channel(receiver_address, 5) assert c is not None assert c.balance == 0 assert c.balance_sig == sign_balance_proof( client.context.private_key, receiver_address, c.block, 0, client.context.channel_manager.address ) assert c.is_valid() # Balance update without sig update. c._balance = 2 assert not c.is_valid() # Proper balance update with sig update. c.update_balance(2) assert c.is_valid() # Random sig. c._balance_sig = b'wrong' assert not c.is_valid() # Balance exceeds deposit. c.update_balance(100) assert not c.is_valid() c.update_balance(0)
def test_explicit_json( empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks ): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address proxy.add_paywalled_resource(JSONResource, '/resource', 3) # test GET response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 channel = client.get_suitable_channel(headers.receiver_address, int(headers.price) * 4) wait_for_blocks(6) channel.update_balance(int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 # If headers don't merge properly, this results in 'application/json,application/json'. assert response.headers['Content-Type'] == 'application/json' assert response.json() == {'GET': 1}
def test_explicit_json(empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address proxy.add_paywalled_resource(JSONResource, '/resource', 3) # test GET response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 channel = client.get_suitable_channel(headers.receiver_address, int(headers.price) * 4) wait_for_blocks(6) channel.update_balance(int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 # If headers don't merge properly, this results in 'application/json,application/json'. assert response.headers['Content-Type'] == 'application/json' assert response.json() == {'GET': 1}
def test_static_price(empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address proxy.add_paywalled_resource(StaticPriceResource, '/resource', 3) # test GET response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 channel = client.get_suitable_channel(headers.receiver_address, int(headers.price) * 4) wait_for_blocks(6) channel.update_balance(int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 assert response.text.strip() == 'GET' assert_method(requests.post, endpoint_url + '/resource', headers, channel, 'POST') assert_method(requests.put, endpoint_url + '/resource', headers, channel, 'PUT') assert_method(requests.delete, endpoint_url + '/resource', headers, channel, 'DEL')
def test_static_price( empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks ): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address proxy.add_paywalled_resource(StaticPriceResource, '/resource', 3) # test GET response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 channel = client.get_suitable_channel(headers.receiver_address, int(headers.price) * 4) wait_for_blocks(6) channel.update_balance(int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 assert response.text.strip() == 'GET' assert_method(requests.post, endpoint_url + '/resource', headers, channel, 'POST') assert_method(requests.put, endpoint_url + '/resource', headers, channel, 'PUT') assert_method(requests.delete, endpoint_url + '/resource', headers, channel, 'DEL')
def test_dynamic_price(empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks, receiver_privkey: str): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address price_cycle = cycle([1, 2, 3, 4, 5]) url_to_price = {} def price_fn(url: str): if url in url_to_price: price = url_to_price[url] else: price = next(price_cycle) url_to_price[url] = price return price content = PaywalledContent( 'resource_\d', price=price_fn, get_fn=lambda url: (url.split("_")[1], 200), ) proxy.add_content(content) response = requests.get(endpoint_url + '/resource_3') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 response = requests.get(endpoint_url + '/resource_5') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 2 response = requests.get(endpoint_url + '/resource_2') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 response = requests.get(endpoint_url + '/resource_3') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 channel = client.get_suitable_channel(headers.receiver_address, 2) wait_for_blocks(6) channel.balance = 2 headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource_5', headers=headers) assert response.status_code == 200 assert response.text.strip() == '"5"' close_channel_cooperatively(channel, receiver_privkey, client.channel_manager_address, 0)
def test_get_expired(empty_proxy: PaywalledProxy, api_endpoint_address: str, sender_address: str, receiver_address: str, client: Client, wait_for_blocks): """ Test with manual client interaction for isolated server testing. Note: Debug in microraiden.proxy.resources.expensive for most of the server response logic. """ es_mock = ElasticsearchBackend(None) es_mock.search = mock.Mock(return_value=Resource( price=5, content='success', expires_at=time.time() + 0.05)) APIServer(empty_proxy, es=es_mock) api_path = 'http://' + api_endpoint_address # Request price (and cache resource). body = {'query': 'query something'} url = api_path + '/some_index/some_type/_search' response = requests.get(url, json=body) assert response.status_code == 402 # Perform payment and request same resource again. Include payment information in headers. channel = client.get_suitable_channel(receiver_address, 5) # Server requires some confirmations, so mine some blocks. wait_for_blocks(10) channel.create_transfer(5) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = sender_address headers.receiver_address = receiver_address headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) # Make sure the price changes for the next request. es_mock.search = mock.Mock(return_value=Resource( price=3, content='success', expires_at=time.time() + 0.05)) # Let former query expire. gevent.sleep(0.1) # Query same resource again with the old expired price. response = requests.get(url, headers=headers, json=body) assert response.status_code == 402 assert response.headers[HTTPHeaders.PRICE] == '3' channel.update_balance(3) headers[HTTPHeaders.BALANCE] = str(channel.balance) headers[HTTPHeaders.BALANCE_SIGNATURE] = encode_hex(channel.balance_sig) response = requests.get(url, headers=headers, json=body) assert response.json() == 'success' es_mock.search.call_args_list == [{ 'query': 'query something' }, { 'query': 'query something' }]
def test_get(empty_proxy: PaywalledProxy, api_endpoint_address: str, channel_manager_address: str, token_address: str, sender_address: str, receiver_address: str, client: Client, wait_for_blocks): """ Test with manual client interaction for isolated server testing. Note: Debug in microraiden.proxy.resources.expensive for most of the server response logic. """ es_mock = ElasticsearchBackend(None) es_mock.search = mock.Mock(return_value=Resource( price=5, content='success', expires_at=time.time() + 30)) server = APIServer(empty_proxy, es=es_mock) api_path = 'http://' + api_endpoint_address # Request price (and cache resource). body = {'query': 'query something'} url = api_path + '/some_index/some_type/_search' response = requests.get(url, json=body) print(response.content) assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert headers.token_address == token_address assert headers.contract_address == channel_manager_address assert headers.receiver_address == receiver_address price = int(headers.price) assert price == 5 assert len(server.resource_cache) == 1 # Perform payment and request same resource again. Include payment information in headers. channel = client.get_suitable_channel(receiver_address, price) # Server requires some confirmations, so mine some blocks. wait_for_blocks(10) channel.create_transfer(price) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = sender_address headers.receiver_address = receiver_address headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(url, headers=headers, json=body) headers = HTTPHeaders.deserialize(response.headers) assert 'nonexisting_channel' not in headers, 'Server should acknowledge the created channel.' assert 'insuf_confs' not in headers, 'Server should acknowledge the created channel.' assert 'invalid_amount' not in headers, 'The correct amount should have been sent.' assert response.status_code == 200 assert response.json() == 'success' assert len(server.resource_cache) == 1 es_mock.search.assert_called_once_with(index='some_index', doc_type='some_type', body={'query': 'query something'})
def test_cooperative_close(client: Client, receiver_privkey, receiver_address): c = client.get_suitable_channel(receiver_address, 3) c.create_transfer(3) assert c.deposit >= 3 assert c.balance == 3 sig = sign_balance_proof(receiver_privkey, c.receiver, c.block, c.balance) assert c.close_cooperatively(sig) assert c.state == Channel.State.closed
def test_cooperative_close(client: Client, receiver_privkey, receiver_address): c = client.get_suitable_channel(receiver_address, 3) assert c is not None c.create_transfer(3) assert c.deposit >= 3 assert c.balance == 3 sig = sign_close(receiver_privkey, c.sender, c.block, c.balance, client.context.channel_manager.address) assert c.close_cooperatively(sig) assert c.state == Channel.State.closed
def test_dynamic_price(empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address price_cycle = cycle([1, 2, 3, 4, 5]) url_to_price = {} # type: Dict def price_fn(url: str): if url in url_to_price: price = url_to_price[url] else: price = next(price_cycle) url_to_price[url] = price return price proxy.add_paywalled_resource(DynamicPriceResource, '/resource_<int:res_id>', price_fn) response = requests.get(endpoint_url + '/resource_3') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 response = requests.get(endpoint_url + '/resource_5') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 2 response = requests.get(endpoint_url + '/resource_2') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 response = requests.get(endpoint_url + '/resource_3') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 channel = client.get_suitable_channel(headers.receiver_address, 2) wait_for_blocks(6) channel.update_balance(2) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource_5', headers=headers) assert response.status_code == 200 assert response.text.strip() == '5'
def test_method_price(empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address proxy.add_paywalled_resource(DynamicMethodResource, '/resource', resource_class_args=(42, ), resource_class_kwargs={'bar': 9814072356}) # test GET response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 channel = client.get_suitable_channel(headers.receiver_address, 1 + 2 + 3 + 4) wait_for_blocks(6) channel.update_balance(int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 assert response.text.strip() == 'GET' assert_method(requests.post, endpoint_url + '/resource', headers, channel, 'POST', expected_price=2) assert_method(requests.put, endpoint_url + '/resource', headers, channel, 'PUT', expected_price=3) assert_method(requests.delete, endpoint_url + '/resource', headers, channel, 'DEL', expected_price=4)
def test_method_price( empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks ): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address proxy.add_paywalled_resource( DynamicMethodResource, '/resource', resource_class_args=(42,), resource_class_kwargs={'bar': 9814072356}) # test GET response = requests.get(endpoint_url + '/resource') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 channel = client.get_suitable_channel(headers.receiver_address, 1 + 2 + 3 + 4) wait_for_blocks(6) channel.update_balance(int(headers.price)) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource', headers=headers) assert response.status_code == 200 assert response.text.strip() == 'GET' assert_method(requests.post, endpoint_url + '/resource', headers, channel, 'POST', expected_price=2) assert_method(requests.put, endpoint_url + '/resource', headers, channel, 'PUT', expected_price=3) assert_method(requests.delete, endpoint_url + '/resource', headers, channel, 'DEL', expected_price=4)
def test_cooperative_close(client: Client, receiver_privkey, receiver_address): c = client.get_suitable_channel(receiver_address, 3) assert c is not None c.create_transfer(3) assert c.deposit >= 3 assert c.balance == 3 sig = sign_close( receiver_privkey, c.sender, c.block, c.balance, client.context.channel_manager.address ) assert c.close_cooperatively(sig) assert c.state == Channel.State.closed
def test_integrity(client: Client, receiver_address): c = client.get_suitable_channel(receiver_address, 5) assert c.balance == 0 assert c.balance_sig == sign_balance_proof(client.privkey, receiver_address, c.block, 0) assert c.is_valid() # Balance update without sig update. c._balance = 2 assert not c.is_valid() # Proper balance update with sig update. c.balance = 2 assert c.is_valid() # Random sig. c._balance_sig = b'wrong' assert not c.is_valid() # Balance exceeds deposit. c.balance = 100 assert not c.is_valid()
def test_sync(client: Client, receiver_address, receiver_privkey): c = client.get_suitable_channel(receiver_address, 5) assert c in client.channels assert len(client.channels) == 1 # Check if channel is still valid after sync. client.sync_channels() assert c in client.channels assert len(client.channels) == 1 # Check if channel can be resynced after data loss. client.channels = [] client.store_channels() client.sync_channels() # Check if channel is forgotten on resync after closure. assert len(client.channels) == 1 c = client.channels[0] close_channel_cooperatively(c, receiver_privkey) client.sync_channels() assert c not in client.channels
def test_dynamic_price( empty_proxy: PaywalledProxy, api_endpoint_address: str, client: Client, wait_for_blocks ): proxy = empty_proxy endpoint_url = "http://" + api_endpoint_address price_cycle = cycle([1, 2, 3, 4, 5]) url_to_price = {} # type: Dict def price_fn(): url = request.path if int(url.split('_')[-1]) == 0: return 0 if url in url_to_price: price = url_to_price[url] else: price = next(price_cycle) url_to_price[url] = price return price proxy.add_paywalled_resource( DynamicPriceResource, '/resource_<int:res_id>', price=price_fn ) response = requests.get(endpoint_url + '/resource_3') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 response = requests.get(endpoint_url + '/resource_5') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 2 response = requests.get(endpoint_url + '/resource_2') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 3 response = requests.get(endpoint_url + '/resource_3') assert response.status_code == 402 headers = HTTPHeaders.deserialize(response.headers) assert int(headers.price) == 1 response = requests.get(endpoint_url + '/resource_0') assert response.status_code == 200 assert response.text.strip() == '0' channel = client.get_suitable_channel(headers.receiver_address, 2) wait_for_blocks(6) channel.update_balance(2) headers = Munch() headers.balance = str(channel.balance) headers.balance_signature = encode_hex(channel.balance_sig) headers.sender_address = channel.sender headers.open_block = str(channel.block) headers = HTTPHeaders.serialize(headers) response = requests.get(endpoint_url + '/resource_5', headers=headers) assert response.status_code == 200 assert response.text.strip() == '5'