You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
316 lines
12 KiB
316 lines
12 KiB
#
|
|
# Copyright (C) 2016 The Android Open Source Project
|
|
#
|
|
# 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 logging
|
|
import sys
|
|
|
|
from vts.proto import ComponentSpecificationMessage_pb2 as CompSpecMsg
|
|
|
|
|
|
def PyValue2PbEnum(message, pb_spec, py_value):
|
|
"""Converts Python value to VTS VariableSecificationMessage (Enum).
|
|
|
|
Args:
|
|
message: VariableSpecificationMessage is the current and result
|
|
value message.
|
|
pb_spec: VariableSpecificationMessage which captures the
|
|
specification of a target attribute.
|
|
py_value: Python value provided by a test case.
|
|
|
|
Returns:
|
|
Converted VariableSpecificationMessage if found, None otherwise
|
|
"""
|
|
if pb_spec.name:
|
|
message.name = pb_spec.name
|
|
message.type = CompSpecMsg.TYPE_ENUM
|
|
# Look for the enum definition and retrieve the scalar type.
|
|
scalar_type = pb_spec.enum_value.scalar_type
|
|
if scalar_type != "":
|
|
# If the scalar type definition is found, set it and return.
|
|
setattr(message.scalar_value, scalar_type, py_value)
|
|
return
|
|
# Use default scalar_type int32_t for enum definition if the definition
|
|
# is not found.
|
|
setattr(message.scalar_value, "int32_t", py_value)
|
|
|
|
|
|
def PyValue2PbScalar(message, pb_spec, py_value):
|
|
"""Converts Python value to VTS VariableSecificationMessage (Scalar).
|
|
|
|
Args:
|
|
message: VariableSpecificationMessage is the current and result
|
|
value message.
|
|
pb_spec: VariableSpecificationMessage which captures the
|
|
specification of a target attribute.
|
|
py_value: Python value provided by a test case.
|
|
|
|
Returns:
|
|
Converted VariableSpecificationMessage if found, None otherwise
|
|
"""
|
|
if pb_spec.name:
|
|
message.name = pb_spec.name
|
|
message.type = CompSpecMsg.TYPE_SCALAR
|
|
message.scalar_type = pb_spec.scalar_type
|
|
setattr(message.scalar_value, pb_spec.scalar_type, py_value)
|
|
|
|
|
|
def PyString2PbString(message, pb_spec, py_value):
|
|
"""Converts Python string to VTS VariableSecificationMessage (String).
|
|
|
|
Args:
|
|
message: VariableSpecificationMessage is the current and result
|
|
value message.
|
|
pb_spec: VariableSpecificationMessage which captures the
|
|
specification of a target attribute.
|
|
py_value: Python value provided by a test case.
|
|
|
|
Returns:
|
|
Converted VariableSpecificationMessage if found, None otherwise
|
|
"""
|
|
if pb_spec.name:
|
|
message.name = pb_spec.name
|
|
message.type = CompSpecMsg.TYPE_STRING
|
|
message.string_value.message = py_value
|
|
message.string_value.length = len(py_value)
|
|
|
|
|
|
def PyList2PbVector(message, pb_spec, py_value):
|
|
"""Converts Python list value to VTS VariableSecificationMessage (Vector).
|
|
|
|
Args:
|
|
message: VariableSpecificationMessage is the current and result
|
|
value message.
|
|
pb_spec: VariableSpecificationMessage which captures the
|
|
specification of a target attribute.
|
|
py_value: Python value provided by a test case.
|
|
|
|
Returns:
|
|
Converted VariableSpecificationMessage if found, None otherwise
|
|
"""
|
|
if pb_spec.name:
|
|
message.name = pb_spec.name
|
|
message.type = CompSpecMsg.TYPE_VECTOR
|
|
if len(py_value) == 0:
|
|
return message
|
|
|
|
vector_spec = pb_spec.vector_value[0]
|
|
for curr_value in py_value:
|
|
new_vector_message = message.vector_value.add()
|
|
new_vector_message.CopyFrom(Convert(vector_spec, curr_value))
|
|
message.vector_size = len(py_value)
|
|
return message
|
|
|
|
|
|
def FindSubStructType(pb_spec, sub_struct_name):
|
|
"""Finds a specific sub_struct type.
|
|
|
|
Args:
|
|
pb_spec: VariableSpecificationMessage which captures the
|
|
specification of a target attribute.
|
|
sub_struct_name: string, the name of a sub struct to look up.
|
|
|
|
Returns:
|
|
VariableSpecificationMessage if found or None otherwise.
|
|
"""
|
|
for sub_struct in pb_spec.sub_struct:
|
|
if sub_struct.name == sub_struct_name:
|
|
return sub_struct
|
|
return None
|
|
|
|
|
|
def FindSubUnionType(pb_spec, sub_union_name):
|
|
"""Finds a specific sub_union type.
|
|
|
|
Args:
|
|
pb_spec: VariableSpecificationMessage which captures the
|
|
specification of a target attribute.
|
|
sub_union_name: string, the name of a sub union to look up.
|
|
|
|
Returns:
|
|
VariableSpecificationMessage if found or None otherwise.
|
|
"""
|
|
for sub_union in pb_spec.sub_union:
|
|
if sub_union.name == sub_union_name:
|
|
return sub_union
|
|
return None
|
|
|
|
|
|
def PyDict2PbStruct(message, pb_spec, py_value):
|
|
"""Converts Python dict to VTS VariableSecificationMessage (struct).
|
|
|
|
Args:
|
|
pb_spec: VariableSpecificationMessage which captures the
|
|
specification of a target attribute.
|
|
py_value: A dictionary that represents a struct.
|
|
|
|
Returns:
|
|
Converted VariableSpecificationMessage if found, None otherwise
|
|
"""
|
|
if pb_spec.name:
|
|
message.name = pb_spec.name
|
|
message.type = CompSpecMsg.TYPE_STRUCT
|
|
provided_attrs = set(py_value.keys())
|
|
for attr in pb_spec.struct_value:
|
|
if attr.name in py_value:
|
|
provided_attrs.remove(attr.name)
|
|
curr_value = py_value[attr.name]
|
|
attr_msg = message.struct_value.add()
|
|
if attr.type == CompSpecMsg.TYPE_ENUM:
|
|
PyValue2PbEnum(attr_msg, attr, curr_value)
|
|
elif attr.type == CompSpecMsg.TYPE_SCALAR:
|
|
PyValue2PbScalar(attr_msg, attr, curr_value)
|
|
elif attr.type == CompSpecMsg.TYPE_STRING:
|
|
PyString2PbString(attr_msg, attr, curr_value)
|
|
elif attr.type == CompSpecMsg.TYPE_VECTOR:
|
|
PyList2PbVector(attr_msg, attr, curr_value)
|
|
elif attr.type == CompSpecMsg.TYPE_STRUCT:
|
|
sub_attr = FindSubStructType(pb_spec, attr.predefined_type)
|
|
if sub_attr:
|
|
PyDict2PbStruct(attr_msg, sub_attr, curr_value)
|
|
else:
|
|
logging.error("PyDict2PbStruct: substruct not found.")
|
|
return None
|
|
elif attr.type == CompSpecMsg.TYPE_UNION:
|
|
sub_attr = FindSubStructType(pb_spec, attr.predefined_type)
|
|
if sub_attr:
|
|
PyDict2PbUnion(attr_msg, sub_attr, curr_value)
|
|
else:
|
|
logging.error("PyDict2PbStruct: subunion not found.")
|
|
return None
|
|
else:
|
|
logging.error("PyDict2PbStruct: unsupported type %s",
|
|
attr.type)
|
|
return None
|
|
else:
|
|
# TODO: instead crash the test, consider to generate default value
|
|
# in case not provided in the py_value.
|
|
logging.error("PyDict2PbStruct: attr %s not provided", attr.name)
|
|
return None
|
|
if len(provided_attrs) > 0:
|
|
logging.error("PyDict2PbStruct: provided dictionary included elements" +
|
|
" not part of the type being converted to: %s",
|
|
provided_attrs)
|
|
return None
|
|
return message
|
|
|
|
|
|
def PyDict2PbUnion(message, pb_spec, py_value):
|
|
"""Converts Python dict to VTS VariableSecificationMessage (union).
|
|
|
|
Args:
|
|
pb_spec: VariableSpecificationMessage which captures the
|
|
specification of a target attribute.
|
|
py_value: A dictionary that represents a struct.
|
|
|
|
Returns:
|
|
Converted VariableSpecificationMessage if found, None otherwise
|
|
"""
|
|
if len(py_value) > 1:
|
|
logging.error("PyDict2PbUnion: Union only allows specifying " +
|
|
"at most one field. Current Python dictionary " +
|
|
"has size %d", len(py_value))
|
|
return None
|
|
|
|
if pb_spec.name:
|
|
message.name = pb_spec.name
|
|
message.type = CompSpecMsg.TYPE_UNION
|
|
provided_attrs = set(py_value.keys())
|
|
for attr in pb_spec.union_value:
|
|
# Since it is a union type, we stop after finding one field name
|
|
# that matches, and shouldn't throw an error when name is not found.
|
|
if attr.name in py_value:
|
|
provided_attrs.remove(attr.name)
|
|
curr_value = py_value[attr.name]
|
|
attr_msg = message.union_value.add()
|
|
if attr.type == CompSpecMsg.TYPE_ENUM:
|
|
PyValue2PbEnum(attr_msg, attr, curr_value)
|
|
elif attr.type == CompSpecMsg.TYPE_SCALAR:
|
|
PyValue2PbScalar(attr_msg, attr, curr_value)
|
|
elif attr.type == CompSpecMsg.TYPE_STRING:
|
|
PyString2PbString(attr_msg, attr, curr_value)
|
|
elif attr.type == CompSpecMsg.TYPE_VECTOR:
|
|
PyList2PbVector(attr_msg, attr, curr_value)
|
|
elif attr.type == CompSpecMsg.TYPE_STRUCT:
|
|
# TODO: is a nested struct in union stored in sub_union field.
|
|
sub_attr = FindSubUnionType(pb_spec, attr.predefined_type)
|
|
if sub_attr:
|
|
PyDict2PbStruct(attr_msg, sub_attr, curr_value)
|
|
else:
|
|
logging.error("PyDict2PbStruct: substruct not found.")
|
|
return None
|
|
elif attr.type == CompSpecMsg.TYPE_UNION:
|
|
sub_attr = FindSubUnionType(pb_spec, attr.predefined_type)
|
|
if sub_attr:
|
|
PyDict2PbUnion(attr_msg, sub_attr, curr_value)
|
|
else:
|
|
logging.error("PyDict2PbUnion: subunion not found.")
|
|
return None
|
|
else:
|
|
logging.error("PyDict2PbStruct: unsupported type %s",
|
|
attr.type)
|
|
return None
|
|
else:
|
|
# Add a field, where name field is initialized as an empty string.
|
|
# In generated driver implementation, driver knows this field is
|
|
# not used, and skip reading it.
|
|
message.union_value.add()
|
|
|
|
if len(provided_attrs) > 0:
|
|
logging.error("PyDict2PbUnion: specified field is not in the union " +
|
|
"definition for union type %s", provided_attrs)
|
|
return None
|
|
return message
|
|
|
|
|
|
def Convert(pb_spec, py_value):
|
|
"""Converts Python native data structure to VTS VariableSecificationMessage.
|
|
|
|
Args:
|
|
pb_spec: VariableSpecificationMessage which captures the
|
|
specification of a target attribute.
|
|
py_value: Python value provided by a test case.
|
|
|
|
Returns:
|
|
Converted VariableSpecificationMessage if found, None otherwise
|
|
"""
|
|
if not pb_spec:
|
|
logging.error("py2pb.Convert: ProtoBuf spec is None", pb_spec)
|
|
return None
|
|
|
|
message = CompSpecMsg.VariableSpecificationMessage()
|
|
message.name = pb_spec.name
|
|
|
|
if isinstance(py_value, CompSpecMsg.VariableSpecificationMessage):
|
|
message.CopyFrom(py_value)
|
|
elif pb_spec.type == CompSpecMsg.TYPE_STRUCT:
|
|
PyDict2PbStruct(message, pb_spec, py_value)
|
|
elif pb_spec.type == CompSpecMsg.TYPE_UNION:
|
|
PyDict2PbUnion(message, pb_spec, py_value)
|
|
elif pb_spec.type == CompSpecMsg.TYPE_ENUM:
|
|
PyValue2PbEnum(message, pb_spec, py_value)
|
|
elif pb_spec.type == CompSpecMsg.TYPE_SCALAR:
|
|
PyValue2PbScalar(message, pb_spec, py_value)
|
|
elif pb_spec.type == CompSpecMsg.TYPE_STRING:
|
|
PyString2PbString(message, pb_spec, py_value)
|
|
elif pb_spec.type == CompSpecMsg.TYPE_VECTOR:
|
|
PyList2PbVector(message, pb_spec, py_value)
|
|
else:
|
|
logging.error("py2pb.Convert: unsupported type %s",
|
|
pb_spec.type)
|
|
return None
|
|
|
|
return message
|