| 1715 | } |
| 1716 | |
| 1717 | void ShapeInferenceTest::TestRelaxHandles(bool input_not_output) { |
| 1718 | NodeDef def; |
| 1719 | InferenceContext c(kVersion, &def, MakeOpDef(2, 2), {S({}), S({})}, {}, {}, |
| 1720 | {}); |
| 1721 | auto make_shape = [&c](std::initializer_list<int64> dim_sizes) { |
| 1722 | ShapeHandle s; |
| 1723 | TF_CHECK_OK(c.MakeShapeFromPartialTensorShape(S(dim_sizes), &s)); |
| 1724 | return s; |
| 1725 | }; |
| 1726 | auto get_shapes_and_types_from_context = [&](int idx) { |
| 1727 | if (input_not_output) { |
| 1728 | return c.input_handle_shapes_and_types(idx); |
| 1729 | } else { |
| 1730 | return c.output_handle_shapes_and_types(idx); |
| 1731 | } |
| 1732 | }; |
| 1733 | auto relax_shapes_and_types_to_context = |
| 1734 | [&](int idx, const std::vector<ShapeAndType>& shapes_and_types) { |
| 1735 | if (input_not_output) { |
| 1736 | return c.RelaxInputHandleShapesAndMergeTypes(idx, shapes_and_types); |
| 1737 | } else { |
| 1738 | return c.RelaxOutputHandleShapesAndMergeTypes(idx, shapes_and_types); |
| 1739 | } |
| 1740 | }; |
| 1741 | |
| 1742 | EXPECT_TRUE(get_shapes_and_types_from_context(0) == nullptr); |
| 1743 | EXPECT_TRUE(get_shapes_and_types_from_context(1) == nullptr); |
| 1744 | |
| 1745 | // First relax will take the input completely. |
| 1746 | std::vector<ShapeAndType> t{{make_shape({1, 2, 3}), DT_FLOAT}, |
| 1747 | {c.UnknownShape(), DT_INVALID}, |
| 1748 | {make_shape({4, 3, 2, 1}), DT_INT32}}; |
| 1749 | ASSERT_TRUE(relax_shapes_and_types_to_context(0, t)); |
| 1750 | ASSERT_TRUE(get_shapes_and_types_from_context(0) != nullptr); |
| 1751 | std::vector<ShapeAndType> v = *get_shapes_and_types_from_context(0); |
| 1752 | ASSERT_EQ(3, v.size()); |
| 1753 | for (int i = 0; i < v.size(); ++i) { |
| 1754 | EXPECT_TRUE(SameHandle(t[i].shape, v[i].shape)) << i; |
| 1755 | EXPECT_EQ(t[i].dtype, v[i].dtype); |
| 1756 | } |
| 1757 | |
| 1758 | // Relax that fails because wrong number of values passed. |
| 1759 | // Fails, and no changes made. |
| 1760 | ASSERT_FALSE(relax_shapes_and_types_to_context( |
| 1761 | 0, std::vector<ShapeAndType>{{make_shape({1, 2, 3}), DT_FLOAT}})); |
| 1762 | v = *get_shapes_and_types_from_context(0); |
| 1763 | ASSERT_EQ(3, v.size()); |
| 1764 | for (int i = 0; i < v.size(); ++i) { |
| 1765 | EXPECT_TRUE(SameHandle(t[i].shape, v[i].shape)) << i; |
| 1766 | EXPECT_EQ(t[i].dtype, v[i].dtype); |
| 1767 | } |
| 1768 | |
| 1769 | // Only difference is in a mismatched shape. This should replace |
| 1770 | // the mismatched dimension with an UnknownDim. |
| 1771 | auto t2 = t; |
| 1772 | t2[2].shape = make_shape({4, 3, 4, 1}); |
| 1773 | ASSERT_TRUE(relax_shapes_and_types_to_context(0, t2)); |
| 1774 | v = *get_shapes_and_types_from_context(0); |
nothing calls this directly
no test coverage detected