|
| 1 | +#!/usr/bin/env python |
| 2 | +# -*- encoding: utf-8 -*- |
| 3 | + |
| 4 | +# Copyright (c) 2002-2016 "Neo Technology," |
| 5 | +# Network Engine for Objects in Lund AB [http://neotechnology.com] |
| 6 | +# |
| 7 | +# This file is part of Neo4j. |
| 8 | +# |
| 9 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 10 | +# you may not use this file except in compliance with the License. |
| 11 | +# You may obtain a copy of the License at |
| 12 | +# |
| 13 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 14 | +# |
| 15 | +# Unless required by applicable law or agreed to in writing, software |
| 16 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 17 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 18 | +# See the License for the specific language governing permissions and |
| 19 | +# limitations under the License. |
| 20 | + |
| 21 | +import random |
| 22 | +import string |
| 23 | + |
| 24 | +from behave import * |
| 25 | + |
| 26 | +from neo4j.v1 import GraphDatabase |
| 27 | +from test.tck.tck_util import to_unicode, Type, send_string, send_parameters, string_to_type |
| 28 | + |
| 29 | +from neo4j.v1 import compat |
| 30 | +use_step_matcher("re") |
| 31 | + |
| 32 | + |
| 33 | +@given("A running database") |
| 34 | +def step_impl(context): |
| 35 | + send_string("RETURN 1") |
| 36 | + |
| 37 | + |
| 38 | +@given("a value (?P<input>.+) of type (?P<bolt_type>.+)") |
| 39 | +def step_impl(context, input, bolt_type): |
| 40 | + context.expected = get_bolt_value(string_to_type(bolt_type), input) |
| 41 | + |
| 42 | + |
| 43 | +@given("a value of type (?P<bolt_type>.+)") |
| 44 | +def step_impl(context, bolt_type): |
| 45 | + context.expected = get_bolt_value(string_to_type(bolt_type), u' ') |
| 46 | + |
| 47 | + |
| 48 | +@given("a list value (?P<input>.+) of type (?P<bolt_type>.+)") |
| 49 | +def step_impl(context, input, bolt_type): |
| 50 | + context.expected = get_list_from_feature_file(input, string_to_type(bolt_type)) |
| 51 | + |
| 52 | + |
| 53 | +@given("an empty list L") |
| 54 | +def step_impl(context): |
| 55 | + context.L = [] |
| 56 | + |
| 57 | + |
| 58 | +@given("an empty map M") |
| 59 | +def step_impl(context): |
| 60 | + context.M = {} |
| 61 | + |
| 62 | + |
| 63 | +@given("a String of size (?P<size>\d+)") |
| 64 | +def step_impl(context, size): |
| 65 | + context.expected = get_random_string(int(size)) |
| 66 | + |
| 67 | + |
| 68 | +@given("a List of size (?P<size>\d+) and type (?P<type>.+)") |
| 69 | +def step_impl(context, size, type): |
| 70 | + context.expected = get_list_of_random_type(int(size), string_to_type(type)) |
| 71 | + |
| 72 | + |
| 73 | +@given("a Map of size (?P<size>\d+) and type (?P<type>.+)") |
| 74 | +def step_impl(context, size, type): |
| 75 | + context.expected = get_dict_of_random_type(int(size), string_to_type(type)) |
| 76 | + |
| 77 | + |
| 78 | +@step("adding a table of lists to the list L") |
| 79 | +def step_impl(context): |
| 80 | + for row in context.table: |
| 81 | + context.L.append(get_list_from_feature_file(row[1], row[0])) |
| 82 | + |
| 83 | + |
| 84 | +@step("adding a table of values to the list L") |
| 85 | +def step_impl(context): |
| 86 | + for row in context.table: |
| 87 | + context.L.append(get_bolt_value(row[0], row[1])) |
| 88 | + |
| 89 | + |
| 90 | +@step("adding a table of values to the map M") |
| 91 | +def step_impl(context): |
| 92 | + for row in context.table: |
| 93 | + context.M['a%d' % len(context.M)] = get_bolt_value(row[0], row[1]) |
| 94 | + |
| 95 | + |
| 96 | +@step("adding map M to list L") |
| 97 | +def step_impl(context): |
| 98 | + context.L.append(context.M) |
| 99 | + |
| 100 | + |
| 101 | +@when("adding a table of lists to the map M") |
| 102 | +def step_impl(context): |
| 103 | + for row in context.table: |
| 104 | + context.M['a%d' % len(context.M)] = get_list_from_feature_file(row[1], row[0]) |
| 105 | + |
| 106 | + |
| 107 | +@step("adding a copy of map M to map M") |
| 108 | +def step_impl(context): |
| 109 | + context.M['a%d' % len(context.M)] = context.M.copy() |
| 110 | + |
| 111 | + |
| 112 | +@when("the driver asks the server to echo this value back") |
| 113 | +def step_impl(context): |
| 114 | + context.results = {"as_string": send_string("RETURN " + as_cypher_text(context.expected)), |
| 115 | + "as_parameters": send_parameters("RETURN {input}", {'input': context.expected})} |
| 116 | + |
| 117 | + |
| 118 | +@when("the driver asks the server to echo this list back") |
| 119 | +def step_impl(context): |
| 120 | + context.expected = context.L |
| 121 | + context.results = {"as_string": send_string("RETURN " + as_cypher_text(context.expected)), |
| 122 | + "as_parameters": send_parameters("RETURN {input}", {'input': context.expected})} |
| 123 | + |
| 124 | + |
| 125 | +@when("the driver asks the server to echo this map back") |
| 126 | +def step_impl(context): |
| 127 | + context.expected = context.M |
| 128 | + context.results = {"as_string": send_string("RETURN " + as_cypher_text(context.expected)), |
| 129 | + "as_parameters": send_parameters("RETURN {input}", {'input': context.expected})} |
| 130 | + |
| 131 | + |
| 132 | +@step("the value given in the result should be the same as what was sent") |
| 133 | +def step_impl(context): |
| 134 | + assert len(context.results) > 0 |
| 135 | + for result in context.results.values(): |
| 136 | + result_value = result[0].values()[0] |
| 137 | + assert result_value == context.expected |
| 138 | + |
| 139 | + |
| 140 | +@given("A driver containing a session pool of size (?P<size>\d+)") |
| 141 | +def step_impl(context, size): |
| 142 | + context.driver = GraphDatabase.driver("bolt://localhost", max_pool_size=1) |
| 143 | + |
| 144 | + |
| 145 | +@when("acquiring a session from the driver") |
| 146 | +def step_impl(context): |
| 147 | + context.session = context.driver.session() |
| 148 | + |
| 149 | + |
| 150 | +@step('with the session running the Cypher statement "(?P<statement>.+)"') |
| 151 | +def step_impl(context, statement): |
| 152 | + context.cursor = context.session.run(statement) |
| 153 | + |
| 154 | + |
| 155 | +@step("pulling the result records") |
| 156 | +def step_impl(context): |
| 157 | + context.cursor.consume() |
| 158 | + |
| 159 | + |
| 160 | +@then("acquiring a session from the driver should not be possible") |
| 161 | +def step_impl(context): |
| 162 | + try: |
| 163 | + context.session = context.driver.session() |
| 164 | + except: |
| 165 | + assert True |
| 166 | + else: |
| 167 | + assert False |
| 168 | + |
| 169 | + |
| 170 | +@then("acquiring a session from the driver should be possible") |
| 171 | +def step_impl(context): |
| 172 | + _ = context.driver.session() |
| 173 | + assert True |
| 174 | + |
| 175 | + |
| 176 | +def get_bolt_value(type, value): |
| 177 | + if type == Type.INTEGER: |
| 178 | + return int(value) |
| 179 | + if type == Type.FLOAT: |
| 180 | + return float(value) |
| 181 | + if type == Type.STRING: |
| 182 | + return to_unicode(value) |
| 183 | + if type == Type.NULL: |
| 184 | + return None |
| 185 | + if type == Type.BOOLEAN: |
| 186 | + return bool(value) |
| 187 | + raise ValueError('No such type : %s' % type) |
| 188 | + |
| 189 | + |
| 190 | +def as_cypher_text(expected): |
| 191 | + if expected is None: |
| 192 | + return "Null" |
| 193 | + if isinstance(expected, (str, compat.string)): |
| 194 | + return '"' + expected + '"' |
| 195 | + if isinstance(expected, float): |
| 196 | + return repr(expected).replace('+', '') |
| 197 | + if isinstance(expected, list): |
| 198 | + l = u'[' |
| 199 | + for i, val in enumerate(expected): |
| 200 | + l += as_cypher_text(val) |
| 201 | + if i < len(expected) - 1: |
| 202 | + l += u',' |
| 203 | + l += u']' |
| 204 | + return l |
| 205 | + if isinstance(expected, dict): |
| 206 | + d = u'{' |
| 207 | + for i, (key, val) in enumerate(expected.items()): |
| 208 | + d += to_unicode(key) + ':' |
| 209 | + d += as_cypher_text(val) |
| 210 | + if i < len(expected.items()) - 1: |
| 211 | + d += u',' |
| 212 | + d += u'}' |
| 213 | + return d |
| 214 | + else: |
| 215 | + return to_unicode(expected) |
| 216 | + |
| 217 | + |
| 218 | +def get_list_from_feature_file(string_list, bolt_type): |
| 219 | + inputs = string_list.strip('[]') |
| 220 | + inputs = inputs.split(',') |
| 221 | + list_to_return = [] |
| 222 | + for value in inputs: |
| 223 | + list_to_return.append(get_bolt_value(bolt_type, value)) |
| 224 | + return list_to_return |
| 225 | + |
| 226 | + |
| 227 | +def get_random_string(size): |
| 228 | + return u''.join( |
| 229 | + random.SystemRandom().choice(list(string.ascii_uppercase + string.digits + string.ascii_lowercase)) for _ in |
| 230 | + range(size)) |
| 231 | + |
| 232 | + |
| 233 | +def get_random_bool(): |
| 234 | + return bool(random.randint(0, 1)) |
| 235 | + |
| 236 | + |
| 237 | +def _get_random_func(type): |
| 238 | + def get_none(): |
| 239 | + return None |
| 240 | + |
| 241 | + if type == Type.INTEGER: |
| 242 | + fu = random.randint |
| 243 | + args = [-9223372036854775808, 9223372036854775808] |
| 244 | + elif type == Type.FLOAT: |
| 245 | + fu = random.random |
| 246 | + args = [] |
| 247 | + elif type == Type.STRING: |
| 248 | + fu = get_random_string |
| 249 | + args = [3] |
| 250 | + elif type == Type.NULL: |
| 251 | + fu = get_none |
| 252 | + args = [] |
| 253 | + elif type == Type.BOOLEAN: |
| 254 | + fu = get_random_bool |
| 255 | + args = [] |
| 256 | + else: |
| 257 | + raise ValueError('No such type : %s' % type) |
| 258 | + return (fu, args) |
| 259 | + |
| 260 | + |
| 261 | +def get_list_of_random_type(size, type): |
| 262 | + fu, args = _get_random_func(type) |
| 263 | + return [fu(*args) for _ in range(size)] |
| 264 | + |
| 265 | + |
| 266 | +def get_dict_of_random_type(size, type): |
| 267 | + fu, args = _get_random_func(type) |
| 268 | + return {'a%d' % i: fu(*args) for i in range(size)} |
0 commit comments