/* * Copyright (c) 2024 Huawei Device Co., Ltd. * 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. */ /* * @tc.name:sendablemap * @tc.desc:test sendablemap * @tc.type: FUNC * @tc.require: issue#I93TZC */ // @ts-nocheck declare function print(str: any): string; function FillMap(map: SendableMap): void { for (let i = 0; i < 5; i++) { map.set(i, 'value' + i); } } let sharedMap: SendableMap = new SendableMap(); // Basic tests print("===Basic test begin===") FillMap(sharedMap); print("map size is " + sharedMap.size); print(SendableMap[Symbol.species] == SendableMap); print(SendableMap.name == 'SendableMap'); print(SendableMap[Symbol.species] == Map); const keyIter = sharedMap.keys(); let nextEntry = keyIter.next(); print("keys next:" + nextEntry.value + ", done: " + nextEntry.done); nextEntry = keyIter.next(); print("keys next:" + nextEntry.value + ", done: " + nextEntry.done); nextEntry = keyIter.next(); print("keys next:" + nextEntry.value + ", done: " + nextEntry.done); nextEntry = keyIter.next(); print("keys next:" + nextEntry.value + ", done: " + nextEntry.done); nextEntry = keyIter.next(); print("keys next:" + nextEntry.value + ", done: " + nextEntry.done); nextEntry = keyIter.next(); print("keys next:" + nextEntry.value + ", done: " + nextEntry.done); const valueIter = sharedMap.values(); nextEntry = valueIter.next(); print("values next:" + nextEntry.value + ", done: " + nextEntry.done); nextEntry = valueIter.next(); print("values next:" + nextEntry.value + ", done: " + nextEntry.done); nextEntry = valueIter.next(); print("values next:" + nextEntry.value + ", done: " + nextEntry.done); nextEntry = valueIter.next(); print("values next:" + nextEntry.value + ", done: " + nextEntry.done); nextEntry = valueIter.next(); print("values next:" + nextEntry.value + ", done: " + nextEntry.done); nextEntry = valueIter.next(); print("values next:" + nextEntry.value + ", done: " + nextEntry.done); sharedMap.forEach((value: string, key: number, map: SendableMap) => { print('map key[forEach]:' + 'key:' + key + ', value:' + value); }); print(sharedMap[Symbol.toStringTag] == 'SendableMap'); for (let iter of sharedMap[Symbol.iterator]()) { print("map key[Symbol.iterator]:" + iter); } for (let [key, value] of sharedMap.entries()) { print("map entries:[" + key +", " + value + "]"); } print(sharedMap[Symbol.iterator] == sharedMap.entries); print(sharedMap[Symbol.iterator] == sharedMap.keys); print(sharedMap[Symbol.iterator] == sharedMap.values); print(sharedMap.has(4)); sharedMap.set(4, "value4"); print(sharedMap.size == 5); print(sharedMap.has(10)); sharedMap.set(10, "value10"); print(sharedMap.get(10) == "value10"); print(sharedMap.size == 6); print(sharedMap.has(10)); sharedMap.delete(10); print(sharedMap.has(10)); print(sharedMap.size == 5); sharedMap.clear(); print(sharedMap.size == 0); print("===Basic test end==="); // No expected Concurrent modification exception while iterating using iterators print("===Concurrent modification during iteration Test(iterator) begin===") sharedMap.clear(); FillMap(sharedMap); print("map size is " + sharedMap.size); const iterator = sharedMap.entries(); for (const [key, _] of iterator) { print("map key[for-of]: " + key); } try { const iterator = sharedMap.entries(); for (const [key, _] of iterator) { if (key == 1) { sharedMap.set(key + 5, "value" + key + 5); } } print("Set Scenario[for-of] updated size: " + sharedMap.size); } catch (e) { print("Set Scenario[for-of]: " + e); } try { const iterator = sharedMap.entries(); for (const [key, _] of iterator) { if (key % 2 == 0) { sharedMap.delete(key); } } print("Delete Scenario[for-of] updated size: " + sharedMap.size); } catch (e) { print("Delete Scenario[for-of]: " + e); } try { const iterator = sharedMap.entries(); for (const [key, _] of iterator) { sharedMap.clear(); } print("Clear Scenario[for-of] updated size: " + sharedMap.size); } catch (e) { print("Clear Scenario[for-of]: " + e); } sharedMap.clear(); FillMap(sharedMap); print("map size is " + sharedMap.size); try { const iterator = sharedMap.entries(); sharedMap.set(6, "value6"); iterator.next(); print("Set Scenario[next()] updated size: " + sharedMap.size); } catch (e) { print("Set Scenario[next()]: " + e); } try { const iterator = sharedMap.entries(); sharedMap.delete(6); iterator.next(); print("Delete Scenario[next()] updated size: " + sharedMap.size); } catch (e) { print("Delete Scenario[next()]: " + e); } try { const iterator = sharedMap.entries(); sharedMap.clear(); iterator.next(); print("Clear Scenario[next()] updated size: " + sharedMap.size); } catch (e) { print("Clear Scenario[next()]: " + e); } print("===Concurrent modification during iteration Test(iterator) end===") // Expected Concurrent modification exception while iterating using forEach print("===Concurrent modification during iteration Test(forEach) begin===") sharedMap.clear(); FillMap(sharedMap); print("map size is " + sharedMap.size); sharedMap.forEach((_: string, key: number, map: SendableMap) => { print('map key[forEach]: ' + key); }); try { sharedMap.forEach((_: string, key: number, map: SendableMap) => { map.set(key + 5, 'value' + key + 5); }); } catch (e) { print("Set Scenario[forEach]: " + e + ", errCode: " + e.code); } try { sharedMap.forEach((_: string, key: number, map: SendableMap) => { if (key % 2 == 0) { map.delete(key); } }); } catch (e) { print("Delete Scenario[forEach]: " + e + ", errCode: " + e.code); } try { sharedMap.forEach((_: string, key: number, map: SendableMap) => { map.clear(); }); } catch (e) { print("Clear Scenario[forEach]: " + e + ", errCode: " + e.code); } print("===Concurrent modification during iteration Test(forEach) end==="); print("===Type check begin==="); class SObject { constructor() { "use sendable" } }; try { let sObj = new SObject(); sharedMap = new SendableMap([ ['str', 1], [sObj, undefined], [true, null], ]); print("sharedMap set[shared] element success"); } catch (e) { print("sharedMap set[unshared]: " + e + ", errCode: " + e.code); } try { let obj = {} sharedMap = new SendableMap([ ['str', 1], [obj, 2], ]); } catch (e) { print("sharedMap set[unshared]: " + e + ", errCode: " + e.code); } try { let sym = Symbol("testSymbol") sharedMap = new SendableMap([ ['str', 1], [sym, 2], ]); } catch (e) { print("sharedMap set[unshared]: " + e + ", errCode: " + e.code); } print("===Type check end==="); print("===Class inheritance test begin ==="); class SubSendableMap extends SendableMap { desc: string = "I'am SubSendableMap"; constructor(entries?: [K, V][] | null) { 'use sendable'; super(entries); } } let subSendableMap = new SubSendableMap(); subSendableMap.set(1, 'one'); print(subSendableMap.has(1)); print(subSendableMap.size); try { subSendableMap['extension'] = 'value'; } catch(e) { print("add extension(.): " + e); } try { subSendableMap.extension = 'value'; } catch(e) { print("add extension([]): " + e); } try { let obj = {}; subSendableMap = new SubSendableMap([['object', obj]]); print(subSendableMap.size); } catch (e) { print('SubSendableMap set[unshared]: ' + e + ', errCode: ' + e.code); } subSendableMap = new SubSendableMap([ [1, 'one'], [2, 'two'], [3, 'three'], ]); print(subSendableMap.size); for (const [key, value] of subSendableMap.entries()) { print('SubSendableMap [key, value][for-of]: ' + '[' + key + ', ' + value + ']'); } try { subSendableMap.forEach((value: string, key: number, map: SubSendableMap) => { if (key % 2 == 0) { map.delete(key); } }); } catch (e) { print('SubSendableMap Delete Scenario[forEach]: ' + e + ', errCode: ' + e.code); } class SubSubSendableMap extends SubSendableMap { constructor(entries?: [K, V][] | null) { 'use sendable'; super(entries); } } let subSubSendableMap = new SubSubSendableMap(); subSubSendableMap.set(1, 'one'); print(subSubSendableMap.has(1)); print(subSubSendableMap.size); try { let obj = {}; subSubSendableMap = new SubSubSendableMap([['object', obj]]); print(subSubSendableMap.size); } catch (e) { print('SubSubSendableMap set[unshared]: ' + e + ', errCode: ' + e.code); } subSubSendableMap = new SubSubSendableMap([ [1, 'one'], [2, 'two'], [3, 'three'], ]); print(subSendableMap.size); for (const [key, value] of subSendableMap.entries()) { print('SubSubSendableMap [key, value][for-of]: ' + '[' + key + ', ' + value + ']'); } try { subSubSendableMap.forEach((value: string, key: number, map: SubSubSendableMap) => { if (key % 2 == 0) { map.delete(key); } }); } catch (e) { print('SubSubSendableMap Delete Scenario[forEach]: ' + e + ', errCode: ' + e.code); } print("=== An iterable object to convert to an ArkTS Map begin===") sharedMap.clear(); FillMap(sharedMap); print("map size is " + sharedMap.size); try { const iterator = sharedMap.entries(); let sharedMap1: SendableMap = new SendableMap(iterator); sharedMap1.forEach((value: string, key: number, map: SendableMap) => { print("map key[forEach]:" + "key:" + key + ", value:" + value); }); } catch (e) { print("SendableMapConstructor Scenario[next()]: " + e); } print("===Class inheritance test end ===");