diff --git a/src/vscode_plugin/src/gen/gendts.ts b/src/vscode_plugin/src/gen/gendts.ts index d623f80567ac243bec5993ac48dc81adbd9d8358..9d782dba736611ca1f2773837f90085ce938b361 100644 --- a/src/vscode_plugin/src/gen/gendts.ts +++ b/src/vscode_plugin/src/gen/gendts.ts @@ -478,7 +478,7 @@ export function getDtsClasses(rootInfo: GenInfo) { for(const method of classItem.functionList) { let methodContent = ''; for(const param of method.parameters) { - methodContent = `${param.name}: ${transTskey2Ckey(param.type)}, `; + methodContent += `${param.name}: ${transTskey2Ckey(param.type)}, `; } classBody += `\t${method.name}(${methodContent.slice(0, -2)}): ${transTskey2Ckey(method.returns)};\n` }; @@ -503,7 +503,7 @@ export function getDtsStructs(rootInfo: GenInfo) { let methodContent = ''; for(const param of method.parameters) { if (param.name && param.type) { - methodContent = `${param.name}: ${transTskey2Ckey(param.type)}, `; + methodContent += `${param.name}: ${transTskey2Ckey(param.type)}, `; } } structBody += `\t${method.name}(${methodContent.slice(0, -2)}): ${transTskey2Ckey(method.returns)};\n` diff --git a/src/vscode_plugin/src/test/suite/gen/gendts.test.ts b/src/vscode_plugin/src/test/suite/gen/gendts.test.ts index 93ba8d8b4f81721750fa766249c4058bab645d72..09d72a03d62491b8acdd51eaf8bf9e9f3ba8bdf2 100644 --- a/src/vscode_plugin/src/test/suite/gen/gendts.test.ts +++ b/src/vscode_plugin/src/test/suite/gen/gendts.test.ts @@ -22,597 +22,6 @@ import * as genDts from '../../../gen/gendts' import { ClassObj, EnumObj, FuncObj, GenInfo, ParseObj, StructObj, UnionObj } from '../../../gen/datatype'; import * as fs from 'fs'; -suite('Gendts_structs_Suite', () => { - let structs: StructObj[] = [ - { - name: 'StructObj', - alias: '', - members: [ - { - type: 'string', - name: 'name', - arraySize: -1, - }, - { - type: 'int', - name: 'age', - arraySize: -1, - }, - ], - functions: [ - { - returns: 'bool', - name: 'funcTest', - type: '', - parameters: [ - { - type: 'size_t', - name: 'v', - arraySize: -1, - }, - ], - }, - ], - }, - ] - //1, 测试一般情况 - test('getDtsStructs_test_1', () => { - let rootInfo = { - parseObj: { - enums: [], - unions: [], - structs: structs, - classes: [], - funcs: [] - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - }; - - let resStr = genDts.getDtsStructs(rootInfo); - assert.strictEqual(resStr, 'export type StructObj = {\n\tname: string;\n\tage: number;\n\tfuncTest(v: number): boolean;\n};\n\n'); - }); - - //2, 测试边界情况 - test('getDtsStructs_test_2', () => { - // 1. structs为空 - let rootInfo = { - parseObj: { - enums: [], - unions: [], - structs: [], - classes: [], - funcs: [] - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - }; - let resStr = genDts.getDtsStructs(rootInfo); - assert.strictEqual(resStr, ''); - - // 2.structs有成员,成员变量为空,成员方法不为空 - let rootInfo2 = { - parseObj: { - enums: [], - unions: [], - structs: [{ - name: 'StructObj', - alias: '', - members: [], - functions: [{ - returns: 'bool', - name: 'funcTest', - type: '', - parameters: [ - { - type: 'size_t', - name: 'v', - arraySize: -1, - }, - ], - }], - }], - classes: [], - funcs: [] - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - }; - resStr = genDts.getDtsStructs(rootInfo2); - assert.strictEqual(resStr, 'export type StructObj = {\n\tfuncTest(v: number): boolean;\n};\n\n'); - - // 3.structs有成员,成员变量不为空,成员方法为空 - let rootInfo3 = { - parseObj: { - enums: [], - unions: [], - structs: [{ - name: 'StructObj', - alias: '', - members: [ - { - type: 'string', - name: 'name', - arraySize: -1, - }, - { - type: 'int', - name: 'age', - arraySize: -1, - }, - ], - functions: [] - }], - classes: [], - funcs: [] - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - }; - resStr = genDts.getDtsStructs(rootInfo3); - assert.strictEqual(resStr, 'export type StructObj = {\n\tname: string;\n\tage: number;\n};\n\n'); - }); - - //3, 测试异常情况 - test('getDtsStructs_test_3', () => { - // 1.parseObj 没有struct属性 - let rootInfo: GenInfo = { - parseObj: { - enums: [], - unions: [], - classes: [], - funcs: [], - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - } - let res = true; - try { - genDts.getDtsStructs(rootInfo); - } catch (error) { - res = false; - } - assert.strictEqual(res, false); - - // 2. struct没有function属性 - let rootInfo2: GenInfo = { - parseObj: { - enums: [], - unions: [], - structs: [{ - name: 'StructObj', - alias: '', - members: [], - }], - classes: [], - funcs: [] - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - } - let res2 = true; - try { - genDts.getDtsStructs(rootInfo2); - } catch (error) { - res2 = false; - } - assert.strictEqual(res2, false); - - // 3. struct没有members属性 - let rootInfo3: GenInfo = { - parseObj: { - enums: [], - unions: [], - structs: [{ - name: 'StructObj', - alias: '', - functions: [] - }], - classes: [], - funcs: [] - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - } - let res3 = true; - try { - genDts.getDtsStructs(rootInfo3); - } catch (error) { - res3 = false; - } - assert.strictEqual(res3, false); - }); - - //4, 测试错误情况 - test('getDtsStructs_test_4', () => { - let res = true; - try { - genDts.getDtsStructs(null); - } catch (error) { - res = false; - } - assert.strictEqual(res, false); - - let res2 = true; - try { - genDts.getDtsStructs(undefined); - } catch (error) { - res2 = false; - } - assert.strictEqual(res2, false); - }); -}) - -suite('Gendts_classes_Suite', () => { - let classes: ClassObj[] = [ - { - name: 'ClassObj', - alias: '', - variableList: [ - { - type: 'double', - name: 'val', - arraySize: -1, - }, - ], - functionList: [ - { - returns: 'int', - name: 'classFunc', - type: '', - parameters: [ - { - type: 'double', - name: 'v1', - arraySize: -1, - }, - ], - }, - ], - }, - ] - //1, 测试一般情况 - test('getDtsClasses_test_1', () => { - let rootInfo = { - parseObj: { - enums: [], - unions: [], - structs: [], - classes: classes, - funcs: [] - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - }; - let resStr = genDts.getDtsClasses(rootInfo); - assert.strictEqual(resStr, 'export class ClassObj {\n\tval: number;\n\tclassFunc(v1: number): number;\n};\n\n'); - }); - - //2, 测试边界情况 - test('getDtsClasses_test_2', () => { - // 1. class为空 - let rootInfo = { - parseObj: { - enums: [], - unions: [], - structs: [], - classes: [], - funcs: [] - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - }; - let resStr = genDts.getDtsClasses(rootInfo); - assert.strictEqual(resStr, ''); - - // 2.class有成员,成员变量为空,成员方法不为空 - let rootInfo2 = { - parseObj: { - enums: [], - unions: [], - structs: [], - classes: [{ - name: 'ClassObj', - alias: '', - variableList: [], - functionList: [ - { - returns: 'int', - name: 'classFunc', - type: '', - parameters: [ - { - type: 'double', - name: 'v1', - arraySize: -1, - }, - ], - }, - ], - },], - funcs: [] - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - }; - resStr = genDts.getDtsClasses(rootInfo2); - assert.strictEqual(resStr, 'export class ClassObj {\n\tclassFunc(v1: number): number;\n};\n\n'); - - // 3.class有成员,成员变量不为空,成员方法为空 - let rootInfo3 = { - parseObj: { - enums: [], - unions: [], - structs: [], - classes: [{ - name: 'ClassObj', - alias: '', - variableList: [ - { - type: 'double', - name: 'val', - arraySize: -1, - }, - ], - functionList: [], - },], - funcs: [] - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - }; - resStr = genDts.getDtsClasses(rootInfo3); - assert.strictEqual(resStr, 'export class ClassObj {\n\tval: number;\n};\n\n'); - }); - - //3, 测试异常情况 - test('getDtsClasses_test_3', () => { - // 1.parseObj 没有classs属性 - let rootInfo: GenInfo = { - parseObj: { - enums: [], - unions: [], - structs: [], - funcs: [], - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - } - let res = true; - try { - genDts.getDtsClasses(rootInfo); - } catch (error) { - res = false; - } - assert.strictEqual(res, false); - - // 2. class没有functionList属性 - let rootInfo2: GenInfo = { - parseObj: { - enums: [], - unions: [], - structs: [], - classes: [{ - name: 'ClassObj', - alias: '', - variableList: [ - { - type: 'double', - name: 'val', - arraySize: -1, - }, - ], - }], - funcs: [] - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - } - let res2 = true; - try { - genDts.getDtsClasses(rootInfo2); - } catch (error) { - res2 = false; - } - assert.strictEqual(res2, false); - - // 3. class没有varableList属性 - let rootInfo3: GenInfo = { - parseObj: { - enums: [], - unions: [], - structs: [], - classes: [{ - name: 'ClassObj', - alias: '', - functionList: [] - }], - funcs: [] - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - } - let res3 = true; - try { - genDts.getDtsClasses(rootInfo3); - } catch (error) { - res3 = false; - } - assert.strictEqual(res3, false); - }); - - //4, 测试错误情况 - test('getDtsClasses_test_4', () => { - let res = true; - try { - genDts.getDtsClasses(null); - } catch (error) { - res = false; - } - assert.strictEqual(res, false); - - let res2 = true; - try { - genDts.getDtsClasses(undefined); - } catch (error) { - res2 = false; - } - assert.strictEqual(res2, false); - }); -}) - -suite('Gendts_funcs_Suite', () => { - vscode.window.showInformationMessage('Start all tests.'); - - let funcList: FuncObj[] = [ - { - type: 'function', - returns: 'int', - name: 'testFunc', - parameters: [ - { - type: 'bool', - name: 'v1', - arraySize: -1, - } - ], - } - ]; - let parseObj: ParseObj = { - enums: [], - unions: [], - structs: [], - classes: [], - funcs: funcList, - } - - //1, 测试一般情况 - test('getDtsFunction_test_1', () => { - let rootInfo: GenInfo = { - parseObj: parseObj, - rawFilePath: 'e:\\test.h', - fileName: 'test', - } - let resStr = genDts.getDtsFunction(rootInfo); - assert.strictEqual(resStr, 'export function testFunc(v1: boolean): number;\n\n'); - }); - - //2, 测试边界情况 - test('getDtsFunction_test_2', () => { - // 1. 函数列表为空,确保返回空字符串 - let rootInfo: GenInfo = { - parseObj: { - enums: [], - unions: [], - structs: [], - classes: [], - funcs: [], - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - } - let resStr = genDts.getDtsFunction(rootInfo); - assert.strictEqual(resStr, ''); - // 2. 函数没有参数的情况,生成不带参数的声明 - let funcList: FuncObj[] = [ - { - type: 'function', - returns: 'int', - name: 'testFunc', - parameters: [], - } - ]; - let rootInfo2: GenInfo = { - parseObj: { - enums: [], - unions: [], - structs: [], - classes: [], - funcs: funcList, - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - } - resStr = genDts.getDtsFunction(rootInfo2); - assert.strictEqual(resStr, 'export function testFunc(): number;\n\n'); - }); - - //3, 测试异常情况 - test('getDtsFunction_test_3', () => { - // 1.rootInfo.parseObj.funcs不存在时是否会抛出错误 - let rootInfo: GenInfo = { - parseObj: { - enums: [], - unions: [], - structs: [], - classes: [], - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - } - let res = true; - try { - genDts.getDtsFunction(rootInfo); - } catch (error) { - res = false; - } - assert.strictEqual(res, false); - // 2.funcItem缺少必要属性(如 缺少returns)时的处理 - let funcList: FuncObj[] = [ - { - type: 'function', - name: 'testFunc', - parameters: [ - { - type: 'bool', - name: 'v1', - arraySize: -1, - } - ], - } - ]; - let rootInfo2: GenInfo = { - parseObj: { - enums: [], - unions: [], - structs: [], - classes: [], - funcs: funcList - }, - rawFilePath: 'e:\\test.h', - fileName: 'test', - } - let res2 = true; - try { - genDts.getDtsFunction(rootInfo2); - } catch (error) { - res2 = false; - } - assert.strictEqual(res2, false); - - }); - - //4, 测试错误情况 - test('getDtsFunction_test_4', () => { - // 1.传递非法参数,如null/undefined,或者错误类型的输入 - let res = true; - try { - genDts.getDtsFunction(null); - } catch (error) { - res = false; - } - assert.strictEqual(res, false); - - let res2 = true; - try { - genDts.getDtsFunction(undefined); - } catch (error) { - res2 = false; - } - assert.strictEqual(res2, false); - }); -}) - suite('Gendts_file_Suite', () => { vscode.window.showInformationMessage('Start all tests.'); let parseObj: ParseObj = { diff --git a/src/vscode_plugin/src/test/suite/gen/gendtsclasses.test.ts b/src/vscode_plugin/src/test/suite/gen/gendtsclasses.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..3352cfbae6e945b4bd09daa419882b3f815ecae3 --- /dev/null +++ b/src/vscode_plugin/src/test/suite/gen/gendtsclasses.test.ts @@ -0,0 +1,1093 @@ +/* +* Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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. +*/ + +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +import * as genDts from '../../../gen/gendts' +import { ClassObj, EnumObj, FuncObj, GenInfo, ParseObj, StructObj, UnionObj } from '../../../gen/datatype'; +import * as fs from 'fs'; + +suite('Gendts_classes_Suite', () => { + //1, 测试一般情况 + test('getDtsClasses_test_1', () => { + //用例1.classes中alias为空,其他正常 + let classes1: ClassObj[] = [ + { + name: 'ClassObj', + alias: '', + variableList: [ + { + type: 'double', + name: 'val', + arraySize: 0, + arraySizeList: [], + }, + ], + functionList: [ + { + returns: 'int', + name: 'classFunc', + type: '', + parameters: [ + { + type: 'double', + name: 'v1', + arraySize: 0, + arraySizeList: [], + }, + ], + }, + ], + }, + ]; + + let rootInfo1: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: classes1, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + let resStr = genDts.getDtsClasses(rootInfo1); + assert.strictEqual(resStr, 'export class ClassObj {\n\tval: number;\n\tclassFunc(v1: number): number;\n};\n\n'); + + //用例2.classes中alias不为空,且alias不等于name,其他正常 + let classes2: ClassObj[] = [ + { + name: 'ClassObj', + alias: 'Alias', + variableList: [ + { + type: 'double', + name: 'val', + arraySize: 0, + arraySizeList: [], + }, + ], + functionList: [ + { + returns: 'int', + name: 'classFunc', + type: '', + parameters: [ + { + type: 'double', + name: 'v1', + arraySize: 0, + arraySizeList: [], + }, + ], + }, + ], + }, + ]; + + let rootInfo2: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: classes2, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + resStr = genDts.getDtsClasses(rootInfo2); + assert.strictEqual(resStr, 'export class ClassObj {\n\tval: number;\n\tclassFunc(v1: number): number;\n};\n\n' + + 'export type Alias = ClassObj;\n\n'); + + //用例3.classes中alias不为空,且alias等于name,其他正常 + let Classes3:ClassObj[] = [ + { + name: 'ClassObj', + alias: 'ClassObj', + variableList: [ + { + type: 'double', + name: 'val', + arraySize: 0, + arraySizeList: [], + }, + ], + functionList: [ + { + returns: 'int', + name: 'classFunc', + type: '', + parameters: [ + { + type: 'double', + name: 'v1', + arraySize: 0, + arraySizeList: [], + }, + ], + }, + ], + }, + ]; + + let rootInfo3: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: Classes3, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + resStr = genDts.getDtsClasses(rootInfo3); + assert.strictEqual(resStr, 'export class ClassObj {\n\tval: number;\n\tclassFunc(v1: number): number;\n};\n\n' + + 'export type ClassObj = ClassObj;\n\n'); + + //用例4. 混合多个类和复杂参数 + let classes4: ClassObj[] = [ + { + name: 'Vehicle', + alias: 'Car', + variableList: [ + { type: 'float', name: 'speed', arraySize: 0, arraySizeList: []}, + { type: 'bool', name: 'isRunning', arraySize: 0, arraySizeList: []} + ], + functionList: [ + { + returns: 'void', + name: 'start', + type: '', + parameters: [ + { type: 'int', name: 'keyType', arraySize: 0, arraySizeList: []}, + { type: 'string', name: 'authCode', arraySize: 0, arraySizeList: []}, + { type: 'bool', name: 'true' , arraySize: 0, arraySizeList: []}, + ] + } + ] + }, + { + name: 'Engine', + alias: '', + variableList: [], + functionList: [ + { + returns: 'double', + name: 'getRPM', + type: '', + parameters: [] + } + ] + } + ]; + + let rootInfo4: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: classes4, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + resStr = genDts.getDtsClasses(rootInfo4); + const expected = + 'export class Vehicle {\n' + + '\tspeed: number;\n' + + '\tisRunning: boolean;\n' + + '\tstart(keyType: number, authCode: string, true: boolean): void;\n' + + '};\n\n' + + 'export type Car = Vehicle;\n\n' + + 'export class Engine {\n' + + '\tgetRPM(): number;\n' + + '};\n\n'; + assert.strictEqual(resStr, expected); + + //用例5. 测试多参数方法的情况 + let classes5: ClassObj[] = [ + { + name: 'MultiParamClass', + alias: 'MPCType', + variableList: [], + functionList: [{ + returns: 'float', + name: 'calculate', + type: '', + parameters: [ + { type: 'int', name: 'x', arraySize: 0, arraySizeList: [] }, + { type: 'double', name: 'y', arraySize: 0, arraySizeList: [] } + ] + }] + } + ]; + + let rootInfo5: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: classes5, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test' + }; + + resStr = genDts.getDtsClasses(rootInfo5); + assert.strictEqual( + resStr, + 'export class MultiParamClass {\n\tcalculate(x: number, y: number): number;\n};\n\n' + + 'export type MPCType = MultiParamClass;\n\n' + ); + + //用例6. 测试混合多个类的情况 + let classes6: ClassObj[] = [ + { + name: 'ClassA', + alias: 'AliasA', + variableList: [{ + type: 'bool', + name: 'flag', + arraySize: 0, + arraySizeList: [] + }], + functionList: [] + }, + { + name: 'ClassB', + alias: '', + variableList: [], + functionList: [{ + returns: 'string', + name: 'getName', + type: '', + parameters: [] + }] + } + ]; + + let rootInfo6: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: classes6, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test' + }; + + resStr = genDts.getDtsClasses(rootInfo6); + assert.strictEqual( + resStr, + 'export class ClassA {\n\tflag: boolean;\n};\n\n' + + 'export type AliasA = ClassA;\n\n' + + 'export class ClassB {\n\tgetName(): string;\n};\n\n' + ); + + //用例7. 测试特殊类型转换(如布尔型) + let classes7: ClassObj[] = [ + { + name: 'SpecialTypes', + alias: 'SType', + variableList: [{ + type: 'bool', + name: 'isValid', + arraySize: 0, + arraySizeList: [] + }], + functionList: [{ + returns: 'char*', + name: 'getChar', + type: '', + parameters: [{ + type: 'long', + name: 'input', + arraySize: 0, + arraySizeList: [] + }] + }] + } + ]; + + let rootInfo7: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: classes7, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test' + }; + + resStr = genDts.getDtsClasses(rootInfo7); + assert.strictEqual( + resStr, + 'export class SpecialTypes {\n\tisValid: boolean;\n\tgetChar(input: number): string;\n};\n\n' + + 'export type SType = SpecialTypes;\n\n' + ); + + //用例8. 包含数组类型和复杂类型转换 + let classes8: ClassObj[] = [ + { + name: 'DataContainer', + alias: 'DC', + variableList: [ + { type: 'array', name: 'scores', arraySize: 2, arraySizeList: [1,2] }, + { type: 'char*', name: 'buffer', arraySize: 2, arraySizeList: [1,2] } + ], + functionList: [{ + returns: 'void*', + name: 'getData', + type: '', + parameters: [ + { type: 'size_t', name: 'length', arraySize: 2, arraySizeList: [1,2] }, + { type: 'bool', name: 'compress', arraySize: 2, arraySizeList: [1,2] } + ] + }] + } + ]; + + let rootInfo8: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: classes8, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + + resStr = genDts.getDtsClasses(rootInfo8); + assert.strictEqual( + resStr, + 'export class DataContainer {\n' + + '\tscores: Array;\n' + + '\tbuffer: string;\n' + + '\tgetData(length: number, compress: boolean): void;\n' + + '};\n\n' + + 'export type DC = DataContainer;\n\n' + ); + + //用例9. 测试C++特殊类型转换 + let classes9: ClassObj[] = [{ + name: 'SpecialTypes', + alias: '', + variableList: [ + { type: 'unsigned int', name: 'count', arraySize: 0, arraySizeList: [] }, + { type: 'long long', name: 'bigNum', arraySize: 0, arraySizeList: [] } + ], + functionList: [{ + returns: 'size_t', + name: 'getSize', + type: '', + parameters: [{ + type: 'uint8_t*', + name: 'buffer', + arraySize: 0, + arraySizeList: [] + }] + }] + }]; + + let rootInfo9: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: classes9, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test' + }; + + assert.strictEqual( + genDts.getDtsClasses(rootInfo9), + 'export class SpecialTypes {\n' + + '\tcount: number;\n' + + '\tbigNum: number;\n' + + '\tgetSize(buffer: number): number;\n' + + '};\n\n' + ); + + //用例10. 测试静态成员和方法 + let classes10: ClassObj[] = [{ + name: 'Utils', + alias: '', + variableList: [{ + type: 'const string', + name: 'VERSION', + arraySize: 0, + arraySizeList: [] + }], + functionList: [{ + returns: 'void', + name: 'staticMethod', + type: 'static', + parameters: [] + }] + }]; + + let rootInfo10: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: classes10, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test' + }; + + assert.strictEqual( + genDts.getDtsClasses(rootInfo10), + 'export class Utils {\n' + + '\tVERSION: string;\n' + + '\tstaticMethod(): void;\n' + + '};\n\n' + ); + + //用例11. 测试模板类处理 + const classes11: ClassObj[] = [{ + name: 'Vector', + alias: 'Vec', + variableList: [{ + type: 'T*', + name: 'data', + arraySize: 0, + arraySizeList: [] + }], + functionList: [{ + returns: 'void', + name: 'push', + type: '', + parameters: [{ + type: 'const T&', + name: 'item', + arraySize: 0, + arraySizeList: [] + }] + }] + }]; + + let rootInfo11: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: classes11, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test' + }; + + assert.strictEqual( + genDts.getDtsClasses(rootInfo11), + 'export class Vector {\n' + + '\tdata: any;\n' + // 假设泛型暂未处理,返回any类型 + '\tpush(item: any): void;\n' + + '};\n\n' + + 'export type Vec = Vector;\n\n' + ); + + //用例12. 测试const成员变量 + const classes12: ClassObj[] = [{ + name: 'Constants', + alias: '', + variableList: [{ + type: 'const int', + name: 'MAX_SIZE', + arraySize: 0, + arraySizeList: [] + }], + functionList: [] + }]; + + const rootInfo12: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: classes12, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test' + }; + + assert.strictEqual( + genDts.getDtsClasses(rootInfo12), + 'export class Constants {\n' + + '\tMAX_SIZE: number;\n' + + '};\n\n' + ); + + //用例13. 测试嵌套类 + let classes13: ClassObj[] = [{ + name: 'Outer::Inner', + alias: 'Nested', + variableList: [{ + type: 'int', + name: 'value', + arraySize: 0, + arraySizeList: [] + }], + functionList: [] + }]; + + let rootInfo13: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: classes13, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test' + }; + + assert.strictEqual( + genDts.getDtsClasses(rootInfo13), + 'export class Outer::Inner {\n' + + '\tvalue: number;\n' + + '};\n\n' + + 'export type Nested = Outer::Inner;\n\n' + ); + }); + + //2, 测试边界情况 + test('getDtsClasses_test_2', () => { + //用例1. class为空 + let rootInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + let resStr = genDts.getDtsClasses(rootInfo); + assert.strictEqual(resStr, ''); + + //用例2.class有成员,成员变量为空,成员方法不为空 + let rootInfo2 = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [{ + name: 'ClassObj', + alias: '', + variableList: [], + functionList: [ + { + returns: 'int', + name: 'classFunc', + type: '', + parameters: [ + { + type: 'double', + name: 'v1', + arraySize: -1, + assertSizeList: [], + }, + ], + }, + ], + },], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + let resStr2 = genDts.getDtsClasses(rootInfo2); + assert.strictEqual(resStr2, 'export class ClassObj {\n\tclassFunc(v1: number): number;\n};\n\n'); + + //用例3.class有成员,成员变量不为空,成员方法为空 + let rootInfo3 = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [{ + name: 'ClassObj', + alias: '', + variableList: [ + { + type: 'double', + name: 'val', + arraySize: -1, + }, + ], + functionList: [], + },], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + let resStr3 = genDts.getDtsClasses(rootInfo3); + assert.strictEqual(resStr3, 'export class ClassObj {\n\tval: number;\n};\n\n'); + + //用例4. 特殊命名测试 + let rootInfo4 = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [{ + name: 'Class$With$SpecialChars', + alias: 'Alias_With_Underscore', + variableList: [{ + type: 'string', + name: 'data-url', + arraySize: 0 + }], + functionList: [{ + returns: 'void', + name: 'delete', + parameters: [] + }] + }], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + let res4 = genDts.getDtsClasses(rootInfo4); + assert.strictEqual( + res4, + 'export class Class$With$SpecialChars {\n' + + '\tdata-url: string;\n' + + '\tdelete(): void;\n' + + '};\n\n' + + 'export type Alias_With_Underscore = Class$With$SpecialChars;\n\n' + ); + + //用例5. 空参数列表测试 + let rootInfo5 = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [{ + name: 'EmptyParams', + alias: '', + variableList: [], + functionList: [{ + returns: 'void', + name: 'noop', + parameters: [] + }] + }], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + let res5 = genDts.getDtsClasses(rootInfo5); + assert.strictEqual(res5, 'export class EmptyParams {\n\tnoop(): void;\n};\n\n'); + + //用例6. 参数缺少必要字段,缺少alias属性的情况 + let rootInfo6: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [{ + name: 'InvalidClass', + // 缺少alias属性 + variableList: [{ + type: 'string', + name: 'invalidVar', + arraySize: 0, + arraySizeList: [] + }], + functionList: [] + }], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + resStr = genDts.getDtsClasses(rootInfo6); + assert.strictEqual(resStr, 'export class InvalidClass {\n\tinvalidVar: string;\n};\n\n'); + + //用例7. 测试空变量和空方法的类结构 + let classes7: ClassObj[] = [ + { + name: 'EmptyClass', + alias: 'EmptyAlias', + variableList: [], + functionList: [] + } + ]; + + let rootInfo7: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: classes7, + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test' + }; + + let resStr7 = genDts.getDtsClasses(rootInfo7); + assert.strictEqual( + resStr7, + 'export class EmptyClass {\n};\n\n' + + 'export type EmptyAlias = EmptyClass;\n\n' + ); + + //用例8. 超长标识符测试 + let longName = 'A'.repeat(500); + let rootInfo8 = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [{ + name: longName, + alias: `${longName}_Alias`, + variableList: [{ + type: 'int', + name: 'value', + arraySize: 0, + arraySizeList: [] + }], + functionList: [] + }], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + + let resStr8 = genDts.getDtsClasses(rootInfo8); + assert.match( + resStr8, + new RegExp(`export class ${longName} {\\n\\tvalue: number;\\n};\\n\\n` + + `export type ${longName}_Alias = ${longName};`) + ); + }); + + //3, 测试异常情况 + test('getDtsClasses_test_3', () => { + //用例1.parseObj 没有classs属性 + let rootInfo: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + funcs: [], + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + let res = true; + try { + genDts.getDtsClasses(rootInfo); + } catch (error) { + res = false; + } + assert.strictEqual(res, false); + + //用例2. class没有functionList属性 + let rootInfo2: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [{ + name: 'ClassObj', + alias: '', + variableList: [ + { + type: 'double', + name: 'val', + arraySize: -1, + arraySizeList: [], + }, + ], + }], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + let res2 = true; + try { + genDts.getDtsClasses(rootInfo2); + } catch (error) { + res2 = false; + } + assert.strictEqual(res2, false); + + //用例3. class没有varableList属性 + let rootInfo3: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [{ + name: 'ClassObj', + alias: '', + functionList: [] + }], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + let res3 = true; + try { + genDts.getDtsClasses(rootInfo3); + } catch (error) { + res3 = false; + } + assert.strictEqual(res3, false); + + //用例4. 参数缺少必要字段,缺少type字段 + let res4 = true; + try { + let rootInfo4: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [{ + name: 'InvalidClass', + alias: '', + variableList: [{ + // 缺少type字段 + name: 'invalidVar', + arraySize: 0 , + arraySizeList: [] + }], + functionList: [] + }], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + genDts.getDtsClasses(rootInfo4); + } catch (error) { + res4 = false; + } + assert.strictEqual(res4, false); + + //用例5. 无效的方法参数结构 + let res5 = true; + const invalidParam = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [{ + name: 'InvalidParam', + alias: '', + functionList: [{ + returns: 'void', + name: 'brokenMethod', + parameters: [{ type: 'int' }] // 缺少name字段 + }] + }], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + + let errorThrown = false; + try { + genDts.getDtsClasses(invalidParam as GenInfo); + } catch (error) { + res5 = false; + } + assert.strictEqual(res5, false); + + //用例6. 嵌套异常类型处理 + let res6 = true; + const nestedError = { + parseObj: { + classes: [{ + name: 'NestedError', + variableList: [{ + type: 'struct', // 无效类型 + name: 'nested', + arraySize: 0 + }] + }] + } as any, // 强制类型绕过 + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + + let nestedResult = ''; + try { + nestedResult = genDts.getDtsClasses(nestedError); + } catch (error) { + res6 = false; + } + assert.strictEqual(res6, false); + }); + + //4, 测试错误情况 + test('getDtsClasses_test_4', () => { + //用例1.传入错误参数类型 null + let res = true; + try { + genDts.getDtsClasses(null); + } catch (error) { + res = false; + } + assert.strictEqual(res, false); + + //用例2.传入错误参数类型 undefined + let res2 = true; + try { + genDts.getDtsClasses(undefined); + } catch (error) { + res2 = false; + } + assert.strictEqual(res2, false); + + //用例3.传入错误参数类型 普通字符串 + let res3 = true; + try { + genDts.getDtsClasses('abc'); + } catch (error) { + res3 = false; + } + assert.strictEqual(res3, false); + + //用例4. 传入错误参数类型 普通数字 + let res4 = true; + try { + genDts.getDtsClasses(123); + } catch (error) { + res4 = false; + } + assert.strictEqual(res4, false); + + //用例5. 传入错误参数类型 普通布尔值 + let res5 = true; + try { + genDts.getDtsClasses(false); + } catch (error) { + res5 = false; + } + assert.strictEqual(res5, false); + + //用例6. 无效对象结构测试 + const invalidObj1 = { + parseObj: { // 缺少classes字段 + enums: [], + unions: [] + } + }; + let errorCount = 0; + try { + genDts.getDtsClasses(invalidObj1 as GenInfo); + } catch { + errorCount++; + } + assert.strictEqual(errorCount, 1); + + //用例7. 无效class成员测试 + const invalidObj2 = { + parseObj: { + classes: [null], // 包含null成员 + enums: [], + unions: [] + } + }; + errorCount = 0; + try { + genDts.getDtsClasses(invalidObj2 as GenInfo); + } catch { + errorCount++; + } + assert.strictEqual(errorCount, 1); + + //用例8. 循环引用测试 + const circularRef: any = { prop: {} }; + circularRef.prop.self = circularRef; + errorCount = 0; + try { + genDts.getDtsClasses(circularRef); + } catch { + errorCount++; + } + assert.strictEqual(errorCount, 1); + + //用例9. 异常对象结构测试 + const malformedObjects = [ + { parseObj: { classes: [{ variableList: {} }]} }, // 无效变量列表类型 + { parseObj: { classes: [{ name: 12345 }]} }, // 数值型类名 + { parseObj: { classes: [{}]} } // 空类定义 + ]; + errorCount = 0; + malformedObjects.forEach(obj => { + try { + genDts.getDtsClasses(obj as GenInfo); + } catch { + errorCount++; + } + }); + assert.strictEqual(errorCount, 3); + + //用例10. 原型污染测试 + const pollutedObject = JSON.parse(`{ + "parseObj": { + "classes": [{ + "name": "ProtoPolluted", + "__proto__": { "polluted": true } + }] + } + }`); + errorCount = 0; + try { + genDts.getDtsClasses(pollutedObject); + } catch { + errorCount++; + } + assert.strictEqual(errorCount, 1); + }); +}) \ No newline at end of file diff --git a/src/vscode_plugin/src/test/suite/gen/gendtsfunction.test.ts b/src/vscode_plugin/src/test/suite/gen/gendtsfunction.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..a0a9f21f637501b8b4485a61a43ea9b54c4c79b2 --- /dev/null +++ b/src/vscode_plugin/src/test/suite/gen/gendtsfunction.test.ts @@ -0,0 +1,578 @@ +/* +* Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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. +*/ + +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +import * as genDts from '../../../gen/gendts' +import { ClassObj, EnumObj, FuncObj, GenInfo, ParseObj, StructObj, UnionObj } from '../../../gen/datatype'; +import * as fs from 'fs'; + +suite('Gendts_funcs_Suite', () => { + vscode.window.showInformationMessage('Start all tests.'); + //1, 测试一般情况 + test('getDtsFunction_test_1', () => { + //用例1. 正常情况 + let funcList: FuncObj[] = [ + { + type: 'function', + returns: 'int', + name: 'testFunc', + parameters: [ + { + type: 'bool', + name: 'v1', + arraySize: -1, + arraySizeList: [] + } + ], + } + ]; + let parseObj: ParseObj = { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList, + } + + let rootInfo: GenInfo = { + parseObj: parseObj, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + let resStr = genDts.getDtsFunction(rootInfo); + assert.strictEqual(resStr, 'export function testFunc(v1: boolean): number;\n\n'); + + //用例2: 普通函数 + let funcList2: FuncObj[] = [{ + type: 'function', + returns: 'double', + name: 'calculate', + parameters: [ + { type: 'float', name: 'x', arraySize: -1, arraySizeList: [] }, + { type: 'int', name: 'y', arraySize: -1, arraySizeList: [] } + ] + }]; + + let rootInfo2: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList2, + }, + rawFilePath: 'e:\\test.h', + fileName: 'test' + } + resStr = genDts.getDtsFunction(rootInfo2); + assert.strictEqual(resStr, 'export function calculate(x: number, y: number): number;\n\n'); + + //用例3: typedef接口 + let funcList3: FuncObj[] = [{ + type: 'typedef', + returns: 'bool', + name: 'Validator', + parameters: [ + { type: 'string', name: 'input', arraySize: -1, arraySizeList: [] }, + { type: 'int', name: 'maxLength', arraySize: -1, arraySizeList: [] } + ] + }]; + + let rootInfo3: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList3, + }, + rawFilePath: 'e:\\test.h', + fileName: 'test' + } + resStr = genDts.getDtsFunction(rootInfo3); + assert.strictEqual(resStr, 'export interface Validator {\n\t(input: string, maxLength: number): boolean;\n};\n\n'); + + //用例4: 混合参数类型 + let funcList4: FuncObj[] = [{ + type: 'function', + returns: 'char*', + name: 'concat', + parameters: [ + { type: 'string', name: 'str1', arraySize: -1, arraySizeList: [] }, + { type: 'array', name: 'codes', arraySize: -1, arraySizeList: [] }, + { type: 'bool', name: 'flag', arraySize: -1, arraySizeList: [] } + ] + }]; + let rootInfo4: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList4, + }, + rawFilePath: 'e:\\test.h', + fileName: 'test' + } + resStr = genDts.getDtsFunction(rootInfo4); + assert.strictEqual(resStr, 'export function concat(str1: string, codes: Array, flag: boolean): string;\n\n'); + + //用例5: 保留字函数名 + let funcList5: FuncObj[] = [{ + type: 'function', + returns: 'void', + name: 'delete', + parameters: [ + { type: 'int', name: 'id', arraySize: -1, arraySizeList: [] } + ] + }]; + let rootInfo5: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList5, + }, + rawFilePath: 'e:\\test.h', + fileName: 'test' + } + resStr = genDts.getDtsFunction(rootInfo5); + assert.strictEqual(resStr, 'export function delete(id: number): void;\n\n'); + + //用例6 混合类型声明 + let funcList6: FuncObj[] = [ + { + type: 'typedef', + name: 'Callback', + returns: 'void', + parameters: [ + { type: 'int', name: 'code', arraySize: -1, arraySizeList: []}, + { type: 'string', name: 'message', arraySize: -1, arraySizeList: []} + ] + }, + { + type: 'function', + returns: 'bool', + name: 'validate', + parameters: [ + { type: 'Callback', name: 'cb', arraySize: -1, arraySizeList: []}, + { type: 'array', name: 'data', arraySize: -1, arraySizeList: []} + ] + } + ]; + + let rootInfo6: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList6 + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + + resStr = genDts.getDtsFunction(rootInfo6); + const expected = + 'export interface Callback {\n' + + '\t(code: number, message: string): void;\n' + + '};\n\n' + + 'export function validate(cb: any, data: Array): boolean;\n\n'; + assert.strictEqual(resStr, expected); + + //用例7: 保留字函数名 + let funcList7: FuncObj[] = [{ + type: 'function', + returns: 'void', + name: 'delete', + parameters: [ + { type: 'int', name: 'id', arraySize: -1, arraySizeList: [] } + ] + }]; + let rootInfo7: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList7 + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + resStr = genDts.getDtsFunction(rootInfo7); + assert.strictEqual(resStr, 'export function delete(id: number): void;\n\n'); + }); + + //2, 测试边界情况 + test('getDtsFunction_test_2', () => { + //用例1. 函数列表为空,确保返回空字符串 + let rootInfo: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: [], + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + let resStr = genDts.getDtsFunction(rootInfo); + assert.strictEqual(resStr, ''); + + //用例2. 函数没有参数的情况,生成不带参数的声明 + let funcList2: FuncObj[] = [ + { + type: 'function', + returns: 'int', + name: 'testFunc', + parameters: [], + } + ]; + let rootInfo2: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList2, + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + resStr = genDts.getDtsFunction(rootInfo2); + assert.strictEqual(resStr, 'export function testFunc(): number;\n\n'); + + //用例3 特殊字符参数名测试 + let funcList3 = [ + { + type: 'function', + returns: 'void', + name: 'specialChars', + parameters: [ + { type: 'int', name: 'data-id', arraySize: 0, arraySizeList: []}, + { type: 'string', name: 'class', arraySize: 0, arraySizeList: []} + ] + } + ]; + let rootInfo3: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList3, + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + resStr = genDts.getDtsFunction(rootInfo3); + assert.strictEqual( + resStr, + 'export function specialChars(data-id: number, class: string): void;\n\n' + ); + + //用例4 最大参数数量 + const maxParams = Array(10).fill(0).map((_,i) => ({ + type: 'int', name: `param${i+1}`, arraySize: 0, arraySizeList: [] + })); + let funcList4 = [ + { + type: 'function', + returns: 'void', + name: 'maxParams', + parameters: maxParams + } + ]; + let rootInfo4: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList4, + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + resStr = genDts.getDtsFunction(rootInfo4); + assert.match(resStr, /param10: number/); + + //用例5: 空参数名 + let funcList5 = [ + { + type: 'function', + returns: 'void', + name: 'invalid', + parameters: [{ type: 'int', name: '', arraySize: 0, arraySizeList: [] }] + } + ]; + let rootInfo5: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList5, + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + resStr = genDts.getDtsFunction(rootInfo5); + assert.strictEqual(resStr, 'export function invalid(): void;\n\n'); + + //用例6: 带特殊符号的参数名 + let funcList6 = [ + { + type: 'function', + returns: 'void', + name: 'special', + parameters: [ + { type: 'string', name: 'data-url', arraySize: 0, arraySizeList: [] }, + { type: 'int', name: 'class', arraySize: 0, arraySizeList: [] } + ] + } + ]; + let rootInfo6: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList6, + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + resStr = genDts.getDtsFunction(rootInfo6); + assert.strictEqual(resStr, 'export function special(data-url: string, class: number): void;\n\n'); + }); + + //3, 测试异常情况 + test('getDtsFunction_test_3', () => { + //用例1.rootInfo.parseObj.funcs不存在时是否会抛出错误 + let rootInfo: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + let res = true; + try { + genDts.getDtsFunction(rootInfo); + } catch (error) { + res = false; + } + assert.strictEqual(res, false); + + //用例2.funcItem缺少必要属性(如 缺少returns)时的处理 + let funcList2: FuncObj[] = [ + { + type: 'function', + name: 'testFunc', + parameters: [ + { + type: 'bool', + name: 'v1', + arraySize: -1, + arraySizeList: [] + } + ], + } + ]; + let rootInfo2: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList2 + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + let res2 = true; + try { + genDts.getDtsFunction(rootInfo2); + } catch (error) { + res2 = false; + } + assert.strictEqual(res2, false); + + //用例3: 参数缺少type + let res3 = true; + let funcList3: FuncObj[] = [ + { + type: 'function', + name: 'testFunc', + returns: 'void', + parameters: [ + { + //参数缺少type + name: 'invalidParam', + arraySize: -1, + arraySizeList: [] + } + ], + } + ]; + let rootInfo3: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList3 + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + try { + genDts.getDtsFunction(rootInfo2); + } catch (error) { + res3 = false; + } + assert.strictEqual(res3, false); + + //用例4: 未知类型转换 + let funcList4: FuncObj[] = [ + { + type: 'function', + name: 'testFunc', + returns: 'unknown_type', + parameters: [ + { + type: 'custom_type', + name: 'param', + arraySize: -1, + arraySizeList: [] + } + ], + } + ]; + let rootInfo4: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: funcList4 + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + let reStr = genDts.getDtsFunction(rootInfo4); + assert.strictEqual(reStr, 'export function testFunc(param: any): any;\n\n'); + assert.match(reStr, /param: any/); + }); + + //4, 测试错误情况 + test('getDtsFunction_test_4', () => { + //用例1.传递非法参数,null + let res = true; + try { + genDts.getDtsFunction(null); + } catch (error) { + res = false; + } + assert.strictEqual(res, false); + + //用例2.传递非法参数,undefined + let res2 = true; + try { + genDts.getDtsFunction(undefined); + } catch (error) { + res2 = false; + } + assert.strictEqual(res2, false); + + //用例3.传入错误参数类型 普通字符串 + let res3 = true; + try { + genDts.getDtsFunction('invalid'); + } catch (error) { + res3 = false; + } + assert.strictEqual(res3, false); + + //用例4. 传入错误参数类型 普通数字 + let res4 = true; + try { + genDts.getDtsFunction(123); + } catch (error) { + res4 = false; + } + assert.strictEqual(res4, false); + + //用例5. 传入错误参数类型 普通布尔值 + let res5 = true; + try { + genDts.getDtsFunction(true); + } catch (error) { + res5 = false; + } + assert.strictEqual(res5, false); + + //用例6: 结构不完整的对象 + let res6 = true; + try { + genDts.getDtsFunction({} as GenInfo); + } catch (error) { + res6 = false; + } + assert.strictEqual(res6, false); + + //用例7: 无效的函数对象结构 + let res7 = true; + try { + genDts.getDtsFunction({ + parseObj: { + funcs: [{ + type: 'function', + name: 12345, // 错误类型 + parameters: [] + }] + } + } as GenInfo); + } catch (error) { + res7 = false; + } + assert.strictEqual(res7, false); + + //用例8: 空函数定义 + let res8 = true; + try { + genDts.getDtsFunction({ + parseObj: { + funcs: [{}] // 空对象 + } + } as GenInfo); + } catch (error) { + res8 = false; + } + assert.strictEqual(res8, false); + }); +}) \ No newline at end of file diff --git a/src/vscode_plugin/src/test/suite/gen/gendtsstructs.test.ts b/src/vscode_plugin/src/test/suite/gen/gendtsstructs.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..a61706796057bd8b90e9fedc92661c6d62f7c19d --- /dev/null +++ b/src/vscode_plugin/src/test/suite/gen/gendtsstructs.test.ts @@ -0,0 +1,679 @@ +/* +* Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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. +*/ + +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +import * as genDts from '../../../gen/gendts' +import { ClassObj, EnumObj, FuncObj, GenInfo, ParseObj, StructObj, UnionObj } from '../../../gen/datatype'; +import * as fs from 'fs'; + +suite('Gendts_structs_Suite', () => { + //1, 测试一般情况 + test('getDtsStructs_test_1', () => { + //用例1.正常情况,没有alias + let structs: StructObj[] = [ + { + name: 'StructObj', + alias: '', + members: [ + { + type: 'string', + name: 'name', + arraySize: -1, + arraySizeList: [] + }, + { + type: 'int', + name: 'age', + arraySize: -1, + arraySizeList: [] + }, + ], + functions: [ + { + returns: 'bool', + name: 'funcTest', + type: '', + parameters: [ + { + type: 'size_t', + name: 'v', + arraySize: -1, + arraySizeList: [] + }, + ], + }, + ], + }, + ] + + let rootInfo = { + parseObj: { + enums: [], + unions: [], + structs: structs, + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + + let resStr = genDts.getDtsStructs(rootInfo); + assert.strictEqual(resStr, 'export type StructObj = {\n\tname: string;' + + '\n\tage: number;\n\tfuncTest(v: number): boolean;\n};\n\n'); + + //用例2.正常情况,有alias,且alias不等于name + let structs2: StructObj[] = [ + { + name: 'StructObj', + alias: 'Alias', + members: [ + { + type: 'string', + name: 'name', + arraySize: -1, + arraySizeList: [] + }, + { + type: 'int', + name: 'age', + arraySize: -1, + arraySizeList: [] + }, + ], + functions: [ + { + returns: 'bool', + name: 'funcTest', + type: '', + parameters: [ + { + type: 'size_t', + name: 'v', + arraySize: -1, + arraySizeList: [] + }, + ], + }, + ], + }, + ] + + let rootInfo2 = { + parseObj: { + enums: [], + unions: [], + structs: structs2, + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + + resStr = genDts.getDtsStructs(rootInfo2); + assert.strictEqual(resStr, 'export type StructObj = {\n\tname: string;' + + '\n\tage: number;\n\tfuncTest(v: number): boolean;\n};\n\n' + + 'export type Alias = StructObj;\n\n'); + + //用例3.正常情况,有alias,且alias等于name + let structs3: StructObj[] = [ + { + name: 'StructObj', + alias: 'StructObj', + members: [ + { + type: 'string', + name: 'name', + arraySize: -1, + arraySizeList: [] + }, + { + type: 'int', + name: 'age', + arraySize: -1, + arraySizeList: [] + }, + ], + functions: [ + { + returns: 'bool', + name: 'funcTest', + type: '', + parameters: [ + { + type: 'size_t', + name: 'v', + arraySize: -1, + arraySizeList: [] + }, + ], + }, + ], + }, + ] + + let rootInfo3 = { + parseObj: { + enums: [], + unions: [], + structs: structs3, + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + + resStr = genDts.getDtsStructs(rootInfo3); + assert.strictEqual(resStr, 'export type StructObj = {\n\tname: string;' + + '\n\tage: number;\n\tfuncTest(v: number): boolean;\n};\n\n'); + + //用例4.正常情况,一个member,多个parameters + let structs4: StructObj[] = [ + { + name: 'StructObj', + alias: '', + members: [ + { + type: 'string', + name: 'name', + arraySize: -1, + arraySizeList: [] + } + ], + functions: [ + { + returns: 'bool', + name: 'funcTest', + type: '', + parameters: [ + { type: 'string', name: 'a', arraySize: -1, arraySizeList: [] }, + { type: 'int', name: 'b', arraySize: -1, arraySizeList: [] }, + { type: 'bool', name: 'c', arraySize: -1, arraySizeList: [] } + ], + }, + ], + }, + ] + + let rootInfo4 = { + parseObj: { + enums: [], + unions: [], + structs: structs4, + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + + resStr = genDts.getDtsStructs(rootInfo4); + assert.strictEqual(resStr, 'export type StructObj = {\n\tname: string;' + + '\n\tfuncTest(a: string, b: number, c: boolean): boolean;\n};\n\n'); + + //用例4.正常情况,多个member,多个parameters + let structs5: StructObj[] = [ + { + name: 'StructObj', + alias: '', + members: [ + { + type: 'string', + name: 'name', + arraySize: -1, + arraySizeList: [] + }, + { + type: 'int', + name: 'age', + arraySize: -1, + arraySizeList: [] + }, + ], + functions: [ + { + returns: 'bool', + name: 'funcTest', + type: '', + parameters: [ + { type: 'string', name: 'aa', arraySize: -1, arraySizeList: [] }, + { type: 'int', name: 'bb', arraySize: -1, arraySizeList: [] }, + { type: 'bool', name: 'cc', arraySize: -1, arraySizeList: [] } + ], + }, + ], + }, + ] + + let rootInfo5 = { + parseObj: { + enums: [], + unions: [], + structs: structs5, + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + + resStr = genDts.getDtsStructs(rootInfo5); + assert.strictEqual(resStr, 'export type StructObj = {\n\tname: string;' + + '\n\tage: number;\n\tfuncTest(aa: string, bb: number, cc: boolean): boolean;\n};\n\n'); + + //用例6.正常情况,一个member,一个parameters + let structs6: StructObj[] = [ + { + name: 'StructObj', + alias: 'Alias', + members: [ + { + type: 'string', + name: 'name', + arraySize: -1, + arraySizeList: [] + } + ], + functions: [ + { + returns: 'bool', + name: 'funcTest', + type: '', + parameters: [ + { type: 'string', name: 'aa', arraySize: -1, arraySizeList: [] }, + ], + }, + ], + }, + ] + + let rootInfo6 = { + parseObj: { + enums: [], + unions: [], + structs: structs6, + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + + resStr = genDts.getDtsStructs(rootInfo6); + assert.strictEqual(resStr, 'export type StructObj = {\n\tname: string;' + + '\n\tfuncTest(aa: string): boolean;\n};\n\nexport type Alias = StructObj;\n\n'); + + }); + + //2, 测试边界情况 + test('getDtsStructs_test_2', () => { + //用例1. structs为空 + let rootInfo = { + parseObj: { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + let resStr = genDts.getDtsStructs(rootInfo); + assert.strictEqual(resStr, ''); + + //用例2.structs有成员,成员变量为空,成员方法不为空 + let structs2: StructObj[] =[{ + name: 'StructObj', + alias: '', + members: [], + functions: [{ + returns: 'bool', + name: 'funcTest', + type: '', + parameters: [ + { + type: 'size_t', + name: 'v', + arraySize: -1, + arraySizeList: [], + }, + ], + }], + }] + + let rootInfo2 = { + parseObj: { + enums: [], + unions: [], + structs: structs2, + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + resStr = genDts.getDtsStructs(rootInfo2); + assert.strictEqual(resStr, 'export type StructObj = {\n\tfuncTest(v: number): boolean;\n};\n\n'); + + //用例3.structs有成员,成员变量不为空,成员方法为空 + let structs3: StructObj[] =[{ + name: 'StructObj', + alias: '', + members: [ + { + type: 'string', + name: 'name', + arraySize: -1, + arraySizeList: [], + }, + { + type: 'int', + name: 'age', + arraySize: -1, + arraySizeList: [], + }, + ], + functions: [] + }] + + let rootInfo3 = { + parseObj: { + enums: [], + unions: [], + structs: structs3, + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + + resStr = genDts.getDtsStructs(rootInfo3); + assert.strictEqual(resStr, 'export type StructObj = {\n\tname: string;\n\tage: number;\n};\n\n'); + + //用例4.structs有成员,成员变量为空,成员方法为空 + let structs4: StructObj[] =[{ + name: 'StructObj', + alias: '', + members: [], + functions: [] + }] + + let rootInfo4 = { + parseObj: { + enums: [], + unions: [], + structs: structs4, + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + resStr = genDts.getDtsStructs(rootInfo4); + assert.strictEqual(resStr, 'export type StructObj = {\n};\n\n'); + + //用例5.structs有成员,成员变量不为空,成员方法不为空,params为空 + + let structs5: StructObj[] =[{ + name: 'StructObj', + alias: '', + members: [ + { + type: 'string', + name: 'name', + arraySize: -1, + arraySizeList: [], + } + ], + functions: [] + }] + + let rootInfo5 = { + parseObj: { + enums: [], + unions: [], + structs: structs5, + classes: [], + funcs: [{ + returns: 'bool', + name: 'funcTest', + type: '', + parameters: [], + }] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + }; + resStr = genDts.getDtsStructs(rootInfo5); + assert.strictEqual(resStr, 'export type StructObj = {\n\tname: string;\n};\n\n'); + }); + + //3, 测试异常情况 + test('getDtsStructs_test_3', () => { + //用例1.parseObj 没有struct属性 + let rootInfo1: GenInfo = { + parseObj: { + enums: [], + unions: [], + classes: [], + funcs: [], + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + let res1 = true; + try { + genDts.getDtsStructs(rootInfo1); + } catch (error) { + res1 = false; + } + assert.strictEqual(res1, false); + + //用例2. struct没有function属性 + let rootInfo2: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [{ + name: 'StructObj', + alias: '', + members: [], + }], + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + let res2 = true; + try { + genDts.getDtsStructs(rootInfo2); + } catch (error) { + res2 = false; + } + assert.strictEqual(res2, false); + + //用例3. struct没有members属性 + let rootInfo3: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: [{ + name: 'StructObj', + alias: '', + functions: [] + }], + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + let res3 = true; + try { + genDts.getDtsStructs(rootInfo3); + } catch (error) { + res3 = false; + } + assert.strictEqual(res3, false); + + //用例4,function没有return属性 + let structs4: StructObj[] =[{ + name: 'StructObj', + alias: '', + members: [ + { + type: 'string', + name: 'name', + arraySize: -1, + arraySizeList: [], + } + ], + functions: [{ + name: 'funcTest', + type: 'string', + parameters: [ + { + type: 'size_t', + name: 'v', + arraySize: -1, + arraySizeList: [], + }, + ], + }], + }] + let rootInfo4: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: structs4, + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + let res4 = true; + try { + genDts.getDtsStructs(rootInfo4); + } catch (error) { + res4 = false; + } + assert.strictEqual(res4, false); + + //用例5,function没有parameters属性 + let structs5: StructObj[] =[{ + name: 'StructObj', + alias: '', + members: [ + { + type: 'string', + name: 'name', + arraySize: -1, + arraySizeList: [], + } + ], + functions: [{ + name: 'funcTest', + returns: 'bool', + type: 'string', + }], + }] + let rootInfo5: GenInfo = { + parseObj: { + enums: [], + unions: [], + structs: structs5, + classes: [], + funcs: [] + }, + rawFilePath: 'e:\\test.h', + fileName: 'test', + } + let res5 = true; + try { + genDts.getDtsStructs(rootInfo5); + } catch (error) { + res5 = false; + } + assert.strictEqual(res5, false); + }); + + //4, 测试错误情况 + test('getDtsStructs_test_4', () => { + //1.传入null + let res = true; + try { + genDts.getDtsStructs(null); + } catch (error) { + res = false; + } + assert.strictEqual(res, false); + + //2.传入undefined + let res2 = true; + try { + genDts.getDtsStructs(undefined); + } catch (error) { + res2 = false; + } + assert.strictEqual(res2, false); + + //3.传入错误参数类型 普通字符串 + let res3 = true; + try { + genDts.getDtsStructs('invalid'); + } catch (error) { + res3 = false; + } + assert.strictEqual(res3, false); + + + //4. 传入错误参数类型 普通数字 + let res4 = true; + try { + genDts.getDtsStructs(123); + } catch (error) { + res4 = false; + } + assert.strictEqual(res4, false); + + //5. 传入错误参数类型 普通布尔值 + let res5 = true; + try { + genDts.getDtsStructs(true); + } catch (error) { + res5 = false; + } + assert.strictEqual(res5, false); + + // 6: 结构不完整的对象 + let res6 = true; + try { + genDts.getDtsStructs({} as GenInfo); + } catch (error) { + res6 = false; + } + assert.strictEqual(res6, false); + }); +}) \ No newline at end of file diff --git a/src/vscode_plugin/src/test/suite/gen/gendtsunion.test.ts b/src/vscode_plugin/src/test/suite/gen/gendtsunion.test.ts index 55e66c7495840a61570f72dd53b269f76b12c798..d80c2643ca0be598d4c3c37c350ff99c46aae6a3 100644 --- a/src/vscode_plugin/src/test/suite/gen/gendtsunion.test.ts +++ b/src/vscode_plugin/src/test/suite/gen/gendtsunion.test.ts @@ -358,7 +358,7 @@ suite('Gendts_unions_Suite', () => { name: 'llen3', arraySize: 10, arraySizeList: [10, 20, 30] - } + }, { type: 'long long', name: 'llint3',