1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# BitBake Test for lib/bb/persist_data/ 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# Copyright (C) 2018 Garmin Ltd. 5*4882a593Smuzhiyun# 6*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 7*4882a593Smuzhiyun# 8*4882a593Smuzhiyun 9*4882a593Smuzhiyunimport unittest 10*4882a593Smuzhiyunimport bb.data 11*4882a593Smuzhiyunimport bb.persist_data 12*4882a593Smuzhiyunimport tempfile 13*4882a593Smuzhiyunimport threading 14*4882a593Smuzhiyun 15*4882a593Smuzhiyunclass PersistDataTest(unittest.TestCase): 16*4882a593Smuzhiyun def _create_data(self): 17*4882a593Smuzhiyun return bb.persist_data.persist('TEST_PERSIST_DATA', self.d) 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun def setUp(self): 20*4882a593Smuzhiyun self.d = bb.data.init() 21*4882a593Smuzhiyun self.tempdir = tempfile.TemporaryDirectory() 22*4882a593Smuzhiyun self.d['PERSISTENT_DIR'] = self.tempdir.name 23*4882a593Smuzhiyun self.data = self._create_data() 24*4882a593Smuzhiyun self.items = { 25*4882a593Smuzhiyun 'A1': '1', 26*4882a593Smuzhiyun 'B1': '2', 27*4882a593Smuzhiyun 'C2': '3' 28*4882a593Smuzhiyun } 29*4882a593Smuzhiyun self.stress_count = 10000 30*4882a593Smuzhiyun self.thread_count = 5 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun for k,v in self.items.items(): 33*4882a593Smuzhiyun self.data[k] = v 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun def tearDown(self): 36*4882a593Smuzhiyun self.tempdir.cleanup() 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun def _iter_helper(self, seen, iterator): 39*4882a593Smuzhiyun with iter(iterator): 40*4882a593Smuzhiyun for v in iterator: 41*4882a593Smuzhiyun self.assertTrue(v in seen) 42*4882a593Smuzhiyun seen.remove(v) 43*4882a593Smuzhiyun self.assertEqual(len(seen), 0, '%s not seen' % seen) 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun def test_get(self): 46*4882a593Smuzhiyun for k, v in self.items.items(): 47*4882a593Smuzhiyun self.assertEqual(self.data[k], v) 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun self.assertIsNone(self.data.get('D')) 50*4882a593Smuzhiyun with self.assertRaises(KeyError): 51*4882a593Smuzhiyun self.data['D'] 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun def test_set(self): 54*4882a593Smuzhiyun for k, v in self.items.items(): 55*4882a593Smuzhiyun self.data[k] += '-foo' 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun for k, v in self.items.items(): 58*4882a593Smuzhiyun self.assertEqual(self.data[k], v + '-foo') 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun def test_delete(self): 61*4882a593Smuzhiyun self.data['D'] = '4' 62*4882a593Smuzhiyun self.assertEqual(self.data['D'], '4') 63*4882a593Smuzhiyun del self.data['D'] 64*4882a593Smuzhiyun self.assertIsNone(self.data.get('D')) 65*4882a593Smuzhiyun with self.assertRaises(KeyError): 66*4882a593Smuzhiyun self.data['D'] 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun def test_contains(self): 69*4882a593Smuzhiyun for k in self.items: 70*4882a593Smuzhiyun self.assertTrue(k in self.data) 71*4882a593Smuzhiyun self.assertTrue(self.data.has_key(k)) 72*4882a593Smuzhiyun self.assertFalse('NotFound' in self.data) 73*4882a593Smuzhiyun self.assertFalse(self.data.has_key('NotFound')) 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun def test_len(self): 76*4882a593Smuzhiyun self.assertEqual(len(self.data), len(self.items)) 77*4882a593Smuzhiyun 78*4882a593Smuzhiyun def test_iter(self): 79*4882a593Smuzhiyun self._iter_helper(set(self.items.keys()), self.data) 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun def test_itervalues(self): 82*4882a593Smuzhiyun self._iter_helper(set(self.items.values()), self.data.itervalues()) 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun def test_iteritems(self): 85*4882a593Smuzhiyun self._iter_helper(set(self.items.items()), self.data.iteritems()) 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun def test_get_by_pattern(self): 88*4882a593Smuzhiyun self._iter_helper({'1', '2'}, self.data.get_by_pattern('_1')) 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun def _stress_read(self, data): 91*4882a593Smuzhiyun for i in range(self.stress_count): 92*4882a593Smuzhiyun for k in self.items: 93*4882a593Smuzhiyun data[k] 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun def _stress_write(self, data): 96*4882a593Smuzhiyun for i in range(self.stress_count): 97*4882a593Smuzhiyun for k, v in self.items.items(): 98*4882a593Smuzhiyun data[k] = v + str(i) 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun def _validate_stress(self): 101*4882a593Smuzhiyun for k, v in self.items.items(): 102*4882a593Smuzhiyun self.assertEqual(self.data[k], v + str(self.stress_count - 1)) 103*4882a593Smuzhiyun 104*4882a593Smuzhiyun def test_stress(self): 105*4882a593Smuzhiyun self._stress_read(self.data) 106*4882a593Smuzhiyun self._stress_write(self.data) 107*4882a593Smuzhiyun self._validate_stress() 108*4882a593Smuzhiyun 109*4882a593Smuzhiyun def test_stress_threads(self): 110*4882a593Smuzhiyun def read_thread(): 111*4882a593Smuzhiyun data = self._create_data() 112*4882a593Smuzhiyun self._stress_read(data) 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun def write_thread(): 115*4882a593Smuzhiyun data = self._create_data() 116*4882a593Smuzhiyun self._stress_write(data) 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun threads = [] 119*4882a593Smuzhiyun for i in range(self.thread_count): 120*4882a593Smuzhiyun threads.append(threading.Thread(target=read_thread)) 121*4882a593Smuzhiyun threads.append(threading.Thread(target=write_thread)) 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun for t in threads: 124*4882a593Smuzhiyun t.start() 125*4882a593Smuzhiyun self._stress_read(self.data) 126*4882a593Smuzhiyun for t in threads: 127*4882a593Smuzhiyun t.join() 128*4882a593Smuzhiyun self._validate_stress() 129*4882a593Smuzhiyun 130