SCF序列化测试的流程图
cx-序列化测试思路图.png
根据这个流程图来设计char类型的测试case,不能通过,原因如下:
- go端原生不支持char字符型,目前go端是用int16来封装char类型
- 在json中不支持char类型,json中只支持 字符串、布尔值、数字(整数和浮点数)、null、对象、数组
- 如果在json中以单个字符的字符串表示char,java可正常解析,go端不能正常解析,go端不能将字符串直接解析至int16中
- 如果在json中以数字或数字字符串表示char, java端解析错误,不能将大于一个字符的数字解析至char类型中
基于以上的问题,想到了一个解决问题的思路,在json文件中只支持一个端的正常解析,因为java的char类型是原生支持的,所以就在json文件中用单个字符的字符串表示char,在go端手动设计,也支持同样的数据和处理逻辑。实现代码如下:
json文件中数据
{ "GoMethodName":"BasicTypeChar","GoInputParam":{"BasicType":{"charParam":"0"}},"JavaReturnData":{"BasicType":{"charParam":"1"}},
"JavaMethodName":"testchar","JavaTypes":"char","ElemKey":"charParam","JavaMapKey":"testchar3","PtrFlag":false},
{ "GoMethodName":"BasicTypeChar","GoInputParam":{"BasicType":{"charParam":"c"}},"JavaReturnData":{"BasicType":{"charParam":"d"}},
"JavaMethodName":"testchar","JavaTypes":"char","ElemKey":"charParam","JavaMapKey":"testchar2","PtrFlag":false},
java端实现代码
public char testchar(char param,String javaMapKey) throws Exception {
log.error("\n testchar-DataParamObj-javaMapKey: "+javaMapKey);
log.error("\n testchar-DataParamObj-this-module: "+this.module);
DataParam DataParamObj = DataDrive.getDataParamFromMap(this.module,javaMapKey);
//如果验证通过,就返回对象中设定好的数据
if (param == DataParamObj.getGoInputParam().getBasicType().getCharParam()) {
return DataParamObj.getJavaReturnData().getBasicType().getCharParam();
}
return param;
}
//go端char的实现思路
func (st *basicTypeTest) BasicTypeCharOld(s DataJsonStruct) {
charMap := make(map[byte]byte)
javaKeyMap := make(map[byte]string)
charMap['0'] = '1'
javaKeyMap['0'] = "testchar3"
charMap['c'] = 'd'
javaKeyMap['c'] = "testchar2"
for goinput, javareturn := range charMap {
sdata := codec.Character(goinput)
fmt.Printf("\n -----JavaMethodName----------%v", s.JavaMethodName)
fmt.Printf("\n -------JavaTypes----------%v", s.JavaTypes)
fmt.Printf("\n ------tdat----------%v\n", sdat)
res, err := BasicTypeService.proxy.Invoke(s.JavaMethodName, s.JavaTypes+";String", sdata, javaKeyMap[goinput])
if err != nil {
fmt.Printf("[BasicTypeChar] Function failed, err:%s", err)
}
fmt.Printf("\n[BasicTypeChar] Function success,Java return data ---:%v\n", res)
checkdat := codec.Character(javareturn)
compareRes := InterfaceComparator(res, codec.Character(javareturn))
fmt.Printf("\n [BasicTypeChar] Java return data compare The check data result is ---:%v\n", compareRes)
if compareRes == false {
panic(fmt.Sprintf("[BasicTypeChar] serialize failed,Java return the result is not the expected result : javareturn=%v, checkdat=%v\n", res, checkdat))
}
}
}
此种实现方式的弊端:
将实现逻辑和数据驱动耦合在一起了,下次对于扩展char类型的测试数据,还需要修改代码,跟序列化测试最初的测试思路违背了。为了解决这个问题,还是需要将数据驱动和具体的代码实现逻辑分开。
具体的思考过程:
一开始思考,用string来表示两端的数据,在go端将string转成char传到java端,java端接收到数据之后,再将json中的String数据转成char进行对比。由此,上网查询,go和java端的转换实现。
后来在思考的过程中,发现用int类型应该会更简单,int类型在go和java端的转换都比较容易。需要注意的点就是,设置的数据范围不能超过char的最大值65535。
具体的实现代码如下:
json数据
{ "GoMethodName":"BasicTypeChar","GoInputParam":{"BasicType":{"intParam":-32765}},"JavaReturnData":{"BasicType":{"intParam":32788}},
"JavaMethodName":"testchar","JavaTypes":"char","ElemKey":"intParam","JavaMapKey":"testchar","PtrFlag":false}
java服务端代码
public char testchar(char param,String javaMapKey) throws Exception {
log.error("\n testchar-DataParamObj-javaMapKey: "+javaMapKey);
log.error("\n testchar-DataParamObj-this-module: "+this.module);
log.error("\n testchar-DataParamObj-param: "+param);
DataParam DataParamObj = DataDrive.getDataParamFromMap(this.module,javaMapKey);
//临时check的数据
int tmpCheckData = DataParamObj.getGoInputParam().getBasicType().getIntParam();
log.error("\n testchar-DataParamObj-tmpCheckData: "+tmpCheckData);
//将int数据转成char
char chekData = (char)tmpCheckData;
log.error("\n testchar-DataParamObj-chekData: "+chekData);
if( param == chekData) {
//临时返回的数据
int tmpReturnData = DataParamObj.getJavaReturnData().getBasicType().getIntParam();
log.error("\n testchar-DataParamObj-tmpReturnData: "+tmpReturnData);
char returnData = (char) tmpReturnData;
log.error("\n testchar-DataParamObj-returnData: "+returnData);
return returnData;
}
return param;
}
Go端实现代码
func (st *basicTypeTest) BasicTypeChar(s DataJsonStruct){
//此处json中用int类型的原因是java端的char是无符号16bit,可支持的码是0-65535,如果用short达不到这个范围,java端的short最大数也是32767
//用int16进行强转的原因是Character底层设计是int16
tmpInputParam := int16(s.GoInputParam.BasicType.IntParam)
//将int数据转换成char
tdat := codec.Character(tmpInputParam)
res := sendRequestToServer(basicTypeModule,s.GoMethodName,s.JavaMethodName,s.JavaTypes,tdat,s.JavaMapKey)
if(res != false ){
tmpReturnParam := int16(s.JavaReturnData.BasicType.IntParam)
checkdat := codec.Character(tmpReturnParam)
checkReturnData(basicTypeModule,res,checkdat,s.GoMethodName)
}
}
这里需要注意的是:
go端是有符号的int16,取值范围是-32768~32767, java端的char取值范围是0~65535,在go端传负数到java端,会进行有符号到无符号的转换,同样,在java端返回大于32767的数据,到go端会自动解析成负数。因为在序列化的底层,是通过二进制来计算返回值的。