From a101964fea7ecced2332c7ee1c4880687de4b652 Mon Sep 17 00:00:00 2001 From: Danny Hermes Date: Thu, 25 Feb 2016 16:21:38 -0800 Subject: [PATCH] Implementing basic HappyBase system test. Also in the process modifying Bigtable Client.copy() since the crypto signer objects used in ServiceAccountCredentials can't be copied (cffi won't allow it). --- gcloud/bigtable/client.py | 5 +- gcloud/bigtable/test_client.py | 1 - system_tests/bigtable_happybase.py | 113 +++++++++++++++++++++++++++++ system_tests/run_system_test.py | 3 + 4 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 system_tests/bigtable_happybase.py diff --git a/gcloud/bigtable/client.py b/gcloud/bigtable/client.py index 381d9d88b85a..2913feaa68c3 100644 --- a/gcloud/bigtable/client.py +++ b/gcloud/bigtable/client.py @@ -27,8 +27,6 @@ """ -import copy - from grpc.beta import implementations from gcloud.bigtable._generated import bigtable_cluster_data_pb2 as data_pb2 @@ -168,7 +166,8 @@ def copy(self): :rtype: :class:`.Client` :returns: A copy of the current client. """ - copied_creds = copy.deepcopy(self._credentials) + credentials = self._credentials + copied_creds = credentials.create_scoped(credentials.scopes) return self.__class__( self.project, copied_creds, diff --git a/gcloud/bigtable/test_client.py b/gcloud/bigtable/test_client.py index 71ce61e51615..1516297b5cba 100644 --- a/gcloud/bigtable/test_client.py +++ b/gcloud/bigtable/test_client.py @@ -129,7 +129,6 @@ def _copy_test_helper(self, read_only=False, admin=False): new_client = client.copy() self.assertEqual(new_client._admin, client._admin) self.assertEqual(new_client._credentials, client._credentials) - self.assertFalse(new_client._credentials is client._credentials) self.assertEqual(new_client.project, client.project) self.assertEqual(new_client.user_agent, client.user_agent) self.assertEqual(new_client.timeout_seconds, client.timeout_seconds) diff --git a/system_tests/bigtable_happybase.py b/system_tests/bigtable_happybase.py new file mode 100644 index 000000000000..06f6dcf4d8b8 --- /dev/null +++ b/system_tests/bigtable_happybase.py @@ -0,0 +1,113 @@ +# 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 time + +import unittest2 + +from gcloud import _helpers +from gcloud.bigtable import client as client_mod +from gcloud.bigtable.happybase.connection import Connection +from gcloud.environment_vars import TESTS_PROJECT + + +_helpers.PROJECT = TESTS_PROJECT +ZONE = 'us-central1-c' +NOW_MILLIS = int(1000 * time.time()) +CLUSTER_ID = 'gcloud-python-%d' % (NOW_MILLIS,) +TABLE_NAME = 'table-name' +ALT_TABLE_NAME = 'other-table' +TTL_FOR_TEST = 3 +COL_FAM1 = 'cf1' +COL_FAM2 = 'cf2' +COL_FAM3 = 'cf3' +FAMILIES = { + COL_FAM1: {'max_versions': 10}, + COL_FAM2: {'max_versions': 1, 'time_to_live': TTL_FOR_TEST}, + COL_FAM3: {}, # use defaults +} + + +class Config(object): + """Run-time configuration to be modified at set-up. + + This is a mutable stand-in to allow test set-up to modify + global state. + """ + CONNECTION = None + TABLE = None + + +def _operation_wait(operation, max_attempts=5): + """Wait until an operation has completed. + + :type operation: :class:`gcloud.bigtable.cluster.Operation` + :param operation: Operation that has not finished. + + :type max_attempts: int + :param max_attempts: (Optional) The maximum number of times to check if + the operation has finished. Defaults to 5. + """ + total_sleep = 0 + while not operation.finished(): + if total_sleep > max_attempts: + return False + time.sleep(1) + total_sleep += 1 + + return True + + +def set_connection(): + client = client_mod.Client(admin=True) + cluster = client.cluster(ZONE, CLUSTER_ID) + client.start() + operation = cluster.create() + if not _operation_wait(operation): + raise RuntimeError('Cluster creation exceed 5 seconds.') + Config.CONNECTION = Connection(cluster=cluster) + + +def setUpModule(): + set_connection() + Config.CONNECTION.create_table(TABLE_NAME, FAMILIES) + Config.TABLE = Config.CONNECTION.table(TABLE_NAME) + + +def tearDownModule(): + Config.CONNECTION.delete_table(TABLE_NAME) + Config.CONNECTION._cluster.delete() + Config.CONNECTION.close() + + +class TestConnection(unittest2.TestCase): + + def test_create_and_delete_table(self): + connection = Config.CONNECTION + + self.assertFalse(ALT_TABLE_NAME in connection.tables()) + connection.create_table(ALT_TABLE_NAME, {COL_FAM1: {}}) + self.assertTrue(ALT_TABLE_NAME in connection.tables()) + connection.delete_table(ALT_TABLE_NAME) + self.assertFalse(ALT_TABLE_NAME in connection.tables()) + + def test_create_table_failure(self): + connection = Config.CONNECTION + + self.assertFalse(ALT_TABLE_NAME in connection.tables()) + empty_families = {} + with self.assertRaises(ValueError): + connection.create_table(ALT_TABLE_NAME, empty_families) + self.assertFalse(ALT_TABLE_NAME in connection.tables()) diff --git a/system_tests/run_system_test.py b/system_tests/run_system_test.py index 7c42cad88322..317a4cd8ab89 100644 --- a/system_tests/run_system_test.py +++ b/system_tests/run_system_test.py @@ -20,6 +20,7 @@ # repository root is the current directory. import bigquery import bigtable +import bigtable_happybase import datastore import pubsub import storage @@ -32,6 +33,7 @@ 'pubsub': ['project', 'credentials'], 'bigquery': ['project', 'credentials'], 'bigtable': ['project', 'credentials'], + 'bigtable-happybase': ['project', 'credentials'], } TEST_MODULES = { 'datastore': datastore, @@ -39,6 +41,7 @@ 'pubsub': pubsub, 'bigquery': bigquery, 'bigtable': bigtable, + 'bigtable-happybase': bigtable_happybase, }