Return-Path: X-Original-To: apmail-cassandra-commits-archive@www.apache.org Delivered-To: apmail-cassandra-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E46E717986 for ; Tue, 7 Apr 2015 22:24:01 +0000 (UTC) Received: (qmail 3983 invoked by uid 500); 7 Apr 2015 22:23:53 -0000 Delivered-To: apmail-cassandra-commits-archive@cassandra.apache.org Received: (qmail 3947 invoked by uid 500); 7 Apr 2015 22:23:53 -0000 Mailing-List: contact commits-help@cassandra.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cassandra.apache.org Delivered-To: mailing list commits@cassandra.apache.org Received: (qmail 3932 invoked by uid 99); 7 Apr 2015 22:23:53 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 07 Apr 2015 22:23:53 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 71AEFE1844; Tue, 7 Apr 2015 22:23:53 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: tylerhobbs@apache.org To: commits@cassandra.apache.org Message-Id: <7c2def927d2a4c22b1905e546421f955@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: cassandra git commit: cqlsh: Add tests for INSERT, UPDATE tab completion Date: Tue, 7 Apr 2015 22:23:53 +0000 (UTC) Repository: cassandra Updated Branches: refs/heads/cassandra-2.1 cb8cb5f99 -> 879691dd3 cqlsh: Add tests for INSERT, UPDATE tab completion Patch by Jim Witschey; reviewed by Tyler Hobbs for CASSANDRA-9125 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/879691dd Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/879691dd Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/879691dd Branch: refs/heads/cassandra-2.1 Commit: 879691dd3546230690835899afb0ff0ce8905eb0 Parents: cb8cb5f Author: Jim Witschey Authored: Tue Apr 7 17:23:11 2015 -0500 Committer: Tyler Hobbs Committed: Tue Apr 7 17:23:11 2015 -0500 ---------------------------------------------------------------------- CHANGES.txt | 1 + pylib/cqlshlib/test/test_cqlsh_completion.py | 299 ++++++++++++++++++++-- pylib/cqlshlib/test/test_keyspace_init.cql | 36 ++- 3 files changed, 290 insertions(+), 46 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/879691dd/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 69f96ba..5cf621d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 2.1.5 + * cqlsh: Add tests for INSERT and UPDATE tab completion (CASSANDRA-9125) * cqlsh: quote column names when needed in COPY FROM inserts (CASSANDRA-9080) * Add generate-idea-files target to build.xml (CASSANDRA-9123) * Do not load read meter for offline operations (CASSANDRA-9082) http://git-wip-us.apache.org/repos/asf/cassandra/blob/879691dd/pylib/cqlshlib/test/test_cqlsh_completion.py ---------------------------------------------------------------------- diff --git a/pylib/cqlshlib/test/test_cqlsh_completion.py b/pylib/cqlshlib/test/test_cqlsh_completion.py index 820414d..2d22a63 100644 --- a/pylib/cqlshlib/test/test_cqlsh_completion.py +++ b/pylib/cqlshlib/test/test_cqlsh_completion.py @@ -43,7 +43,61 @@ class CqlshCompletionCase(BaseTestCase): def tearDown(self): self.cqlsh_runner.__exit__(None, None, None) - def _trycompletions_inner(self, inputstring, immediate='', choices=(), other_choices_ok=False): + def _get_completions(self, inputstring, split_completed_lines=True): + """ + Get results of tab completion in cqlsh. Returns a bare string if a + string completes immediately. Otherwise, returns a set of all + whitespace-separated tokens in the offered completions by default, or a + list of the lines in the offered completions if split_completed_lines is + False. + """ + self.cqlsh.send(inputstring) + self.cqlsh.send(TAB) + immediate = self.cqlsh.read_up_to_timeout(COMPLETION_RESPONSE_TIME) + immediate = immediate.replace(' \b', '') + self.assertEqual(immediate[:len(inputstring)], inputstring) + immediate = immediate[len(inputstring):] + immediate = immediate.replace(BEL, '') + + if immediate: + return immediate + + self.cqlsh.send(TAB) + choice_output = self.cqlsh.read_up_to_timeout(COMPLETION_RESPONSE_TIME) + if choice_output == BEL: + choice_output = '' + + self.cqlsh.send(CTRL_C) # cancel any current line + self.cqlsh.read_to_next_prompt() + + choice_lines = choice_output.splitlines() + if choice_lines: + # ensure the last line of the completion is the prompt + prompt_regex = self.cqlsh.prompt.lstrip() + re.escape(inputstring) + msg = ('Double-tab completion ' + 'does not print prompt for input "{}"'.format(inputstring)) + self.assertRegexpMatches(choice_lines[-1], prompt_regex, msg=msg) + + choice_lines = [line.strip() for line in choice_lines[:-1]] + choice_lines = [line for line in choice_lines if line] + + if split_completed_lines: + completed_lines = map(set, (completion_separation_re.split(line.strip()) + for line in choice_lines)) + + if not completed_lines: + return set() + + completed_tokens = set.union(*completed_lines) + return completed_tokens - {''} + else: + return choice_lines + + assert False + + def _trycompletions_inner(self, inputstring, immediate='', choices=(), + other_choices_ok=False, + split_completed_lines=True): """ Test tab completion in cqlsh. Enters in the text in inputstring, then simulates a tab keypress to see what is immediately completed (this @@ -53,37 +107,25 @@ class CqlshCompletionCase(BaseTestCase): is simulated in order to get a list of choices, which are expected to match the items in 'choices' (order is not important, but case is). """ - self.cqlsh.send(inputstring) - self.cqlsh.send(TAB) - completed = self.cqlsh.read_up_to_timeout(COMPLETION_RESPONSE_TIME) - completed = completed.replace(' \b', '') - self.assertEqual(completed[:len(inputstring)], inputstring) - completed = completed[len(inputstring):] - completed = completed.replace(BEL, '') - self.assertEqual(completed, immediate, 'cqlsh completed %r, but we expected %r' - % (completed, immediate)) + completed = self._get_completions(inputstring, + split_completed_lines=split_completed_lines) + if immediate: + msg = 'cqlsh completed %r, but we expected %r' % (completed, immediate) + self.assertEqual(completed, immediate, msg=msg) return - self.cqlsh.send(TAB) - choice_output = self.cqlsh.read_up_to_timeout(COMPLETION_RESPONSE_TIME) - if choice_output == BEL: - lines = () - else: - lines = choice_output.splitlines() - self.assertRegexpMatches(lines[-1], self.cqlsh.prompt.lstrip() + re.escape(inputstring)) - choicesseen = set() - for line in lines[:-1]: - choicesseen.update(completion_separation_re.split(line.strip())) - choicesseen.discard('') if other_choices_ok: - self.assertEqual(set(choices), choicesseen.intersection(choices)) + self.assertEqual(set(choices), completed.intersection(choices)) else: - self.assertEqual(set(choices), choicesseen) + self.assertEqual(set(choices), set(completed)) - def trycompletions(self, inputstring, immediate='', choices=(), other_choices_ok=False): + def trycompletions(self, inputstring, immediate='', choices=(), + other_choices_ok=False, split_completed_lines=True): try: - self._trycompletions_inner(inputstring, immediate, choices, other_choices_ok) + self._trycompletions_inner(inputstring, immediate, choices, + other_choices_ok=other_choices_ok, + split_completed_lines=split_completed_lines) finally: self.cqlsh.send(CTRL_C) # cancel any current line self.cqlsh.read_to_next_prompt() @@ -114,10 +156,213 @@ class TestCqlshCompletion(CqlshCompletionCase): pass def test_complete_in_insert(self): - pass + self.trycompletions('INSERT INTO ', + choices=('twenty_rows_table', + 'ascii_with_special_chars', + 'users', + 'has_all_types', + 'system.', + 'system_auth.', + 'empty_composite_table', + 'empty_table', + 'undefined_values_table', + 'dynamic_columns', + 'twenty_rows_composite_table', + 'utf8_with_special_chars', + 'system_traces.', + 'songs'), + other_choices_ok=True) + self.trycompletions('INSERT INTO twenty_rows_composite_table', + immediate=' ') + self.trycompletions('INSERT INTO twenty_rows_composite_table ', + choices=['(', 'JSON']) + self.trycompletions('INSERT INTO twenty_rows_composite_table (a, b ', + choices=(')', ',')) + self.trycompletions('INSERT INTO twenty_rows_composite_table (a, b, ', + immediate='c ') + self.trycompletions('INSERT INTO twenty_rows_composite_table (a, b, c ', + choices=(',', ')')) + self.trycompletions('INSERT INTO twenty_rows_composite_table (a, b)', + immediate=' VALUES ( ') + self.trycompletions('INSERT INTO twenty_rows_composite_table (a, b, c) VAL', + immediate='UES ( ') + + self.trycompletions( + 'INSERT INTO twenty_rows_composite_table (a, b, c) VALUES (', + [''], + split_completed_lines=False) + + self.trycompletions( + "INSERT INTO twenty_rows_composite_table (a, b, c) VALUES ('", + [''], + split_completed_lines=False) + + self.trycompletions( + "INSERT INTO twenty_rows_composite_table (a, b, c) VALUES ( 'eggs", + [''], + split_completed_lines=False) + + self.trycompletions( + "INSERT INTO twenty_rows_composite_table (a, b, c) VALUES ('eggs'", + immediate=', ') + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs',"), + [''], + split_completed_lines=False) + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam')"), + immediate=' ') + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') "), + choices=[';', 'USING', 'IF']) + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam');"), + choices=['?', 'ALTER', 'BEGIN', 'CAPTURE', 'CONSISTENCY', 'COPY', + 'CREATE', 'DEBUG', 'DELETE', 'DESC', 'DESCRIBE', 'DROP', + 'EXPAND', 'GRANT', 'HELP', 'INSERT', 'LIST', 'PAGING', + 'REVOKE', 'SELECT', 'SHOW', 'SOURCE', 'TRACING', + 'TRUNCATE', 'UPDATE', 'USE', 'exit', 'quit']) + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') US"), + immediate='ING T') + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') USING"), + immediate=' T') + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') USING T"), + choices=['TTL', 'TIMESTAMP']) + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') USING TT"), + immediate='L ') + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') USING TI"), + immediate='MESTAMP ') + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') USING TIMESTAMP "), + choices=['']) + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') USING TTL "), + choices=['']) + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') USING TIMESTAMP 0 "), + choices=['AND', ';']) + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') USING TTL 0 "), + choices=['AND', ';']) + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') USING TIMESTAMP 0 A"), + immediate='ND TTL ') + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') USING TTL 0 A"), + immediate='ND TIMESTAMP ') + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') USING TTL 0 AND TIMESTAMP "), + choices=['']) + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') USING TTL 0 AND TIMESTAMP 0 "), + choices=['AND', ';']) + + self.trycompletions( + ("INSERT INTO twenty_rows_composite_table (a, b, c) " + "VALUES ( 'eggs', 'sausage', 'spam') USING TTL 0 AND TIMESTAMP 0 AND "), + choices=[]) + def test_complete_in_update(self): - pass + self.trycompletions("UPD", immediate="ATE ") + self.trycompletions("UPDATE ", + choices=['twenty_rows_table', 'system_auth.', + 'users', 'has_all_types', 'system.', + 'ascii_with_special_chars', + 'empty_composite_table', 'empty_table', + 'undefined_values_table', + 'dynamic_columns', + 'twenty_rows_composite_table', + 'utf8_with_special_chars', 'ks.', + 'system_traces.', 'songs'], + other_choices_ok=True) + + self.trycompletions("UPDATE empty_table ", choices=['USING', 'SET']) + + self.trycompletions("UPDATE empty_table S", + immediate='ET lonelycol = ') + self.trycompletions("UPDATE empty_table SET lon", + immediate='elycol = ') + self.trycompletions("UPDATE empty_table SET lonelycol", + immediate=' = ') + + self.trycompletions("UPDATE empty_table U", immediate='SING T') + self.trycompletions("UPDATE empty_table USING T", + choices=["TTL", "TIMESTAMP"]) + + self.trycompletions("UPDATE empty_table SET lonelycol = ", + choices=[''], + split_completed_lines=False) + + self.trycompletions("UPDATE empty_table SET lonelycol = 'eg", + choices=[''], + split_completed_lines=False) + self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs'", + choices=[',', 'WHERE']) + self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE ", + choices=['TOKEN(', '', '']) + self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE ", + choices=['TOKEN(', '', '']) + + self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE lonel", + choices=['', '']) + self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE lonelykey ", + choices=['=', '<=', '>=', '>', '<', 'CONTAINS', 'IN', '[']) + self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE lonelykey = 0.0 ", + choices=['AND', 'IF', ';']) + self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE lonelykey = 0.0 AND ", + choices=['TOKEN(', '', '']) + + self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE TOKEN(lonelykey ", + choices=[',', ')']) + self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE TOKEN(lonelykey) ", + choices=['=', '<=', '>=', '<', '>']) + self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE TOKEN(lonelykey) <= TOKEN(13) ", + choices=[';', 'AND', 'IF']) + self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE TOKEN(lonelykey) <= TOKEN(13) IF ", + choices=['EXISTS', '', '']) + + self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE TOKEN(lonelykey) <= TOKEN(13) IF EXISTS ", + choices=['>=', '!=', '<=', 'IN', '[', ';', '=', '<', '>']) def test_complete_in_delete(self): pass http://git-wip-us.apache.org/repos/asf/cassandra/blob/879691dd/pylib/cqlshlib/test/test_keyspace_init.cql ---------------------------------------------------------------------- diff --git a/pylib/cqlshlib/test/test_keyspace_init.cql b/pylib/cqlshlib/test/test_keyspace_init.cql index 1d1e5aa..542721a 100644 --- a/pylib/cqlshlib/test/test_keyspace_init.cql +++ b/pylib/cqlshlib/test/test_keyspace_init.cql @@ -5,12 +5,10 @@ CREATE TABLE has_all_types ( bigintcol bigint, blobcol blob, booleancol boolean, - datecol date, decimalcol decimal, doublecol double, floatcol float, textcol text, - timecol time, timestampcol timestamp, uuidcol uuid, varcharcol varchar, @@ -18,34 +16,34 @@ CREATE TABLE has_all_types ( ) WITH compression = {'sstable_compression':'LZ4Compressor'}; INSERT INTO has_all_types (num, intcol, asciicol, bigintcol, blobcol, booleancol, - datecol, decimalcol, doublecol, floatcol, textcol, - timecol, timestampcol, uuidcol, varcharcol, varintcol) + decimalcol, doublecol, floatcol, textcol, + timestampcol, uuidcol, varcharcol, varintcol) VALUES (0, -12, 'abcdefg', 1234567890123456789, 0x000102030405fffefd, true, - '2001-07-13', 19952.11882, 1.0, -2.1, 'Voilá!', - '23:12:15.889445123', '2012-05-14 12:53:20+0000', bd1924e1-6af8-44ae-b5e1-f24131dbd460, '"', 10000000000000000000000000); + 19952.11882, 1.0, -2.1, 'Voilá!', + '2012-05-14 12:53:20+0000', bd1924e1-6af8-44ae-b5e1-f24131dbd460, '"', 10000000000000000000000000); INSERT INTO has_all_types (num, intcol, asciicol, bigintcol, blobcol, booleancol, - datecol, decimalcol, doublecol, floatcol, textcol, - timecol, timestampcol, uuidcol, varcharcol, varintcol) + decimalcol, doublecol, floatcol, textcol, + timestampcol, uuidcol, varcharcol, varintcol) VALUES (1, 2147483647, '__!''$#@!~"', 9223372036854775807, 0xffffffffffffffffff, true, - '2012-11-30', 0.00000000000001, 9999999.999, 99999.99, '∭Ƕ⑮ฑ➳❏''', - '00:01:59.998994', '1900-01-01+0000', ffffffff-ffff-ffff-ffff-ffffffffffff, 'newline-> + 0.00000000000001, 9999999.999, 99999.99, '∭Ƕ⑮ฑ➳❏''', + '1900-01-01+0000', ffffffff-ffff-ffff-ffff-ffffffffffff, 'newline-> <-', 9); INSERT INTO has_all_types (num, intcol, asciicol, bigintcol, blobcol, booleancol, - datecol, decimalcol, doublecol, floatcol, textcol, - timecol, timestampcol, uuidcol, varcharcol, varintcol) + decimalcol, doublecol, floatcol, textcol, + timestampcol, uuidcol, varcharcol, varintcol) VALUES (2, 0, '', 0, 0x, false, - 0, 0.0, 0.0, 0.0, '', - '0:0:0.1', 0, 00000000-0000-0000-0000-000000000000, '', 0); + 0.0, 0.0, 0.0, '', + 0, 00000000-0000-0000-0000-000000000000, '', 0); INSERT INTO has_all_types (num, intcol, asciicol, bigintcol, blobcol, booleancol, - datecol, decimalcol, doublecol, floatcol, textcol, - timecol, timestampcol, uuidcol, varcharcol, varintcol) + decimalcol, doublecol, floatcol, textcol, + timestampcol, uuidcol, varcharcol, varintcol) VALUES (3, -2147483648, '''''''', -9223372036854775808, 0x80, false, - '9999-12-31', 10.0000000000000, -1004.10, 100000000.9, '龍馭鬱', - '23:59:59.999999999', '2038-01-19T03:14-1200', ffffffff-ffff-1fff-8fff-ffffffffffff, - '''', -10000000000000000000000000); + 10.0000000000000, -1004.10, 100000000.9, '龍馭鬱', + '2038-01-19T03:14-1200', ffffffff-ffff-1fff-8fff-ffffffffffff, + '''', -10000000000000000000000000); INSERT INTO has_all_types (num, intcol, asciicol, bigintcol, blobcol, booleancol, decimalcol, doublecol, floatcol, textcol,