from __future__ import absolute_import, division, print_function import os # Don't remove !!! import threading import pytest from olap.xmla import xmla from spyne import Application from spyne.protocol.soap import Soap11 from spyne.server.wsgi import WsgiApplication from werkzeug.serving import make_server from olapy.core.services.xmla import XmlaProviderService from tests.xs0_responses import TEST_QUERY_AXIS0 HOST = "127.0.0.1" PORT = 8230 RUNNING_TOX = 'RUNTING_TOX' in os.environ class Member(object): def __init__(self, **kwargs): self.__dict__.update(kwargs) def __eq__(self, other): if isinstance(other, self.__class__): return self.__dict__ == other.__dict__ return NotImplemented def __ne__(self, other): if isinstance(other, self.__class__): return not self.__eq__(other) return NotImplemented def __hash__(self): return hash(tuple(sorted(self.__dict__.items()))) class WSGIServer: """ HTTP server running a WSGI application in its own thread. Copy/pasted from pytest_localserver w/ slight changes. """ def __init__(self, host='127.0.0.1', port=8000, application=None, **kwargs): self._server = make_server(host, port, application, **kwargs) self.server_address = self._server.server_address self.thread = threading.Thread( name=self.__class__, target=self._server.serve_forever) def __del__(self): self.stop() def start(self): self.thread.start() def stop(self): self._server.shutdown() self.thread.join() @property def url(self): host, port = self.server_address proto = 'http' if self._server.ssl_context is None else 'https' return '%s://%s:%i' % (proto, host, port) @pytest.fixture(scope="function") def conn(): print("spawning server") application = Application( [XmlaProviderService], 'urn:schemas-microsoft-com:xml-analysis', in_protocol=Soap11(validator='soft'), out_protocol=Soap11(validator='soft')) wsgi_application = WsgiApplication(application) server = WSGIServer(application=wsgi_application, host=HOST, port=PORT) server.start() provider = xmla.XMLAProvider() conn = provider.connect(location=server.url) yield conn print("stopping server") server.stop() @pytest.mark.skipif("RUNNING_TOX") def test_connection(conn): assert len(conn.getCatalogs()) > 0 @pytest.mark.skipif("RUNNING_TOX") def test_DISCOVER_PROPERTIES(conn): discover = conn.Discover( 'DISCOVER_PROPERTIES', properties={'LocaleIdentifier': '1036'}, restrictions={'PropertyName': 'Catalog'})[0] assert discover['PropertyName'] == "Catalog" assert discover['PropertyDescription'] == "Catalog" assert discover['PropertyType'] == "string" assert discover['PropertyAccessType'] == "ReadWrite" assert discover['IsRequired'] == "false" assert discover['Value'] == "olapy Unspecified Catalog" @pytest.mark.skipif("RUNNING_TOX") def test_MDSCHEMA_CUBES(conn): discover = conn.Discover( "MDSCHEMA_CUBES", restrictions={'CUBE_NAME': 'sales'}, properties={'Catalog': 'sales'})[0] assert discover['CATALOG_NAME'] == "sales" assert discover['CUBE_NAME'] == "sales" assert discover['CUBE_TYPE'] == "CUBE" assert discover['IS_DRILLTHROUGH_ENABLED'] == "true" assert discover['CUBE_CAPTION'] == "sales" @pytest.mark.skipif("RUNNING_TOX") def test_query1(conn): # only one measure selected # Result : # Amount # 1023 cmd = """ SELECT FROM [sales] WHERE ([Measures].[Amount]) CELL PROPERTIES VALUE, FORMAT_STRING, LANGUAGE, BACK_COLOR, FORE_COLOR, FONT_FLAGS """ res = conn.Execute(cmd, Catalog="sales") assert res.cellmap[0]['_CellOrdinal'] == '0' assert res.cellmap[0]['Value'] == 1023 @pytest.mark.skipif("RUNNING_TOX") def test_query2(conn): # drill down on one Dimension # Result : # Row Labels Amount # All Continent 1023 # America 768 # United States 768 # New York 768 # Europe 255 # France 4 # Spain 3 # Barcelona 2 # Madrid 1 # Switzerland 248 # This kind of query is generated by excel once you select a dimension a you do drill dow cmd = """ SELECT NON EMPTY Hierarchize(AddCalculatedMembers(DrilldownMember( {{DrilldownMember({{{[Geography].[Geography].[All Continent].Members}}}, {[Geography].[Geography].[Continent].[America], [Geography].[Geography].[Continent].[Europe]})}}, {[Geography].[Geography].[Continent].[America].[United States], [Geography].[Geography].[Continent].[Europe].[Spain]}))) DIMENSION PROPERTIES PARENT_UNIQUE_NAME,HIERARCHY_UNIQUE_NAME ON COLUMNS FROM [sales] WHERE ([Measures].[Amount]) CELL PROPERTIES VALUE, FORMAT_STRING, LANGUAGE, BACK_COLOR, FORE_COLOR, FONT_FLAGS """ res = conn.Execute(cmd, Catalog="sales") columns = [] values = [] for cell in res.cellmap.viewitems(): columns.append(res.getAxisTuple('Axis0')[cell[0]]) values.append(cell[1]['Value']) mems = [] mems.append( Member( _Hierarchy='[Geography].[Geography]', UName='[Geography].[Geography].[Continent].[America]', Caption='America', LName='[Geography].[Geography].[Continent]', LNum='0', DisplayInfo='131076', HIERARCHY_UNIQUE_NAME='[Geography].[Geography]')) mems.append( Member( _Hierarchy='[Geography].[Geography]', UName='[Geography].[Geography].[Country].[America].[United States]', Caption='United States', LName='[Geography].[Geography].[Country]', LNum='1', DisplayInfo='131076', PARENT_UNIQUE_NAME='[Geography].[Geography].[Continent].[America]', HIERARCHY_UNIQUE_NAME='[Geography].[Geography]')) mems.append( Member( _Hierarchy='[Geography].[Geography]', UName='[Geography].[Geography].[City].[America].[United States].[New York]', Caption='New York', LName='[Geography].[Geography].[City]', LNum='2', DisplayInfo='131076', PARENT_UNIQUE_NAME='[Geography].[Geography].[Continent].[America].[United States]', HIERARCHY_UNIQUE_NAME='[Geography].[Geography]')) mems.append( Member( _Hierarchy='[Geography].[Geography]', UName='[Geography].[Geography].[Continent].[Europe]', Caption='Europe', LName='[Geography].[Geography].[Continent]', LNum='0', DisplayInfo='131076', HIERARCHY_UNIQUE_NAME='[Geography].[Geography]')) mems.append( Member( _Hierarchy='[Geography].[Geography]', UName='[Geography].[Geography].[Country].[Europe].[France]', Caption='France', LName='[Geography].[Geography].[Country]', LNum='1', DisplayInfo='131076', PARENT_UNIQUE_NAME='[Geography].[Geography].[Continent].[Europe]', HIERARCHY_UNIQUE_NAME='[Geography].[Geography]')) mems.append( Member( _Hierarchy='[Geography].[Geography]', UName='[Geography].[Geography].[Country].[Europe].[Spain]', Caption='Spain', LName='[Geography].[Geography].[Country]', LNum='1', DisplayInfo='131076', PARENT_UNIQUE_NAME='[Geography].[Geography].[Continent].[Europe]', HIERARCHY_UNIQUE_NAME='[Geography].[Geography]')) mems.append( Member( _Hierarchy='[Geography].[Geography]', UName='[Geography].[Geography].[City].[Europe].[Spain].[Barcelona]', Caption='Barcelona', LName='[Geography].[Geography].[City]', LNum='2', DisplayInfo='131076', PARENT_UNIQUE_NAME='[Geography].[Geography].[Continent].[Europe].[Spain]', HIERARCHY_UNIQUE_NAME='[Geography].[Geography]')) mems.append( Member( _Hierarchy='[Geography].[Geography]', UName='[Geography].[Geography].[City].[Europe].[Spain].[Madrid]', Caption='Madrid', LName='[Geography].[Geography].[City]', LNum='2', DisplayInfo='131076', PARENT_UNIQUE_NAME='[Geography].[Geography].[Continent].[Europe].[Spain]', HIERARCHY_UNIQUE_NAME='[Geography].[Geography]')) mems.append( Member( _Hierarchy='[Geography].[Geography]', UName='[Geography].[Geography].[Country].[Europe].[Switzerland]', Caption='Switzerland', LName='[Geography].[Geography].[Country]', LNum='1', DisplayInfo='131076', PARENT_UNIQUE_NAME='[Geography].[Geography].[Continent].[Europe]', HIERARCHY_UNIQUE_NAME='[Geography].[Geography]')) assert [Member(**dict(co)) for co in columns] == mems assert values == [768, 768, 768, 255, 4, 3, 2, 1, 248] @pytest.mark.skipif("RUNNING_TOX") def test_query3(conn): # Many Dimensions selected # Result : # Row Labels Amount # All Continent # America # Crazy Development # 2010 # 768 # Europe # Crazy Development # 2010 # 255 # This kind of query is generated by excel once you select a dimension a you do drill dow cmd = """ SELECT NON EMPTY CrossJoin(CrossJoin(Hierarchize(AddCalculatedMembers({ [Geography].[Geography].[All Continent].Members})), Hierarchize(AddCalculatedMembers({ [Product].[Product].[Company].Members}))), Hierarchize(AddCalculatedMembers({[Time].[Time].[Year].Members}))) DIMENSION PROPERTIES PARENT_UNIQUE_NAME,HIERARCHY_UNIQUE_NAME ON COLUMNS FROM [sales] WHERE ([Measures].[Amount]) CELL PROPERTIES VALUE, FORMAT_STRING, LANGUAGE, BACK_COLOR, FORE_COLOR, FONT_FLAGS """ res = conn.Execute(cmd, Catalog="sales") columns = [] values = [] for cell in res.cellmap.viewitems(): columns.append(res.getAxisTuple('Axis0')[cell[0]]) values.append(cell[1]['Value']) mems = [] mems.append([ Member( _Hierarchy='[Geography].[Geography]', UName='[Geography].[Geography].[Continent].[America]', Caption='America', LName='[Geography].[Geography].[Continent]', LNum='0', DisplayInfo='131076', HIERARCHY_UNIQUE_NAME='[Geography].[Geography]'), Member( _Hierarchy='[Product].[Product]', UName='[Product].[Product].[Company].[Crazy Development]', Caption='Crazy Development', LName='[Product].[Product].[Company]', LNum='0', DisplayInfo='131076', HIERARCHY_UNIQUE_NAME='[Product].[Product]'), Member( _Hierarchy='[Time].[Time]', UName='[Time].[Time].[Year].[2010]', Caption='2010', LName='[Time].[Time].[Year]', LNum='0', DisplayInfo='131076', HIERARCHY_UNIQUE_NAME='[Time].[Time]') ]) mems.append([ Member( _Hierarchy='[Geography].[Geography]', UName='[Geography].[Geography].[Continent].[Europe]', Caption='Europe', LName='[Geography].[Geography].[Continent]', LNum='0', DisplayInfo='131076', HIERARCHY_UNIQUE_NAME='[Geography].[Geography]'), Member( _Hierarchy='[Product].[Product]', UName='[Product].[Product].[Company].[Crazy Development]', Caption='Crazy Development', LName='[Product].[Product].[Company]', LNum='0', DisplayInfo='131076', HIERARCHY_UNIQUE_NAME='[Product].[Product]'), Member( _Hierarchy='[Time].[Time]', UName='[Time].[Time].[Year].[2010]', Caption='2010', LName='[Time].[Time].[Year]', LNum='0', DisplayInfo='131076', HIERARCHY_UNIQUE_NAME='[Time].[Time]') ]) for idx, item in enumerate(columns): assert [Member(**dict(co)) for co in item] == mems[idx] assert values == [768, 255] @pytest.mark.skipif("RUNNING_TOX") def test_query4(conn): # Many Dimensions selected with different measures # Result : # Row Labels # Amount # Crazy Development # olapy # All Continent # America # 2010 768 # Europe # France # 2010 4 # Spain # 2010 3 # Switzerland # 2010 248 # Count # Crazy Development # olapy # All Continent # America # 2010 576 # Europe # France # 2010 2 # Spain # 2010 925 # Switzerland # 2010 377 # This kind of query is generated by excel once you select a dimension a you do drill dow cmd = """ SELECT NON EMPTY CrossJoin(CrossJoin(CrossJoin({ [Measures].[Amount], [Measures].[Count]}, Hierarchize(AddCalculatedMembers(DrilldownMember({{ [Product].[Product].[Company].Members}}, { [Product].[Product].[Company].[Crazy Development] })))), Hierarchize(AddCalculatedMembers(DrilldownMember({{{ [Geography].[Geography].[All Continent].Members}}}, { [Geography].[Geography].[Continent].[Europe]})))), Hierarchize(AddCalculatedMembers({ [Time].[Time].[Year].Members}))) DIMENSION PROPERTIES PARENT_UNIQUE_NAME,HIERARCHY_UNIQUE_NAME ON COLUMNS FROM [sales] CELL PROPERTIES VALUE, FORMAT_STRING, LANGUAGE, BACK_COLOR, FORE_COLOR, FONT_FLAGS """ res = conn.Execute(cmd, Catalog="sales") columns = [] values = [] for cell in res.cellmap.viewitems(): columns.append(res.getAxisTuple('Axis0')[cell[0]]) values.append(cell[1]['Value']) strr = """""" for idx, item in enumerate(columns): strr += str(item) assert strr == TEST_QUERY_AXIS0 assert values == [ 768, 255, 4, 3, 248, 768, 255, 4, 3, 248, 576, 1304, 2, 925, 377, 576, 1304, 2, 925, 377 ]