class TestSQLiteStorage(FlaskTrackUsageTestCase):
    def _create_storage(self):
        engine = sql.create_engine("sqlite://")
        metadata = sql.MetaData(bind=engine)
        self.storage = SQLStorage(engine=engine,
                                  metadata=metadata,
                                  table_name=self.given_table_name)
        metadata.create_all()

    def tearDown(self):
        meta = sql.MetaData()
        meta.reflect(bind=self.storage._eng)
        for table in reversed(meta.sorted_tables):
            self.storage._eng.execute(table.delete())

    def setUp(self):
        self.given_table_name = 'my_usage'
        FlaskTrackUsageTestCase.setUp(self)
        self.blueprint = Blueprint('blueprint', __name__)

        @self.blueprint.route('/blueprint')
        def blueprint():
            return "blueprint"

        self.app.register_blueprint(self.blueprint)

        self._create_storage()

        self.track_usage = TrackUsage(self.app, self.storage)
        self.track_usage.include_blueprint(self.blueprint)

    def test_table_name(self):

        meta = sql.MetaData()
        meta.reflect(bind=self.storage._eng)
        assert self.given_table_name == meta.tables.keys()[0]

    def test_storage_data_basic(self):
        self.client.get('/')
        con = self.storage._eng.connect()
        s = sql.select([self.storage.track_table])
        result = con.execute(s).fetchone()
        #assert result[0] == 1  # first row
        assert result[1] == u'http://localhost/'
        assert result[2] is None
        assert result[3] is None
        assert result[4] is None
        assert result[5] is None
        assert result[6] is None
        assert result[8] == 200
        self.assertTrue(result[9])
        assert result[10] == None
        assert result[11] == False
        assert result[12] is None
        assert result[13] == '/'
        assert result[14].__class__ is float
        assert type(result[15]) is datetime.datetime

    def test_storage_data_blueprint(self):
        self.client.get('/blueprint')
        con = self.storage._eng.connect()
        s = sql.select([self.storage.track_table])
        result = con.execute(s).fetchone()
        assert result[1] == u'http://localhost/blueprint'
        assert result[2] is None
        assert result[3] is None
        assert result[4] is None
        assert result[5] is None
        assert result[6] == 'blueprint'
        assert result[8] == 200
        self.assertTrue(result[9])
        assert result[10] is None
        assert result[11] == False
        assert result[12] is None
        assert result[13] == '/blueprint'
        assert result[14].__class__ is float
        assert type(result[15]) is datetime.datetime

    def test_storage__get_raw(self):
        # First check no blueprint case get_usage is correct
        self.client.get('/')
        result = self.storage._get_raw()[0]
        assert result[1] == u'http://localhost/'
        assert result[2] is None
        assert result[3] is None
        assert result[4] is None
        assert result[5] is None
        assert result[6] is None
        assert result[8] == 200
        self.assertTrue(result[9])
        assert result[10] is None
        assert result[11] == False
        assert result[12] is None
        assert result[13] == '/'
        assert result[14].__class__ is float
        assert type(result[15]) is datetime.datetime

        # Next check with blueprint the get_usage is correct
        self.client.get('/blueprint')
        rows = self.storage._get_raw()
        print rows[1]
        result = rows[1]  # if rows[0][6] is None else rows[0]
        #assert result[0] == 2 # first row
        assert result[1] == u'http://localhost/blueprint'
        assert result[2] is None
        assert result[3] is None
        assert result[4] is None
        assert result[5] is None
        assert result[6] == 'blueprint'
        assert result[8] == 200
        self.assertTrue(result[9])
        assert result[10] is None
        assert result[11] == False
        assert result[12] is None
        assert result[13] == '/blueprint'
        assert result[14].__class__ is float
        assert type(result[15]) is datetime.datetime

        # third get
        self.client.get('/')

        # Limit tests
        assert len(self.storage._get_raw()) == 3
        assert len(self.storage._get_raw(limit=2)) == 2
        assert len(self.storage._get_raw(limit=1)) == 1

        # timing tests
        # give a 5 second lag since datetime stored is second precision

        now = datetime.datetime.utcnow() + datetime.timedelta(0, 5)
        assert len(self.storage._get_raw(start_date=now)) == 0
        assert len(self.storage._get_raw(end_date=now)) == 3
        assert len(self.storage._get_raw(end_date=now, limit=2)) == 2

    def test_storage__get_usage(self):
        self.client.get('/')
        result = self.storage._get_raw()[0]
        result2 = self.storage._get_usage()[0]
        #assert result[0] == 1 # first row
        assert result[1] == result2['url']
        assert result[2] == result2['user_agent']['browser']
        assert result[3] == result2['user_agent']['language']
        assert result[4] == result2['user_agent']['platform']
        assert result[5] == result2['user_agent']['version']
        assert result[6] == result2['blueprint']
        assert result[8] == result2['status']
        assert result[9] == result2['remote_addr']
        assert result[10] == result2['xforwardedfor']
        assert result[11] == result2['authorization']
        assert result[12] == result2['ip_info']
        assert result[13] == result2['path']
        assert result[14] == result2['speed']
        assert result[15] == result2['date']

    def test_storage_get_usage(self):
        self.client.get('/')
        result = self.storage._get_raw()[0]
        result2 = self.storage.get_usage()[0]
        #assert result[0] == 1 # first row
        assert result[1] == result2['url']
        assert result[2] == result2['user_agent']['browser']
        assert result[3] == result2['user_agent']['language']
        assert result[4] == result2['user_agent']['platform']
        assert result[5] == result2['user_agent']['version']
        assert result[6] == result2['blueprint']
        assert result[8] == result2['status']
        assert result[9] == result2['remote_addr']
        assert result[10] == result2['xforwardedfor']
        assert result[11] == result2['authorization']
        assert result[12] == result2['ip_info']
        assert result[13] == result2['path']
        assert result[14] == result2['speed']
        assert result[15] == result2['date']

    def test_storage_get_usage_pagination(self):
        # test pagination
        for i in range(100):
            self.client.get('/')

        limit = 10
        num_pages = 10
        for page in range(1, num_pages + 1):
            result = self.storage._get_usage(limit=limit, page=page)
            assert len(result) == limit

        # actual api test
        result = self.storage._get_raw(limit=100)  # raw data
        result2 = self.storage.get_usage(limit=100)  # dict data
        for i in range(100):
            assert result[i][1] == result2[i]['url']
            assert result[i][2] == result2[i]['user_agent']['browser']
            assert result[i][3] == result2[i]['user_agent']['language']
            assert result[i][4] == result2[i]['user_agent']['platform']
            assert result[i][5] == result2[i]['user_agent']['version']
            assert result[i][6] == result2[i]['blueprint']
            assert result[i][8] == result2[i]['status']
            assert result[i][9] == result2[i]['remote_addr']
            assert result[i][10] == result2[i]['xforwardedfor']
            assert result[i][11] == result2[i]['authorization']
            assert result[i][12] == result2[i]['ip_info']
            assert result[i][13] == result2[i]['path']
            assert result[i][14] == result2[i]['speed']
            assert result[i][15] == result2[i]['date']
