// Copyright 2022 The Tint Authors.
//
// 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.

////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen
// using the template:
//   src/tint/ast/storage_class_test.cc.tmpl
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////

#include "src/tint/ast/storage_class.h"

#include <string>

#include "src/tint/ast/test_helper.h"
#include "src/tint/utils/string.h"

namespace tint::ast {
namespace {

namespace parse_print_tests {

struct Case {
    const char* string;
    StorageClass value;
};

inline std::ostream& operator<<(std::ostream& out, Case c) {
    return out << "'" << std::string(c.string) << "'";
}

static constexpr Case kValidCases[] = {
    {"function", StorageClass::kFunction},   {"private", StorageClass::kPrivate},
    {"workgroup", StorageClass::kWorkgroup}, {"uniform", StorageClass::kUniform},
    {"storage", StorageClass::kStorage},     {"push_constant", StorageClass::kPushConstant},
};

static constexpr Case kInvalidCases[] = {
    {"fccnctin", StorageClass::kInvalid},       {"ucti3", StorageClass::kInvalid},
    {"functVon", StorageClass::kInvalid},       {"priv1te", StorageClass::kInvalid},
    {"pqiJate", StorageClass::kInvalid},        {"privat7ll", StorageClass::kInvalid},
    {"workroppqHH", StorageClass::kInvalid},    {"workru", StorageClass::kInvalid},
    {"wbkgGoup", StorageClass::kInvalid},       {"unifiivm", StorageClass::kInvalid},
    {"8WWiform", StorageClass::kInvalid},       {"uxxform", StorageClass::kInvalid},
    {"sXraggg", StorageClass::kInvalid},        {"traXe", StorageClass::kInvalid},
    {"stor3ge", StorageClass::kInvalid},        {"push_constanE", StorageClass::kInvalid},
    {"push_TTPnstant", StorageClass::kInvalid}, {"puxxdh_constan", StorageClass::kInvalid},
};

using StorageClassParseTest = testing::TestWithParam<Case>;

TEST_P(StorageClassParseTest, Parse) {
    const char* string = GetParam().string;
    StorageClass expect = GetParam().value;
    EXPECT_EQ(expect, ParseStorageClass(string));
}

INSTANTIATE_TEST_SUITE_P(ValidCases, StorageClassParseTest, testing::ValuesIn(kValidCases));
INSTANTIATE_TEST_SUITE_P(InvalidCases, StorageClassParseTest, testing::ValuesIn(kInvalidCases));

using StorageClassPrintTest = testing::TestWithParam<Case>;

TEST_P(StorageClassPrintTest, Print) {
    StorageClass value = GetParam().value;
    const char* expect = GetParam().string;
    EXPECT_EQ(expect, utils::ToString(value));
}

INSTANTIATE_TEST_SUITE_P(ValidCases, StorageClassPrintTest, testing::ValuesIn(kValidCases));

}  // namespace parse_print_tests

}  // namespace
}  // namespace tint::ast
