this repo has no description
at trunk 304 lines 12 kB view raw
1#!/usr/bin/env python3 2# Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 3import array 4import sys 5import unittest 6from unittest.mock import Mock 7 8 9class ArrayTest(unittest.TestCase): 10 def test_new_with_bad_typecode_raises_value_error(self): 11 with self.assertRaises(ValueError) as context: 12 array.array.__new__(array.array, "c") 13 self.assertEqual( 14 str(context.exception), 15 "bad typecode (must be b, B, u, h, H, i, I, l, L, q, Q, f or d)", 16 ) 17 18 def test_new_with_non_str_typecode_raises_type_error(self): 19 with self.assertRaises(TypeError) as context: 20 array.array.__new__(array.array, b"not-string") 21 self.assertIn("must be a unicode character, not bytes", str(context.exception)) 22 23 def test_new_with_long_str_typecode_raises_type_error(self): 24 with self.assertRaises(TypeError) as context: 25 array.array.__new__(array.array, "too") 26 self.assertIn("must be a unicode character, not str", str(context.exception)) 27 28 def test_new_with_str_array_init_and_non_str_typecode_raises_type_error(self): 29 unicode_array = array.array("u") 30 31 with self.assertRaises(TypeError) as context: 32 array.array.__new__(array.array, "c", unicode_array) 33 self.assertEqual( 34 str(context.exception), 35 "cannot use a unicode array to initialize an array with typecode 'c'", 36 ) 37 38 def test_new_with_valid_typecode_returns_array(self): 39 byte_array = array.array("b") 40 self.assertEqual(byte_array.typecode, "b") 41 42 def test_new_with_array_subtype_returns_subtype(self): 43 class ArraySub(array.array): 44 pass 45 46 array_sub = array.array.__new__(ArraySub, "B") 47 self.assertIsInstance(array_sub, ArraySub) 48 self.assertEqual(array_sub.typecode, "B") 49 50 def test_new_with_integer_typecode_and_non_number_raises_type_error(self): 51 with self.assertRaises(TypeError) as ctx: 52 array.array("i", ["not-a-number"]) 53 self.assertEqual(str(ctx.exception), "an integer is required (got type str)") 54 55 def test_new_with_integer_typecode_and_float_raises_type_error(self): 56 with self.assertRaises(TypeError) as ctx: 57 array.array("Q", [2.0]) 58 self.assertEqual(str(ctx.exception), "array item must be integer") 59 60 def test_new_with_integer_typecode_and_too_large_value_raises_overflow_error(self): 61 with self.assertRaises(OverflowError) as ctx: 62 array.array("b", [128]) 63 self.assertIn("greater than maximum", str(ctx.exception)) 64 65 def test_new_with_float_typecode_and_non_number_raises_type_error(self): 66 with self.assertRaises(TypeError) as ctx: 67 array.array("f", ["1"]) 68 self.assertEqual(str(ctx.exception), "must be real number, not str") 69 70 def test_new_with_list_stores_each_number_in_the_array(self): 71 int_array = array.array("i", [1, 2, 3]) 72 self.assertEqual(int_array[0], 1) 73 self.assertEqual(int_array[1], 2) 74 self.assertEqual(int_array[2], 3) 75 76 def test_new_with_tuple_stores_each_number_in_the_array(self): 77 int_array = array.array("d", (1.0, 2.0, 4.0)) 78 self.assertEqual(int_array[0], 1.0) 79 self.assertEqual(int_array[1], 2.0) 80 self.assertEqual(int_array[2], 4.0) 81 82 def test_new_with_iterable_stores_each_number_in_the_array(self): 83 class Iterator: 84 def __iter__(self): 85 return [1, 2, 3].__iter__() 86 87 int_array = array.array("b", Iterator()) 88 self.assertEqual(int_array[0], 1) 89 self.assertEqual(int_array[1], 2) 90 self.assertEqual(int_array[2], 3) 91 with self.assertRaises(IndexError) as ctx: 92 int_array[3] 93 self.assertEqual(str(ctx.exception), "array index out of range") 94 95 def test_new_with_float_typecode_and_list_calls_dunder_float_on_elements(self): 96 class FloatSub(float): 97 pass 98 99 class DunderFloat: 100 def __float__(self): 101 return 4.0 102 103 float_array = array.array("f", [1.0, FloatSub(2.0), DunderFloat()]) 104 self.assertEqual(float_array[0], 1.0) 105 self.assertEqual(type(float_array[0]), float) 106 self.assertEqual(float_array[1], 2.0) 107 self.assertEqual(type(float_array[1]), float) 108 self.assertEqual(float_array[2], 4.0) 109 self.assertEqual(type(float_array[2]), float) 110 111 def test_new_with_integer_typecode_and_list_calls_dunder_index_on_elements(self): 112 class IntSub(int): 113 pass 114 115 class DunderIndex: 116 def __index__(self): 117 return 8 118 119 int_array = array.array("i", [1, IntSub(4), DunderIndex()]) 120 self.assertEqual(int_array[0], 1) 121 self.assertEqual(type(int_array[0]), int) 122 self.assertEqual(int_array[1], 4) 123 self.assertEqual(type(int_array[1]), int) 124 self.assertEqual(int_array[2], 8) 125 self.assertEqual(type(int_array[2]), int) 126 127 def test_append_does_not_iterate_over_argument(self): 128 int_array = array.array("i") 129 with self.assertRaises(TypeError) as ctx: 130 int_array.append([0, 1]) 131 self.assertEqual(str(ctx.exception), "an integer is required (got type list)") 132 133 def test_append_grows_array(self): 134 int_array = array.array("i") 135 self.assertEqual(int_array.__len__(), 0) 136 int_array.append(1) 137 self.assertEqual(int_array.__len__(), 1) 138 int_array.append(2) 139 self.assertEqual(int_array.__len__(), 2) 140 self.assertEqual(int_array[0], 1) 141 self.assertEqual(int_array[1], 2) 142 143 def test_dunder_mul_with_str_raises_type_error(self): 144 int_array = array.array("i") 145 with self.assertRaises(TypeError) as ctx: 146 int_array.__mul__("hello") 147 self.assertEqual( 148 str(ctx.exception), "'str' object cannot be interpreted as an integer" 149 ) 150 151 def test_dunder_mul_with_subclass_returns_array(self): 152 class ArraySub(array.array): 153 pass 154 155 int_array = ArraySub("i", [1, 2, 3]) 156 new_array = int_array.__mul__(3) 157 self.assertEqual(int_array.__len__(), 3) 158 self.assertEqual(type(new_array), array.array) 159 self.assertEqual(new_array.__len__(), 9) 160 self.assertEqual(list(new_array), [1, 2, 3, 1, 2, 3, 1, 2, 3]) 161 162 def test_dunder_mul_with_maxsize_raises_memory_error(self): 163 int_array = array.array("i", [1, 2, 3]) 164 with self.assertRaises(MemoryError): 165 int_array.__mul__(sys.maxsize) 166 167 def test_dunder_mul_with_int_returns_array(self): 168 int_array = array.array("i", [1, 2, 3]) 169 new_array = int_array.__mul__(3) 170 self.assertEqual(int_array.__len__(), 3) 171 self.assertEqual(new_array.__len__(), 9) 172 self.assertEqual(list(new_array), [1, 2, 3, 1, 2, 3, 1, 2, 3]) 173 174 def test_dunder_mul_with_index_returns_array(self): 175 class Num: 176 def __index__(self): 177 return 3 178 179 num = Num() 180 int_array = array.array("i", [1, 2, 3]) 181 new_array = int_array.__mul__(num) 182 self.assertEqual(int_array.__len__(), 3) 183 self.assertEqual(new_array.__len__(), 9) 184 self.assertEqual(list(new_array), [1, 2, 3, 1, 2, 3, 1, 2, 3]) 185 186 def test_extend_with_iterable_can_resize_past_length_hint(self): 187 class Iterator: 188 def __length_hint__(self): 189 return 1 190 191 def __iter__(self): 192 return [1, 2, 3].__iter__() 193 194 int_array = array.array("b") 195 int_array.extend(Iterator()) 196 self.assertEqual(int_array[0], 1) 197 self.assertEqual(int_array[1], 2) 198 self.assertEqual(int_array[2], 3) 199 with self.assertRaises(IndexError) as ctx: 200 int_array[3] 201 self.assertEqual(str(ctx.exception), "array index out of range") 202 203 def test_extend_with_iterable_shorter_than_length_hint_resizes_to_iterable(self): 204 class Iterator: 205 def __length_hint__(self): 206 return 6 207 208 def __iter__(self): 209 return [1, 2, 3].__iter__() 210 211 int_array = array.array("b") 212 int_array.extend(Iterator()) 213 self.assertEqual(int_array[0], 1) 214 self.assertEqual(int_array[1], 2) 215 self.assertEqual(int_array[2], 3) 216 with self.assertRaises(IndexError) as ctx: 217 int_array[3] = 4 218 self.assertEqual(str(ctx.exception), "array assignment index out of range") 219 220 def test_subclass_will_call_array_setitem_on_initialization(self): 221 class ArraySub(array.array): 222 __setitem__ = Mock(name="__setitem__", return_value=None) 223 224 int_array = ArraySub("i", [3, 2, 1]) 225 self.assertEqual(int_array.__len__(), 3) 226 self.assertEqual(int_array[0], 3) 227 self.assertEqual(int_array[1], 2) 228 self.assertEqual(int_array[2], 1) 229 230 int_array[0] = 0 231 int_array.__setitem__.assert_called_once() 232 233 def test_getting_a_value_out_range_raises_index_error(self): 234 int_array = array.array("i", [1, 2, 3]) 235 with self.assertRaises(IndexError) as ctx: 236 int_array[5] 237 self.assertEqual(str(ctx.exception), "array index out of range") 238 239 def test_getting_a_negative_value_out_of_range_raises_index_error(self): 240 int_array = array.array("i", [1, 2, 3]) 241 with self.assertRaises(IndexError) as ctx: 242 int_array[-4] 243 self.assertEqual(str(ctx.exception), "array index out of range") 244 245 def test_getting_an_index_longer_than_word_raises_index_error(self): 246 int_array = array.array("i", [1, 2, 3]) 247 with self.assertRaises(IndexError) as ctx: 248 int_array[1 << 65] 249 self.assertEqual( 250 str(ctx.exception), "cannot fit 'int' into an index-sized integer" 251 ) 252 253 def test_getting_a_non_integer_index_raises_type_error(self): 254 int_array = array.array("i", [1, 2, 3]) 255 with self.assertRaises(TypeError) as ctx: 256 int_array["not-int"] 257 self.assertIn("integer", str(ctx.exception)) 258 259 def test_getitem_wth_dunder_index_calls_dunder_index(self): 260 class DunderIndex: 261 def __index__(self): 262 return 0 263 264 int_array = array.array("i", [1, 2, 3]) 265 self.assertEqual(int_array[DunderIndex()], 1) 266 267 def test_setting_a_value_out_range_raises_index_error(self): 268 int_array = array.array("i", [1, 2, 3]) 269 with self.assertRaises(IndexError) as ctx: 270 int_array[5] = 1 271 self.assertEqual(str(ctx.exception), "array assignment index out of range") 272 273 def test_setting_a_negative_value_out_range_raises_index_error(self): 274 int_array = array.array("i", [1, 2, 3]) 275 with self.assertRaises(IndexError) as ctx: 276 int_array[-5] = 1 277 self.assertEqual(str(ctx.exception), "array assignment index out of range") 278 279 def test_setting_an_index_longer_than_word_raises_index_error(self): 280 int_array = array.array("i", [1, 2, 3]) 281 with self.assertRaises(IndexError) as ctx: 282 int_array[1 << 65] = 1 283 self.assertEqual( 284 str(ctx.exception), "cannot fit 'int' into an index-sized integer" 285 ) 286 287 def test_setting_a_non_integer_index_raises_type_error(self): 288 int_array = array.array("i", [1, 2, 3]) 289 with self.assertRaises(TypeError) as ctx: 290 int_array["not-int"] = 2 291 self.assertIn("integer", str(ctx.exception)) 292 293 def test_setitem_wth_dunder_index_calls_dunder_index(self): 294 class DunderIndex: 295 def __index__(self): 296 return 0 297 298 int_array = array.array("i", [1, 2, 3]) 299 int_array[DunderIndex()] = 10 300 self.assertEqual(int_array[0], 10) 301 302 303if __name__ == "__main__": 304 unittest.main()