class TestSQLiteStorage(FlaskTrackUsageTestCase):

    def _create_storage(self):
        engine = sql.create_engine("sqlite://")
        metadata = sql.MetaData(bind=engine)
        self.storage = SQLStorage(
            engine=engine,
            metadata=metadata,
            table_name=self.given_table_name
        )
        metadata.create_all()

    def tearDown(self):
        meta = sql.MetaData()
        meta.reflect(bind=self.storage._eng)
        for table in reversed(meta.sorted_tables):
            self.storage._eng.execute(table.delete())

    def setUp(self):
        self.given_table_name = 'my_usage'
        FlaskTrackUsageTestCase.setUp(self)
        self.blueprint = Blueprint('blueprint', __name__)

        @self.blueprint.route('/blueprint')
        def blueprint():
            return "blueprint"
        self.app.register_blueprint(self.blueprint)

        self._create_storage()

        self.track_usage = TrackUsage(self.app, self.storage)
        self.track_usage.include_blueprint(self.blueprint)

    def test_table_name(self):
        meta = sql.MetaData()
        meta.reflect(bind=self.storage._eng)
        print(self.given_table_name, list(meta.tables.keys())[0])
        self.assertIn(self.given_table_name, meta.tables.keys())

    def test_storage_data_basic(self):
        self.client.get('/')
        con = self.storage._eng.connect()
        s = sql.select([self.storage.track_table])
        result = con.execute(s).fetchone()
        #assert result[0] == 1  # first row
        assert result[1] == u'http://localhost/'
        assert result[2] is None
        assert result[3] is None
        assert result[4] is None
        assert result[5] is None
        assert result[6] is None
        assert result[8] == 200
        self.assertTrue(result[9])
        assert result[10] == None
        assert result[11] == False
        assert result[12] is None
        assert result[13] == '/'
        assert result[14].__class__ is float
        assert type(result[15]) is datetime.datetime

    def test_storage_data_blueprint(self):
        self.client.get('/blueprint')
        con = self.storage._eng.connect()
        s = sql.select([self.storage.track_table])
        result = con.execute(s).fetchone()
        assert result[1] == u'http://localhost/blueprint'
        assert result[2] is None
        assert result[3] is None
        assert result[4] is None
        assert result[5] is None
        assert result[6] == 'blueprint'
        assert result[8] == 200
        self.assertTrue(result[9])
        assert result[10] is None
        assert result[11] == False
        assert result[12] is None
        assert result[13] == '/blueprint'
        assert result[14].__class__ is float
        assert type(result[15]) is datetime.datetime

    def test_storage__get_raw(self):
        # First check no blueprint case get_usage is correct
        self.client.get('/')
        result = self.storage._get_raw()[0]
        assert result[1] == u'http://localhost/'
        assert result[2] is None
        assert result[3] is None
        assert result[4] is None
        assert result[5] is None
        assert result[6] is None
        assert result[8] == 200
        self.assertTrue(result[9])
        assert result[10] is None
        assert result[11] == False
        assert result[12] is None
        assert result[13] == '/'
        assert result[14].__class__ is float
        assert type(result[15]) is datetime.datetime

        # Next check with blueprint the get_usage is correct
        self.client.get('/blueprint')
        rows = self.storage._get_raw()
        print(rows[1])
        result = rows[1]# if rows[0][6] is None else rows[0]
        #assert result[0] == 2 # first row
        assert result[1] == u'http://localhost/blueprint'
        assert result[2] is None
        assert result[3] is None
        assert result[4] is None
        assert result[5] is None
        assert result[6] == 'blueprint'
        assert result[8] == 200
        self.assertTrue(result[9])
        assert result[10] is None
        assert result[11] == False
        assert result[12] is None
        assert result[13] == '/blueprint'
        assert result[14].__class__ is float
        assert type(result[15]) is datetime.datetime

        # third get
        self.client.get('/')

        # Limit tests
        assert len(self.storage._get_raw()) == 3
        assert len(self.storage._get_raw(limit=2)) == 2
        assert len(self.storage._get_raw(limit=1)) == 1

        # timing tests
        # give a 5 second lag since datetime stored is second precision

        now = datetime.datetime.utcnow() + datetime.timedelta(0, 5)
        assert len(self.storage._get_raw(start_date=now)) == 0
        assert len(self.storage._get_raw(end_date=now)) == 3
        assert len(self.storage._get_raw(end_date=now, limit=2)) == 2

    def test_storage__get_usage(self):
        self.client.get('/')
        result = self.storage._get_raw()[0]
        result2 = self.storage._get_usage()[0]
        #assert result[0] == 1 # first row
        assert result[1] == result2['url']
        assert result[2] == result2['user_agent']['browser']
        assert result[3] == result2['user_agent']['language']
        assert result[4] == result2['user_agent']['platform']
        assert result[5] == result2['user_agent']['version']
        assert result[6] == result2['blueprint']
        assert result[8] == result2['status']
        assert result[9] == result2['remote_addr']
        assert result[10] == result2['xforwardedfor']
        assert result[11] == result2['authorization']
        assert result[12] == result2['ip_info']
        assert result[13] == result2['path']
        assert result[14] == result2['speed']
        assert result[15] == result2['date']
        assert result[16] == result2['username']
        track_var = result[17] if result[17] != '{}' else None
        assert track_var == result2['track_var']

    def test_storage_get_usage(self):
        self.client.get('/')
        result = self.storage._get_raw()[0]
        result2 = self.storage.get_usage()[0]
        #assert result[0] == 1 # first row
        assert result[1] == result2['url']
        assert result[2] == result2['user_agent']['browser']
        assert result[3] == result2['user_agent']['language']
        assert result[4] == result2['user_agent']['platform']
        assert result[5] == result2['user_agent']['version']
        assert result[6] == result2['blueprint']
        assert result[8] == result2['status']
        assert result[9] == result2['remote_addr']
        assert result[10] == result2['xforwardedfor']
        assert result[11] == result2['authorization']
        assert result[12] == result2['ip_info']
        assert result[13] == result2['path']
        assert result[14] == result2['speed']
        assert result[15] == result2['date']
        assert result[16] == result2['username']
        track_var = result[17] if result[17] != '{}' else None
        assert track_var == result2['track_var']

    def test_storage_get_usage_pagination(self):
        # test pagination
        for i in range(100):
            self.client.get('/')

        limit = 10
        num_pages = 10
        for page in range(1, num_pages + 1):
            result = self.storage._get_usage(limit=limit, page=page)
            assert len(result) == limit

        # actual api test
        result = self.storage._get_raw(limit=100)  # raw data
        result2 = self.storage.get_usage(limit=100)  # dict data
        for i in range(100):
            assert result[i][1] == result2[i]['url']
            assert result[i][2] == result2[i]['user_agent']['browser']
            assert result[i][3] == result2[i]['user_agent']['language']
            assert result[i][4] == result2[i]['user_agent']['platform']
            assert result[i][5] == result2[i]['user_agent']['version']
            assert result[i][6] == result2[i]['blueprint']
            assert result[i][8] == result2[i]['status']
            assert result[i][9] == result2[i]['remote_addr']
            assert result[i][10] == result2[i]['xforwardedfor']
            assert result[i][11] == result2[i]['authorization']
            assert result[i][12] == result2[i]['ip_info']
            assert result[i][13] == result2[i]['path']
            assert result[i][14] == result2[i]['speed']
            assert result[i][15] == result2[i]['date']
            assert result[i][16] == result2[i]['username']
            track_var = result[i][17] if result[i][17] != '{}' else None
            assert track_var == result2[i]['track_var']
