Add Struct IsValid tests.

This Cl adds tests for the Struct::IsValid to make sure struct members
are also valid.

Bug: tint:11
Change-Id: I49d9f1dd6a6d2da8c49a273466316a849e1d28cd
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/16670
Reviewed-by: Sarah Mashayekhi <sarahmashay@google.com>
diff --git a/src/ast/struct.cc b/src/ast/struct.cc
index 1cdf866..e643e2b 100644
--- a/src/ast/struct.cc
+++ b/src/ast/struct.cc
@@ -17,6 +17,8 @@
 namespace tint {
 namespace ast {
 
+Struct::Struct() : Node() {}
+
 Struct::Struct(StructDecoration decoration,
                std::vector<std::unique_ptr<StructMember>> members)
     : Node(), decoration_(decoration), members_(std::move(members)) {}
@@ -29,6 +31,11 @@
 Struct::~Struct() = default;
 
 bool Struct::IsValid() const {
+  for (const auto& mem : members_) {
+    if (mem == nullptr || !mem->IsValid()) {
+      return false;
+    }
+  }
   return true;
 }
 
diff --git a/src/ast/struct.h b/src/ast/struct.h
index a3d2e12..b7b157c 100644
--- a/src/ast/struct.h
+++ b/src/ast/struct.h
@@ -32,7 +32,7 @@
 class Struct : public Node {
  public:
   /// Create a new empty struct statement
-  Struct() = default;
+  Struct();
   /// Create a new struct statement
   /// @param decoration The struct decorations
   /// @param members The struct members
diff --git a/src/ast/struct_member.cc b/src/ast/struct_member.cc
index 4ad5230..7642ec2 100644
--- a/src/ast/struct_member.cc
+++ b/src/ast/struct_member.cc
@@ -36,7 +36,7 @@
 StructMember::~StructMember() = default;
 
 bool StructMember::IsValid() const {
-  if (name_.length() == 0) {
+  if (name_.empty()) {
     return false;
   }
   if (type_ == nullptr) {
diff --git a/src/ast/struct_test.cc b/src/ast/struct_test.cc
index 9802270..35d608d 100644
--- a/src/ast/struct_test.cc
+++ b/src/ast/struct_test.cc
@@ -59,6 +59,27 @@
   EXPECT_TRUE(s.IsValid());
 }
 
+TEST_F(StructTest, IsValid_Null_StructMember) {
+  type::I32Type i32;
+  std::vector<std::unique_ptr<StructMember>> members;
+  members.push_back(std::make_unique<StructMember>(
+      "a", &i32, std::vector<std::unique_ptr<StructMemberDecoration>>()));
+  members.push_back(nullptr);
+
+  Struct s{StructDecoration::kNone, std::move(members)};
+  EXPECT_FALSE(s.IsValid());
+}
+
+TEST_F(StructTest, IsValid_Invalid_StructMember) {
+  type::I32Type i32;
+  std::vector<std::unique_ptr<StructMember>> members;
+  members.push_back(std::make_unique<StructMember>(
+      "", &i32, std::vector<std::unique_ptr<StructMemberDecoration>>()));
+
+  Struct s{StructDecoration::kNone, std::move(members)};
+  EXPECT_FALSE(s.IsValid());
+}
+
 TEST_F(StructTest, ToStr) {
   type::I32Type i32;
   Source source{27, 4};
@@ -69,10 +90,10 @@
   Struct s{source, StructDecoration::kNone, std::move(members)};
 
   std::ostringstream out;
-  s.to_str(out, 0);
-  EXPECT_EQ(out.str(), R"(Struct{
-  StructMember{a: __i32}
-}
+  s.to_str(out, 2);
+  EXPECT_EQ(out.str(), R"(  Struct{
+    StructMember{a: __i32}
+  }
 )");
 }