Vehicle-Anti-Theft-Face-Rec.../venv/Lib/site-packages/gcloud/bigtable/test_row_data.py

727 lines
25 KiB
Python

# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest2
class TestCell(unittest2.TestCase):
def _getTargetClass(self):
from gcloud.bigtable.row_data import Cell
return Cell
def _makeOne(self, *args, **kwargs):
return self._getTargetClass()(*args, **kwargs)
def _from_pb_test_helper(self, labels=None):
import datetime
from gcloud._helpers import _EPOCH
from gcloud.bigtable._generated_v2 import (
data_pb2 as data_v2_pb2)
timestamp_micros = 18738724000 # Make sure millis granularity
timestamp = _EPOCH + datetime.timedelta(microseconds=timestamp_micros)
value = b'value-bytes'
if labels is None:
cell_pb = data_v2_pb2.Cell(
value=value, timestamp_micros=timestamp_micros)
cell_expected = self._makeOne(value, timestamp)
else:
cell_pb = data_v2_pb2.Cell(
value=value, timestamp_micros=timestamp_micros, labels=labels)
cell_expected = self._makeOne(value, timestamp, labels=labels)
klass = self._getTargetClass()
result = klass.from_pb(cell_pb)
self.assertEqual(result, cell_expected)
def test_from_pb(self):
self._from_pb_test_helper()
def test_from_pb_with_labels(self):
labels = [u'label1', u'label2']
self._from_pb_test_helper(labels)
def test_constructor(self):
value = object()
timestamp = object()
cell = self._makeOne(value, timestamp)
self.assertEqual(cell.value, value)
self.assertEqual(cell.timestamp, timestamp)
def test___eq__(self):
value = object()
timestamp = object()
cell1 = self._makeOne(value, timestamp)
cell2 = self._makeOne(value, timestamp)
self.assertEqual(cell1, cell2)
def test___eq__type_differ(self):
cell1 = self._makeOne(None, None)
cell2 = object()
self.assertNotEqual(cell1, cell2)
def test___ne__same_value(self):
value = object()
timestamp = object()
cell1 = self._makeOne(value, timestamp)
cell2 = self._makeOne(value, timestamp)
comparison_val = (cell1 != cell2)
self.assertFalse(comparison_val)
def test___ne__(self):
value1 = 'value1'
value2 = 'value2'
timestamp = object()
cell1 = self._makeOne(value1, timestamp)
cell2 = self._makeOne(value2, timestamp)
self.assertNotEqual(cell1, cell2)
class TestPartialRowData(unittest2.TestCase):
def _getTargetClass(self):
from gcloud.bigtable.row_data import PartialRowData
return PartialRowData
def _makeOne(self, *args, **kwargs):
return self._getTargetClass()(*args, **kwargs)
def test_constructor(self):
row_key = object()
partial_row_data = self._makeOne(row_key)
self.assertTrue(partial_row_data._row_key is row_key)
self.assertEqual(partial_row_data._cells, {})
def test___eq__(self):
row_key = object()
partial_row_data1 = self._makeOne(row_key)
partial_row_data2 = self._makeOne(row_key)
self.assertEqual(partial_row_data1, partial_row_data2)
def test___eq__type_differ(self):
partial_row_data1 = self._makeOne(None)
partial_row_data2 = object()
self.assertNotEqual(partial_row_data1, partial_row_data2)
def test___ne__same_value(self):
row_key = object()
partial_row_data1 = self._makeOne(row_key)
partial_row_data2 = self._makeOne(row_key)
comparison_val = (partial_row_data1 != partial_row_data2)
self.assertFalse(comparison_val)
def test___ne__(self):
row_key1 = object()
partial_row_data1 = self._makeOne(row_key1)
row_key2 = object()
partial_row_data2 = self._makeOne(row_key2)
self.assertNotEqual(partial_row_data1, partial_row_data2)
def test___ne__cells(self):
row_key = object()
partial_row_data1 = self._makeOne(row_key)
partial_row_data1._cells = object()
partial_row_data2 = self._makeOne(row_key)
self.assertNotEqual(partial_row_data1, partial_row_data2)
def test_to_dict(self):
cell1 = object()
cell2 = object()
cell3 = object()
family_name1 = u'name1'
family_name2 = u'name2'
qual1 = b'col1'
qual2 = b'col2'
qual3 = b'col3'
partial_row_data = self._makeOne(None)
partial_row_data._cells = {
family_name1: {
qual1: cell1,
qual2: cell2,
},
family_name2: {
qual3: cell3,
},
}
result = partial_row_data.to_dict()
expected_result = {
b'name1:col1': cell1,
b'name1:col2': cell2,
b'name2:col3': cell3,
}
self.assertEqual(result, expected_result)
def test_cells_property(self):
partial_row_data = self._makeOne(None)
cells = {1: 2}
partial_row_data._cells = cells
# Make sure we get a copy, not the original.
self.assertFalse(partial_row_data.cells is cells)
self.assertEqual(partial_row_data.cells, cells)
def test_row_key_getter(self):
row_key = object()
partial_row_data = self._makeOne(row_key)
self.assertTrue(partial_row_data.row_key is row_key)
class TestPartialRowsData(unittest2.TestCase):
def _getTargetClass(self):
from gcloud.bigtable.row_data import PartialRowsData
return PartialRowsData
def _getDoNothingClass(self):
klass = self._getTargetClass()
class FakePartialRowsData(klass):
def __init__(self, *args, **kwargs):
super(FakePartialRowsData, self).__init__(*args, **kwargs)
self._consumed = []
def consume_next(self):
value = self._response_iterator.next()
self._consumed.append(value)
return value
return FakePartialRowsData
def _makeOne(self, *args, **kwargs):
return self._getTargetClass()(*args, **kwargs)
def test_constructor(self):
response_iterator = object()
partial_rows_data = self._makeOne(response_iterator)
self.assertTrue(partial_rows_data._response_iterator
is response_iterator)
self.assertEqual(partial_rows_data._rows, {})
def test___eq__(self):
response_iterator = object()
partial_rows_data1 = self._makeOne(response_iterator)
partial_rows_data2 = self._makeOne(response_iterator)
self.assertEqual(partial_rows_data1, partial_rows_data2)
def test___eq__type_differ(self):
partial_rows_data1 = self._makeOne(None)
partial_rows_data2 = object()
self.assertNotEqual(partial_rows_data1, partial_rows_data2)
def test___ne__same_value(self):
response_iterator = object()
partial_rows_data1 = self._makeOne(response_iterator)
partial_rows_data2 = self._makeOne(response_iterator)
comparison_val = (partial_rows_data1 != partial_rows_data2)
self.assertFalse(comparison_val)
def test___ne__(self):
response_iterator1 = object()
partial_rows_data1 = self._makeOne(response_iterator1)
response_iterator2 = object()
partial_rows_data2 = self._makeOne(response_iterator2)
self.assertNotEqual(partial_rows_data1, partial_rows_data2)
def test_state_start(self):
prd = self._makeOne([])
self.assertEqual(prd.state, prd.START)
def test_state_new_row_w_row(self):
prd = self._makeOne([])
prd._last_scanned_row_key = ''
prd._row = object()
self.assertEqual(prd.state, prd.NEW_ROW)
def test_rows_getter(self):
partial_rows_data = self._makeOne(None)
partial_rows_data._rows = value = object()
self.assertTrue(partial_rows_data.rows is value)
def test_cancel(self):
response_iterator = _MockCancellableIterator()
partial_rows_data = self._makeOne(response_iterator)
self.assertEqual(response_iterator.cancel_calls, 0)
partial_rows_data.cancel()
self.assertEqual(response_iterator.cancel_calls, 1)
# 'consume_nest' tested via 'TestPartialRowsData_JSON_acceptance_tests'
def test_consume_all(self):
klass = self._getDoNothingClass()
value1, value2, value3 = object(), object(), object()
response_iterator = _MockCancellableIterator(value1, value2, value3)
partial_rows_data = klass(response_iterator)
self.assertEqual(partial_rows_data._consumed, [])
partial_rows_data.consume_all()
self.assertEqual(
partial_rows_data._consumed, [value1, value2, value3])
def test_consume_all_with_max_loops(self):
klass = self._getDoNothingClass()
value1, value2, value3 = object(), object(), object()
response_iterator = _MockCancellableIterator(value1, value2, value3)
partial_rows_data = klass(response_iterator)
self.assertEqual(partial_rows_data._consumed, [])
partial_rows_data.consume_all(max_loops=1)
self.assertEqual(partial_rows_data._consumed, [value1])
# Make sure the iterator still has the remaining values.
self.assertEqual(
list(response_iterator.iter_values), [value2, value3])
def test__copy_from_current_unset(self):
prd = self._makeOne([])
chunks = _generate_cell_chunks([''])
chunk = chunks[0]
prd._copy_from_current(chunk)
self.assertEqual(chunk.row_key, b'')
self.assertEqual(chunk.family_name.value, u'')
self.assertEqual(chunk.qualifier.value, b'')
self.assertEqual(chunk.timestamp_micros, 0)
self.assertEqual(chunk.labels, [])
def test__copy_from_current_blank(self):
ROW_KEY = b'RK'
FAMILY_NAME = u'A'
QUALIFIER = b'C'
TIMESTAMP_MICROS = 100
LABELS = ['L1', 'L2']
prd = self._makeOne([])
prd._cell = _PartialCellData()
chunks = _generate_cell_chunks([''])
chunk = chunks[0]
chunk.row_key = ROW_KEY
chunk.family_name.value = FAMILY_NAME
chunk.qualifier.value = QUALIFIER
chunk.timestamp_micros = TIMESTAMP_MICROS
chunk.labels.extend(LABELS)
prd._copy_from_current(chunk)
self.assertEqual(chunk.row_key, ROW_KEY)
self.assertEqual(chunk.family_name.value, FAMILY_NAME)
self.assertEqual(chunk.qualifier.value, QUALIFIER)
self.assertEqual(chunk.timestamp_micros, TIMESTAMP_MICROS)
self.assertEqual(chunk.labels, LABELS)
def test__copy_from_previous_unset(self):
prd = self._makeOne([])
cell = _PartialCellData()
prd._copy_from_previous(cell)
self.assertEqual(cell.row_key, '')
self.assertEqual(cell.family_name, u'')
self.assertEqual(cell.qualifier, b'')
self.assertEqual(cell.timestamp_micros, 0)
self.assertEqual(cell.labels, [])
def test__copy_from_previous_blank(self):
ROW_KEY = 'RK'
FAMILY_NAME = u'A'
QUALIFIER = b'C'
TIMESTAMP_MICROS = 100
LABELS = ['L1', 'L2']
prd = self._makeOne([])
cell = _PartialCellData(
row_key=ROW_KEY,
family_name=FAMILY_NAME,
qualifier=QUALIFIER,
timestamp_micros=TIMESTAMP_MICROS,
labels=LABELS,
)
prd._previous_cell = _PartialCellData()
prd._copy_from_previous(cell)
self.assertEqual(cell.row_key, ROW_KEY)
self.assertEqual(cell.family_name, FAMILY_NAME)
self.assertEqual(cell.qualifier, QUALIFIER)
self.assertEqual(cell.timestamp_micros, TIMESTAMP_MICROS)
self.assertEqual(cell.labels, LABELS)
def test__copy_from_previous_filled(self):
ROW_KEY = 'RK'
FAMILY_NAME = u'A'
QUALIFIER = b'C'
TIMESTAMP_MICROS = 100
LABELS = ['L1', 'L2']
prd = self._makeOne([])
prd._previous_cell = _PartialCellData(
row_key=ROW_KEY,
family_name=FAMILY_NAME,
qualifier=QUALIFIER,
timestamp_micros=TIMESTAMP_MICROS,
labels=LABELS,
)
cell = _PartialCellData()
prd._copy_from_previous(cell)
self.assertEqual(cell.row_key, ROW_KEY)
self.assertEqual(cell.family_name, FAMILY_NAME)
self.assertEqual(cell.qualifier, QUALIFIER)
self.assertEqual(cell.timestamp_micros, 0)
self.assertEqual(cell.labels, [])
def test__save_row_no_cell(self):
ROW_KEY = 'RK'
prd = self._makeOne([])
row = prd._row = _Dummy(row_key=ROW_KEY)
prd._cell = None
prd._save_current_row()
self.assertTrue(prd._rows[ROW_KEY] is row)
def test_invalid_last_scanned_row_key_on_start(self):
from gcloud.bigtable.row_data import InvalidReadRowsResponse
response = _ReadRowsResponseV2(chunks=(), last_scanned_row_key='ABC')
iterator = _MockCancellableIterator(response)
prd = self._makeOne(iterator)
with self.assertRaises(InvalidReadRowsResponse):
prd.consume_next()
def test_valid_last_scanned_row_key_on_start(self):
response = _ReadRowsResponseV2(
chunks=(), last_scanned_row_key='AFTER')
iterator = _MockCancellableIterator(response)
prd = self._makeOne(iterator)
prd._last_scanned_row_key = 'BEFORE'
prd.consume_next()
self.assertEqual(prd._last_scanned_row_key, 'AFTER')
def test_invalid_empty_chunk(self):
from gcloud.bigtable.row_data import InvalidChunk
chunks = _generate_cell_chunks([''])
response = _ReadRowsResponseV2(chunks)
iterator = _MockCancellableIterator(response)
prd = self._makeOne(iterator)
with self.assertRaises(InvalidChunk):
prd.consume_next()
def test_invalid_empty_second_chunk(self):
from gcloud.bigtable.row_data import InvalidChunk
chunks = _generate_cell_chunks(['', ''])
first = chunks[0]
first.row_key = b'RK'
first.family_name.value = 'A'
first.qualifier.value = b'C'
response = _ReadRowsResponseV2(chunks)
iterator = _MockCancellableIterator(response)
prd = self._makeOne(iterator)
with self.assertRaises(InvalidChunk):
prd.consume_next()
class TestPartialRowsData_JSON_acceptance_tests(unittest2.TestCase):
_json_tests = None
def _getTargetClass(self):
from gcloud.bigtable.row_data import PartialRowsData
return PartialRowsData
def _makeOne(self, *args, **kwargs):
return self._getTargetClass()(*args, **kwargs)
def _load_json_test(self, test_name):
import os
if self.__class__._json_tests is None:
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'read-rows-acceptance-test.json')
raw = _parse_readrows_acceptance_tests(filename)
tests = self.__class__._json_tests = {}
for (name, chunks, results) in raw:
tests[name] = chunks, results
return self.__class__._json_tests[test_name]
# JSON Error cases: invalid chunks
def _fail_during_consume(self, testcase_name):
from gcloud.bigtable.row_data import InvalidChunk
chunks, results = self._load_json_test(testcase_name)
response = _ReadRowsResponseV2(chunks)
iterator = _MockCancellableIterator(response)
prd = self._makeOne(iterator)
with self.assertRaises(InvalidChunk):
prd.consume_next()
expected_result = self._sort_flattend_cells(
[result for result in results if not result['error']])
flattened = self._sort_flattend_cells(_flatten_cells(prd))
self.assertEqual(flattened, expected_result)
def test_invalid_no_cell_key_before_commit(self):
self._fail_during_consume('invalid - no cell key before commit')
def test_invalid_no_cell_key_before_value(self):
self._fail_during_consume('invalid - no cell key before value')
def test_invalid_new_col_family_wo_qualifier(self):
self._fail_during_consume(
'invalid - new col family must specify qualifier')
def test_invalid_no_commit_between_rows(self):
self._fail_during_consume('invalid - no commit between rows')
def test_invalid_no_commit_after_first_row(self):
self._fail_during_consume('invalid - no commit after first row')
def test_invalid_duplicate_row_key(self):
self._fail_during_consume('invalid - duplicate row key')
def test_invalid_new_row_missing_row_key(self):
self._fail_during_consume('invalid - new row missing row key')
def test_invalid_bare_reset(self):
self._fail_during_consume('invalid - bare reset')
def test_invalid_bad_reset_no_commit(self):
self._fail_during_consume('invalid - bad reset, no commit')
def test_invalid_missing_key_after_reset(self):
self._fail_during_consume('invalid - missing key after reset')
def test_invalid_reset_with_chunk(self):
self._fail_during_consume('invalid - reset with chunk')
def test_invalid_commit_with_chunk(self):
self._fail_during_consume('invalid - commit with chunk')
# JSON Error cases: incomplete final row
def _sort_flattend_cells(self, flattened):
import operator
key_func = operator.itemgetter('rk', 'fm', 'qual')
return sorted(flattened, key=key_func)
def _incomplete_final_row(self, testcase_name):
chunks, results = self._load_json_test(testcase_name)
response = _ReadRowsResponseV2(chunks)
iterator = _MockCancellableIterator(response)
prd = self._makeOne(iterator)
prd.consume_next()
self.assertEqual(prd.state, prd.ROW_IN_PROGRESS)
expected_result = self._sort_flattend_cells(
[result for result in results if not result['error']])
flattened = self._sort_flattend_cells(_flatten_cells(prd))
self.assertEqual(flattened, expected_result)
def test_invalid_no_commit(self):
self._incomplete_final_row('invalid - no commit')
def test_invalid_last_row_missing_commit(self):
self._incomplete_final_row('invalid - last row missing commit')
# Non-error cases
_marker = object()
def _match_results(self, testcase_name, expected_result=_marker):
chunks, results = self._load_json_test(testcase_name)
response = _ReadRowsResponseV2(chunks)
iterator = _MockCancellableIterator(response)
prd = self._makeOne(iterator)
prd.consume_next()
flattened = self._sort_flattend_cells(_flatten_cells(prd))
if expected_result is self._marker:
expected_result = self._sort_flattend_cells(results)
self.assertEqual(flattened, expected_result)
def test_bare_commit_implies_ts_zero(self):
self._match_results('bare commit implies ts=0')
def test_simple_row_with_timestamp(self):
self._match_results('simple row with timestamp')
def test_missing_timestamp_implies_ts_zero(self):
self._match_results('missing timestamp, implied ts=0')
def test_empty_cell_value(self):
self._match_results('empty cell value')
def test_two_unsplit_cells(self):
self._match_results('two unsplit cells')
def test_two_qualifiers(self):
self._match_results('two qualifiers')
def test_two_families(self):
self._match_results('two families')
def test_with_labels(self):
self._match_results('with labels')
def test_split_cell_bare_commit(self):
self._match_results('split cell, bare commit')
def test_split_cell(self):
self._match_results('split cell')
def test_split_four_ways(self):
self._match_results('split four ways')
def test_two_split_cells(self):
self._match_results('two split cells')
def test_multi_qualifier_splits(self):
self._match_results('multi-qualifier splits')
def test_multi_qualifier_multi_split(self):
self._match_results('multi-qualifier multi-split')
def test_multi_family_split(self):
self._match_results('multi-family split')
def test_two_rows(self):
self._match_results('two rows')
def test_two_rows_implicit_timestamp(self):
self._match_results('two rows implicit timestamp')
def test_two_rows_empty_value(self):
self._match_results('two rows empty value')
def test_two_rows_one_with_multiple_cells(self):
self._match_results('two rows, one with multiple cells')
def test_two_rows_multiple_cells_multiple_families(self):
self._match_results('two rows, multiple cells, multiple families')
def test_two_rows_multiple_cells(self):
self._match_results('two rows, multiple cells')
def test_two_rows_four_cells_two_labels(self):
self._match_results('two rows, four cells, 2 labels')
def test_two_rows_with_splits_same_timestamp(self):
self._match_results('two rows with splits, same timestamp')
def test_no_data_after_reset(self):
# JSON testcase has `"results": null`
self._match_results('no data after reset', expected_result=[])
def test_simple_reset(self):
self._match_results('simple reset')
def test_reset_to_new_val(self):
self._match_results('reset to new val')
def test_reset_to_new_qual(self):
self._match_results('reset to new qual')
def test_reset_with_splits(self):
self._match_results('reset with splits')
def test_two_resets(self):
self._match_results('two resets')
def test_reset_to_new_row(self):
self._match_results('reset to new row')
def test_reset_in_between_chunks(self):
self._match_results('reset in between chunks')
def test_empty_cell_chunk(self):
self._match_results('empty cell chunk')
def _flatten_cells(prd):
# Match results format from JSON testcases.
# Doesn't handle error cases.
from gcloud._helpers import _bytes_to_unicode
from gcloud._helpers import _microseconds_from_datetime
for row_key, row in prd.rows.items():
for family_name, family in row.cells.items():
for qualifier, column in family.items():
for cell in column:
yield {
u'rk': _bytes_to_unicode(row_key),
u'fm': family_name,
u'qual': _bytes_to_unicode(qualifier),
u'ts': _microseconds_from_datetime(cell.timestamp),
u'value': _bytes_to_unicode(cell.value),
u'label': u' '.join(cell.labels),
u'error': False,
}
class _MockCancellableIterator(object):
cancel_calls = 0
def __init__(self, *values):
self.iter_values = iter(values)
def cancel(self):
self.cancel_calls += 1
def next(self):
return next(self.iter_values)
def __next__(self): # pragma: NO COVER Py3k
return self.next()
class _Dummy(object):
def __init__(self, **kw):
self.__dict__.update(kw)
class _PartialCellData(object):
row_key = ''
family_name = u''
qualifier = b''
timestamp_micros = 0
def __init__(self, **kw):
self.labels = kw.pop('labels', [])
self.__dict__.update(kw)
class _ReadRowsResponseV2(object):
def __init__(self, chunks, last_scanned_row_key=''):
self.chunks = chunks
self.last_scanned_row_key = last_scanned_row_key
def _generate_cell_chunks(chunk_text_pbs):
from google.protobuf.text_format import Merge
from gcloud.bigtable._generated_v2.bigtable_pb2 import ReadRowsResponse
chunks = []
for chunk_text_pb in chunk_text_pbs:
chunk = ReadRowsResponse.CellChunk()
chunks.append(Merge(chunk_text_pb, chunk))
return chunks
def _parse_readrows_acceptance_tests(filename):
"""Parse acceptance tests from JSON
See:
https://github.com/GoogleCloudPlatform/cloud-bigtable-client/blob/master/bigtable-client-core/src/test/resources/com/google/cloud/bigtable/grpc/scanner/v2/read-rows-acceptance-test.json
"""
import json
with open(filename) as json_file:
test_json = json.load(json_file)
for test in test_json['tests']:
name = test['name']
chunks = _generate_cell_chunks(test['chunks'])
results = test['results']
yield name, chunks, results