class TestMySQLStorage(FlaskTrackUsageTestCase):
    def _create_storage(self):
        engine = sql.create_engine(SQLALCHEMY_DATABASE_URI)
        metadata = sql.MetaData(bind=engine)
        self.storage = SQLStorage(engine=engine,
                                  metadata=metadata,
                                  table_name=self.given_table_name)
        # metadata.create_all()

    def tearDown(self):
        """
        Delete the table
        """
        self.storage.track_table.drop(self.storage._eng)

    def setUp(self):
        """
        Create the app, track usage and init storage
        """
        self.given_table_name = 'my_usage'
        FlaskTrackUsageTestCase.setUp(self)
        self._create_storage()

        self.track_usage = TrackUsage()
        self.track_usage.init_app(self.app, self.storage)
        # self.track_usage.include_blueprint(self.blueprint)

    def test_table_name(self):
        meta = sql.MetaData()
        meta.reflect(bind=self.storage._eng)
        print(self.given_table_name, list(meta.tables.keys())[0])
        self.assertIn(self.given_table_name, meta.tables.keys())

    def test_storage_data_basic(self):
        self.client.get('/')
        result = self.storage.track_table.select().execute().first()
        assert result['id'] == 1  # first row
        assert result['url'] == u'http://localhost/'
        assert result['ua_browser'] is None
        assert result['ua_language'] is None
        assert result['ua_platform'] is None
        assert result['ua_version'] is None
        assert result['blueprint'] is None
        assert result['view_args'] == '{}'
        assert result['status'] == 200
        assert result['remote_addr'] == '127.0.0.1'
        assert result['xforwardedfor'] is None
        assert result['authorization'] is False
        assert result['ip_info'] is None
        assert result['path'] == '/'
        assert result['speed'] > 0
        assert type(result['date']) is datetime.datetime
        assert result['username'] is None
        assert result['track_var'] == '{}'

    def test_storage_get_usage_pagination(self):
        # test pagination
        for i in range(100):
            self.client.get('/')

        limit = 10
        num_pages = 10
        for page in range(1, num_pages + 1):
            result = self.storage._get_usage(limit=limit, page=page)
            assert len(result) == limit

        # actual api test
        result = self.storage._get_raw(limit=100)  # raw data
        result2 = self.storage.get_usage(limit=100)  # dict data
        for i in range(100):
            for key in result[i].keys():
                if key == 'id':
                    assert key not in result2[i]
                    assert key in result[i]
                elif 'ua_' in key:
                    result[i][key] == result2[i]['user_agent'][key.split('_')
                                                               [1]]
                elif result[i][key] == '{}':
                    assert result2[i][key] is None
                else:
                    assert result[i][key] == result2[i][key]