summaryrefslogtreecommitdiffstats
path: root/mojo
diff options
context:
space:
mode:
authoryzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-16 01:09:07 +0000
committeryzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-16 01:09:07 +0000
commit044f520a31a3a31c28affc3f2e22294b4b143a2d (patch)
tree44765fdb29b6e51e3ebe1b43af9c85a705b2c8a8 /mojo
parent1073810d0b9aede1f09dd7c7c9093377d4754a6f (diff)
downloadchromium_src-044f520a31a3a31c28affc3f2e22294b4b143a2d.zip
chromium_src-044f520a31a3a31c28affc3f2e22294b4b143a2d.tar.gz
chromium_src-044f520a31a3a31c28affc3f2e22294b4b143a2d.tar.bz2
Support [handles] in validation test input format and add handle-related tests.
BUG=None TEST=None Review URL: https://codereview.chromium.org/327323003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@277344 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo')
-rw-r--r--mojo/public/cpp/bindings/tests/validation_test_input_parser.cc91
-rw-r--r--mojo/public/cpp/bindings/tests/validation_test_input_parser.h15
-rw-r--r--mojo/public/cpp/bindings/tests/validation_unittest.cc53
-rw-r--r--mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good.data35
-rw-r--r--mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good.expected1
-rw-r--r--mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good_invalid_handle.data36
-rw-r--r--mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good_invalid_handle.expected1
-rw-r--r--mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_handle_out_of_range.data15
-rw-r--r--mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_handle_out_of_range.expected1
-rw-r--r--mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_1.data22
-rw-r--r--mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_1.expected1
-rw-r--r--mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_2.data35
-rw-r--r--mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_2.expected1
-rw-r--r--mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_wrong_handle_order.data36
-rw-r--r--mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_wrong_handle_order.expected1
-rw-r--r--mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom10
16 files changed, 303 insertions, 51 deletions
diff --git a/mojo/public/cpp/bindings/tests/validation_test_input_parser.cc b/mojo/public/cpp/bindings/tests/validation_test_input_parser.cc
index 382c484..49544ee 100644
--- a/mojo/public/cpp/bindings/tests/validation_test_input_parser.cc
+++ b/mojo/public/cpp/bindings/tests/validation_test_input_parser.cc
@@ -21,7 +21,8 @@ namespace {
class ValidationTestInputParser {
public:
ValidationTestInputParser(const std::string& input,
- std::vector<uint8_t>* parsed_input,
+ std::vector<uint8_t>* data,
+ size_t* num_handles,
std::string* error_message);
~ValidationTestInputParser();
@@ -44,7 +45,7 @@ class ValidationTestInputParser {
// A dist4/8 item that hasn't been matched with an anchr item.
struct PendingDistanceItem {
- // Where this data item is located in |parsed_input_|.
+ // Where this data item is located in |data_|.
size_t pos;
// Either 4 or 8 (bytes).
size_t data_size;
@@ -64,14 +65,18 @@ class ValidationTestInputParser {
const std::string& value_string);
bool ParseDistance(const DataType& type, const std::string& value_string);
bool ParseAnchor(const DataType& type, const std::string& value_string);
+ bool ParseHandles(const DataType& type, const std::string& value_string);
bool StartsWith(const Range& range, const char* prefix, size_t prefix_length);
+ bool ConvertToUnsignedInteger(const std::string& value_string,
+ unsigned long long int* value);
+
template <typename T>
void AppendData(T data) {
- size_t pos = parsed_input_->size();
- parsed_input_->resize(pos + sizeof(T));
- memcpy(&(*parsed_input_)[pos], &data, sizeof(T));
+ size_t pos = data_->size();
+ data_->resize(pos + sizeof(T));
+ memcpy(&(*data_)[pos], &data, sizeof(T));
}
template <typename TargetType, typename InputType>
@@ -91,8 +96,8 @@ class ValidationTestInputParser {
return false;
}
TargetType target_value = static_cast<TargetType>(value);
- assert(pos + sizeof(TargetType) <= parsed_input_->size());
- memcpy(&(*parsed_input_)[pos], &target_value, sizeof(TargetType));
+ assert(pos + sizeof(TargetType) <= data_->size());
+ memcpy(&(*data_)[pos], &target_value, sizeof(TargetType));
return true;
}
@@ -102,7 +107,8 @@ class ValidationTestInputParser {
const std::string& input_;
size_t input_cursor_;
- std::vector<uint8_t>* parsed_input_;
+ std::vector<uint8_t>* data_;
+ size_t* num_handles_;
std::string* error_message_;
std::map<std::string, PendingDistanceItem> pending_distance_items_;
@@ -126,7 +132,8 @@ const ValidationTestInputParser::DataType
DATA_TYPE("[d]", 8, &ValidationTestInputParser::ParseDouble),
DATA_TYPE("[dist4]", 4, &ValidationTestInputParser::ParseDistance),
DATA_TYPE("[dist8]", 8, &ValidationTestInputParser::ParseDistance),
- DATA_TYPE("[anchr]", 0, &ValidationTestInputParser::ParseAnchor)
+ DATA_TYPE("[anchr]", 0, &ValidationTestInputParser::ParseAnchor),
+ DATA_TYPE("[handles]", 0, &ValidationTestInputParser::ParseHandles)
};
const size_t ValidationTestInputParser::kDataTypeCount =
@@ -135,15 +142,19 @@ const size_t ValidationTestInputParser::kDataTypeCount =
ValidationTestInputParser::ValidationTestInputParser(
const std::string& input,
- std::vector<uint8_t>* parsed_input,
+ std::vector<uint8_t>* data,
+ size_t* num_handles,
std::string* error_message)
: input_(input),
input_cursor_(0),
- parsed_input_(parsed_input),
+ data_(data),
+ num_handles_(num_handles),
error_message_(error_message) {
- assert(parsed_input_);
+ assert(data_);
+ assert(num_handles_);
assert(error_message_);
- parsed_input_->clear();
+ data_->clear();
+ *num_handles_ = 0;
error_message_->clear();
}
@@ -165,10 +176,12 @@ bool ValidationTestInputParser::Run() {
*error_message_ = "Error occurred when matching [dist4/8] and [anchr].";
result = false;
}
- if (!result)
- parsed_input_->clear();
- else
+ if (!result) {
+ data_->clear();
+ *num_handles_ = 0;
+ } else {
assert(error_message_->empty());
+ }
return result;
}
@@ -219,12 +232,7 @@ bool ValidationTestInputParser::ParseItem(const Range& range) {
bool ValidationTestInputParser::ParseUnsignedInteger(
const DataType& type, const std::string& value_string) {
unsigned long long int value;
- const char* format = NULL;
- if (value_string.find_first_of("xX") != std::string::npos)
- format = "%llx";
- else
- format = "%llu";
- if (sscanf(value_string.c_str(), format, &value) != 1)
+ if (!ConvertToUnsignedInteger(value_string, &value))
return false;
switch (type.data_size) {
@@ -312,8 +320,8 @@ bool ValidationTestInputParser::ParseDistance(const DataType& type,
pending_distance_items_.end())
return false;
- PendingDistanceItem item = {parsed_input_->size(), type.data_size};
- parsed_input_->resize(parsed_input_->size() + type.data_size);
+ PendingDistanceItem item = {data_->size(), type.data_size};
+ data_->resize(data_->size() + type.data_size);
pending_distance_items_[value_string] = item;
return true;
@@ -329,7 +337,7 @@ bool ValidationTestInputParser::ParseAnchor(const DataType& type,
PendingDistanceItem dist_item = iter->second;
pending_distance_items_.erase(iter);
- size_t distance = parsed_input_->size() - dist_item.pos;
+ size_t distance = data_->size() - dist_item.pos;
switch (dist_item.data_size) {
case 4:
return ConvertAndFillData<uint32_t>(dist_item.pos, distance);
@@ -341,6 +349,23 @@ bool ValidationTestInputParser::ParseAnchor(const DataType& type,
}
}
+bool ValidationTestInputParser::ParseHandles(const DataType& type,
+ const std::string& value_string) {
+ // It should be the first item.
+ if (!data_->empty())
+ return false;
+
+ unsigned long long int value;
+ if (!ConvertToUnsignedInteger(value_string, &value))
+ return false;
+
+ if (value > std::numeric_limits<size_t>::max())
+ return false;
+
+ *num_handles_ = static_cast<size_t>(value);
+ return true;
+}
+
bool ValidationTestInputParser::StartsWith(const Range& range,
const char* prefix,
size_t prefix_length) {
@@ -350,12 +375,24 @@ bool ValidationTestInputParser::StartsWith(const Range& range,
return memcmp(range.first, prefix, prefix_length) == 0;
}
+bool ValidationTestInputParser::ConvertToUnsignedInteger(
+ const std::string& value_string,
+ unsigned long long int* value) {
+ const char* format = NULL;
+ if (value_string.find_first_of("xX") != std::string::npos)
+ format = "%llx";
+ else
+ format = "%llu";
+ return sscanf(value_string.c_str(), format, value) == 1;
+}
+
} // namespace
bool ParseValidationTestInput(const std::string& input,
- std::vector<uint8_t>* parsed_input,
+ std::vector<uint8_t>* data,
+ size_t* num_handles,
std::string* error_message) {
- ValidationTestInputParser parser(input, parsed_input, error_message);
+ ValidationTestInputParser parser(input, data, num_handles, error_message);
return parser.Run();
}
diff --git a/mojo/public/cpp/bindings/tests/validation_test_input_parser.h b/mojo/public/cpp/bindings/tests/validation_test_input_parser.h
index 8a4c95a..c8821cd 100644
--- a/mojo/public/cpp/bindings/tests/validation_test_input_parser.h
+++ b/mojo/public/cpp/bindings/tests/validation_test_input_parser.h
@@ -60,6 +60,12 @@ namespace test {
// data.
// Value Format: The value is an ID of the same format as that of dist4/8.
//
+// Type: handles
+// Description: The number of handles that are associated with the message. This
+// special item is not part of the message data. If specified, it should be the
+// first item.
+// Value Format: The same format as u1/2/4/8.
+//
// EXAMPLE:
//
// Suppose you have the following Mojo types defined:
@@ -99,12 +105,13 @@ namespace test {
// [anchr]bar
// Parses validation test input.
-// On success, |parsed_input| stores the parsing result and |error_message| is
-// cleared; on failure, |error_message| is set to a message describing the error
-// and |parsed_input| is cleared.
+// On success, |data| and |num_handles| store the parsing result,
+// |error_message| is cleared; on failure, |error_message| is set to a message
+// describing the error, |data| is cleared and |num_handles| set to 0.
// Note: For now, this method only works on little-endian platforms.
bool ParseValidationTestInput(const std::string& input,
- std::vector<uint8_t>* parsed_input,
+ std::vector<uint8_t>* data,
+ size_t* num_handles,
std::string* error_message);
} // namespace test
diff --git a/mojo/public/cpp/bindings/tests/validation_unittest.cc b/mojo/public/cpp/bindings/tests/validation_unittest.cc
index f1e1b0b..2dbbddb 100644
--- a/mojo/public/cpp/bindings/tests/validation_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/validation_unittest.cc
@@ -38,21 +38,25 @@ void Append(std::vector<uint8_t>* data_vector, T data) {
bool TestInputParser(const std::string& input,
bool expected_result,
- const std::vector<uint8_t>& expected_parsed_input) {
- std::vector<uint8_t> parsed_input;
+ const std::vector<uint8_t>& expected_data,
+ size_t expected_num_handles) {
+ std::vector<uint8_t> data;
+ size_t num_handles;
std::string error_message;
- bool result = ParseValidationTestInput(input, &parsed_input, &error_message);
+ bool result = ParseValidationTestInput(input, &data, &num_handles,
+ &error_message);
if (expected_result) {
if (result && error_message.empty() &&
- expected_parsed_input == parsed_input) {
+ expected_data == data && expected_num_handles == num_handles) {
return true;
}
// Compare with an empty string instead of checking |error_message.empty()|,
// so that the message will be printed out if the two are not equal.
EXPECT_EQ(std::string(), error_message);
- EXPECT_EQ(expected_parsed_input, parsed_input);
+ EXPECT_EQ(expected_data, data);
+ EXPECT_EQ(expected_num_handles, num_handles);
return false;
}
@@ -93,13 +97,15 @@ bool ReadFile(const std::string& path, std::string* result) {
return size == size_read;
}
-bool ReadAndParseDataFile(const std::string& path, std::vector<uint8_t>* data) {
+bool ReadAndParseDataFile(const std::string& path,
+ std::vector<uint8_t>* data,
+ size_t* num_handles) {
std::string input;
if (!ReadFile(path, &input))
return false;
std::string error_message;
- if (!ParseValidationTestInput(input, data, &error_message)) {
+ if (!ParseValidationTestInput(input, data, num_handles, &error_message)) {
ADD_FAILURE() << error_message;
return false;
}
@@ -135,7 +141,8 @@ bool ReadTestCase(const std::string& test,
Message* message,
std::string* expected) {
std::vector<uint8_t> data;
- if (!ReadAndParseDataFile(GetPath(test, ".data"), &data) ||
+ size_t num_handles;
+ if (!ReadAndParseDataFile(GetPath(test, ".data"), &data, &num_handles) ||
!ReadResultFile(GetPath(test, ".expected"), expected)) {
return false;
}
@@ -143,9 +150,7 @@ bool ReadTestCase(const std::string& test,
message->AllocUninitializedData(static_cast<uint32_t>(data.size()));
if (!data.empty())
memcpy(message->mutable_data(), &data[0], data.size());
-
- // TODO(yzshen): add support to specify the number of handles associated with
- // the message.
+ message->mutable_handles()->resize(num_handles);
return true;
}
@@ -280,14 +285,14 @@ TEST(ValidationTest, InputParser) {
std::string input;
std::vector<uint8_t> expected;
- EXPECT_TRUE(TestInputParser(input, true, expected));
+ EXPECT_TRUE(TestInputParser(input, true, expected, 0));
}
{
// Test input that only consists of comments and whitespaces.
std::string input = " \t // hello world \n\r \t// the answer is 42 ";
std::vector<uint8_t> expected;
- EXPECT_TRUE(TestInputParser(input, true, expected));
+ EXPECT_TRUE(TestInputParser(input, true, expected, 0));
}
{
std::string input = "[u1]0x10// hello world !! \n\r \t [u2]65535 \n"
@@ -300,7 +305,7 @@ TEST(ValidationTest, InputParser) {
Append(&expected, static_cast<uint8_t>(0));
Append(&expected, static_cast<uint8_t>(0xff));
- EXPECT_TRUE(TestInputParser(input, true, expected));
+ EXPECT_TRUE(TestInputParser(input, true, expected, 0));
}
{
std::string input = "[s8]-0x800 [s1]-128\t[s2]+0 [s4]-40";
@@ -310,7 +315,7 @@ TEST(ValidationTest, InputParser) {
Append(&expected, static_cast<int16_t>(0));
Append(&expected, static_cast<int32_t>(-40));
- EXPECT_TRUE(TestInputParser(input, true, expected));
+ EXPECT_TRUE(TestInputParser(input, true, expected, 0));
}
{
std::string input = "[b]00001011 [b]10000000 // hello world\r [b]00000000";
@@ -319,7 +324,7 @@ TEST(ValidationTest, InputParser) {
Append(&expected, static_cast<uint8_t>(128));
Append(&expected, static_cast<uint8_t>(0));
- EXPECT_TRUE(TestInputParser(input, true, expected));
+ EXPECT_TRUE(TestInputParser(input, true, expected, 0));
}
{
std::string input = "[f]+.3e9 [d]-10.03";
@@ -327,7 +332,7 @@ TEST(ValidationTest, InputParser) {
Append(&expected, +.3e9f);
Append(&expected, -10.03);
- EXPECT_TRUE(TestInputParser(input, true, expected));
+ EXPECT_TRUE(TestInputParser(input, true, expected, 0));
}
{
std::string input = "[dist4]foo 0 [dist8]bar 0 [anchr]foo [anchr]bar";
@@ -337,7 +342,14 @@ TEST(ValidationTest, InputParser) {
Append(&expected, static_cast<uint64_t>(9));
Append(&expected, static_cast<uint8_t>(0));
- EXPECT_TRUE(TestInputParser(input, true, expected));
+ EXPECT_TRUE(TestInputParser(input, true, expected, 0));
+ }
+ {
+ std::string input = "// This message has handles! \n[handles]50 [u8]2";
+ std::vector<uint8_t> expected;
+ Append(&expected, static_cast<uint64_t>(2));
+
+ EXPECT_TRUE(TestInputParser(input, true, expected, 50));
}
// Test some failure cases.
@@ -345,18 +357,20 @@ TEST(ValidationTest, InputParser) {
const char* error_inputs[] = {
"/ hello world",
"[u1]x",
+ "[u2]-1000",
"[u1]0x100",
"[s2]-0x8001",
"[b]1",
"[b]1111111k",
"[dist4]unmatched",
"[anchr]hello [dist8]hello",
+ "0 [handles]50",
NULL
};
for (size_t i = 0; error_inputs[i]; ++i) {
std::vector<uint8_t> expected;
- if (!TestInputParser(error_inputs[i], false, expected))
+ if (!TestInputParser(error_inputs[i], false, expected, 0))
ADD_FAILURE() << "Unexpected test result for: " << error_inputs[i];
}
}
@@ -368,7 +382,6 @@ TEST(ValidationTest, Conformance) {
validators.Append<mojo::internal::MessageHeaderValidator>();
validators.Append<ConformanceTestInterface::RequestValidator_>();
- // TODO(yzshen): add more conformance tests.
RunValidationTests("conformance_", validators.GetHead());
}
diff --git a/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good.data b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good.data
new file mode 100644
index 0000000..0518c14
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good.data
@@ -0,0 +1,35 @@
+[handles]10 // Larger than the number of handles that we know about is okay.
+
+[dist4]message_header // num_bytes
+[u4]2 // num_fields
+[u4]5 // name
+[u4]0 // flags
+[anchr]message_header
+
+[dist4]method5_params // num_bytes
+[u4]2 // num_fields
+[dist8]param0_ptr // param0
+[u4]4 // param1
+[u4]0 // padding
+[anchr]method5_params
+
+[anchr]param0_ptr
+[dist4]struct_e // num_bytes
+[u4]2 // num_fields
+[dist8]struct_d_ptr // struct_d
+[u4]3 // data_pipe_consumer
+[u4]0 // padding
+[anchr]struct_e
+
+[anchr]struct_d_ptr
+[dist4]struct_d // num_bytes
+[u4]1 // num_fields
+[dist8]message_pipes_ptr // message_pipes
+[anchr]struct_d
+
+[anchr]message_pipes_ptr
+[dist4]message_pipe_array // num_bytes
+[u4]2 // num_elements
+[u4]0
+[u4]1
+[anchr]message_pipe_array
diff --git a/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good.expected b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good.expected
new file mode 100644
index 0000000..7ef22e9
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good.expected
@@ -0,0 +1 @@
+PASS
diff --git a/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good_invalid_handle.data b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good_invalid_handle.data
new file mode 100644
index 0000000..a63e2d0
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good_invalid_handle.data
@@ -0,0 +1,36 @@
+[handles]0
+
+[dist4]message_header // num_bytes
+[u4]2 // num_fields
+[u4]5 // name
+[u4]0 // flags
+[anchr]message_header
+
+[dist4]method5_params // num_bytes
+[u4]2 // num_fields
+[dist8]param0_ptr // param0
+[s4]-1 // param1: An invalid handle.
+[u4]0 // padding
+[anchr]method5_params
+
+[anchr]param0_ptr
+[dist4]struct_e // num_bytes
+[u4]2 // num_fields
+[dist8]struct_d_ptr // struct_d
+[s4]-1 // data_pipe_consumer: An invalid handle.
+[u4]0 // padding
+[anchr]struct_e
+
+[anchr]struct_d_ptr
+[dist4]struct_d // num_bytes
+[u4]1 // num_fields
+[dist8]message_pipes_ptr // message_pipes
+[anchr]struct_d
+
+[anchr]message_pipes_ptr
+[dist4]message_pipe_array // num_bytes
+[u4]3 // num_elements
+[s4]-1 // An invalid handle.
+[s4]-1 // An invalid handle.
+[s4]-1 // An invalid handle.
+[anchr]message_pipe_array
diff --git a/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good_invalid_handle.expected b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good_invalid_handle.expected
new file mode 100644
index 0000000..7ef22e9
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good_invalid_handle.expected
@@ -0,0 +1 @@
+PASS
diff --git a/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_handle_out_of_range.data b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_handle_out_of_range.data
new file mode 100644
index 0000000..557c2ec
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_handle_out_of_range.data
@@ -0,0 +1,15 @@
+[handles]10
+
+[dist4]message_header // num_bytes
+[u4]2 // num_fields
+[u4]5 // name
+[u4]0 // flags
+[anchr]message_header
+
+[dist4]method5_params // num_bytes
+[u4]2 // num_fields
+[u8]0 // param0
+[u4]10 // param1: It is outside of the valid encoded handle
+ // range [0, 9).
+[u4]0 // padding
+[anchr]method5_params
diff --git a/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_handle_out_of_range.expected b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_handle_out_of_range.expected
new file mode 100644
index 0000000..eef8e38
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_handle_out_of_range.expected
@@ -0,0 +1 @@
+VALIDATION_ERROR_ILLEGAL_HANDLE
diff --git a/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_1.data b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_1.data
new file mode 100644
index 0000000..a736b5c
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_1.data
@@ -0,0 +1,22 @@
+[handles]10
+
+[dist4]message_header // num_bytes
+[u4]2 // num_fields
+[u4]5 // name
+[u4]0 // flags
+[anchr]message_header
+
+[dist4]method5_params // num_bytes
+[u4]2 // num_fields
+[dist8]param0_ptr // param0
+[u4]4 // param1
+[u4]0 // padding
+[anchr]method5_params
+
+[anchr]param0_ptr
+[dist4]struct_e // num_bytes
+[u4]2 // num_fields
+[u8]0 // struct_d
+[u4]4 // data_pipe_consumer: The same value as |param1| above.
+[u4]0 // padding
+[anchr]struct_e
diff --git a/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_1.expected b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_1.expected
new file mode 100644
index 0000000..eef8e38
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_1.expected
@@ -0,0 +1 @@
+VALIDATION_ERROR_ILLEGAL_HANDLE
diff --git a/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_2.data b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_2.data
new file mode 100644
index 0000000..95a356b
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_2.data
@@ -0,0 +1,35 @@
+[handles]10
+
+[dist4]message_header // num_bytes
+[u4]2 // num_fields
+[u4]5 // name
+[u4]0 // flags
+[anchr]message_header
+
+[dist4]method5_params // num_bytes
+[u4]2 // num_fields
+[dist8]param0_ptr // param0
+[u4]4 // param1
+[u4]0 // padding
+[anchr]method5_params
+
+[anchr]param0_ptr
+[dist4]struct_e // num_bytes
+[u4]2 // num_fields
+[dist8]struct_d_ptr // struct_d
+[u4]3 // data_pipe_consumer
+[u4]0 // padding
+[anchr]struct_e
+
+[anchr]struct_d_ptr
+[dist4]struct_d // num_bytes
+[u4]1 // num_fields
+[dist8]message_pipes_ptr // message_pipes
+[anchr]struct_d
+
+[anchr]message_pipes_ptr
+[dist4]message_pipe_array // num_bytes
+[u4]2 // num_elements
+[u4]1 // The two message pipe handles have the same value.
+[u4]1
+[anchr]message_pipe_array
diff --git a/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_2.expected b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_2.expected
new file mode 100644
index 0000000..eef8e38
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_2.expected
@@ -0,0 +1 @@
+VALIDATION_ERROR_ILLEGAL_HANDLE
diff --git a/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_wrong_handle_order.data b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_wrong_handle_order.data
new file mode 100644
index 0000000..c6fa8ea
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_wrong_handle_order.data
@@ -0,0 +1,36 @@
+[handles]10
+
+[dist4]message_header // num_bytes
+[u4]2 // num_fields
+[u4]5 // name
+[u4]0 // flags
+[anchr]message_header
+
+[dist4]method5_params // num_bytes
+[u4]2 // num_fields
+[dist8]param0_ptr // param0
+[u4]9 // param1
+[u4]0 // padding
+[anchr]method5_params
+
+[anchr]param0_ptr
+[dist4]struct_e // num_bytes
+[u4]2 // num_fields
+[dist8]struct_d_ptr // struct_d
+[u4]1 // data_pipe_consumer: It is smaller than those handles
+ // in |message_pipe_array|, which is wrong.
+[u4]0 // padding
+[anchr]struct_e
+
+[anchr]struct_d_ptr
+[dist4]struct_d // num_bytes
+[u4]1 // num_fields
+[dist8]message_pipes_ptr // message_pipes
+[anchr]struct_d
+
+[anchr]message_pipes_ptr
+[dist4]message_pipe_array // num_bytes
+[u4]2 // num_elements
+[u4]3
+[u4]4
+[anchr]message_pipe_array
diff --git a/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_wrong_handle_order.expected b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_wrong_handle_order.expected
new file mode 100644
index 0000000..eef8e38
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_wrong_handle_order.expected
@@ -0,0 +1 @@
+VALIDATION_ERROR_ILLEGAL_HANDLE
diff --git a/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom b/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom
index d8d66c3..c16c384 100644
--- a/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom
+++ b/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom
@@ -16,12 +16,22 @@ struct StructC {
uint8[] array;
};
+struct StructD {
+ handle<message_pipe>[] message_pipes;
+};
+
+struct StructE {
+ StructD struct_d;
+ handle<data_pipe_consumer> data_pipe_consumer;
+};
+
interface ConformanceTestInterface {
Method0(float param0);
Method1(StructA param0);
Method2(StructB param0, StructA param1);
Method3(bool[] param0);
Method4(StructC param0, uint8[] param1);
+ Method5(StructE param0, handle<data_pipe_producer> param1);
};
struct BasicStruct {