// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC.  All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

#include "upb/util/required_fields.h"

#include <stdlib.h>

#include <gtest/gtest.h>
#include "absl/strings/string_view.h"
#include "upb/base/status.hpp"
#include "upb/json/decode.h"
#include "upb/mem/arena.h"
#include "upb/mem/arena.hpp"
#include "upb/reflection/common.h"
#include "upb/reflection/def.hpp"
#include "upb/util/required_fields_editions_test.upb.h"
#include "upb/util/required_fields_editions_test.upbdefs.h"
#include "upb/util/required_fields_test.upb.h"
#include "upb/util/required_fields_test.upbdefs.h"

std::vector<std::string> PathsToText(upb_FieldPathEntry* entry) {
  std::vector<std::string> ret;
  char buf[1024];  // Larger than anything we'll use in this test.
  while (entry->field) {
    upb_FieldPathEntry* before = entry;
    size_t len = upb_FieldPath_ToText(&entry, buf, sizeof(buf));
    EXPECT_LT(len, sizeof(buf));
    assert(len <= sizeof(buf));
    ret.push_back(buf);

    // Ensure that we can have a short buffer and that it will be
    // NULL-terminated.
    char shortbuf[4];
    size_t len2 = upb_FieldPath_ToText(&before, shortbuf, sizeof(shortbuf));
    EXPECT_EQ(len, len2);
    EXPECT_EQ(ret.back().substr(0, sizeof(shortbuf) - 1),
              std::string(shortbuf));
  }
  return ret;
}

template <typename T>
class RequiredFieldsTest : public testing::Test {
 public:
  void CheckRequired(absl::string_view json,
                     const std::vector<std::string>& missing) {
    upb::Arena arena;
    upb::DefPool defpool;
    auto* test_msg = T::NewMessage(arena.ptr());
    upb::MessageDefPtr m = T::GetMessageDef(defpool.ptr());
    upb::Status status;
    EXPECT_TRUE(upb_JsonDecode(json.data(), json.size(), test_msg, m.ptr(),
                               defpool.ptr(), 0, arena.ptr(), status.ptr()))
        << status.error_message();
    upb_FieldPathEntry* entries = nullptr;
    EXPECT_EQ(
        !missing.empty(),
        upb_util_HasUnsetRequired(test_msg, m.ptr(), defpool.ptr(), &entries));
    if (entries) {
      EXPECT_EQ(missing, PathsToText(entries));
      free(entries);
    }

    // Verify that we can pass a NULL pointer to entries when we don't care
    // about them.
    EXPECT_EQ(!missing.empty(), upb_util_HasUnsetRequired(
                                    test_msg, m.ptr(), defpool.ptr(), nullptr));
  }
};

class Proto2Type {
 public:
  using MessageType = upb_util_test_TestRequiredFields;
  static MessageType* NewMessage(upb_Arena* arena) {
    return upb_util_test_TestRequiredFields_new(arena);
  }
  static upb::MessageDefPtr GetMessageDef(upb_DefPool* defpool) {
    return upb::MessageDefPtr(
        upb_util_test_TestRequiredFields_getmsgdef(defpool));
  }
};

class Edition2023Type {
 public:
  using MessageType = upb_util_2023_test_TestRequiredFields;
  static MessageType* NewMessage(upb_Arena* arena) {
    return upb_util_2023_test_TestRequiredFields_new(arena);
  }
  static upb::MessageDefPtr GetMessageDef(upb_DefPool* defpool) {
    return upb::MessageDefPtr(
        upb_util_2023_test_TestRequiredFields_getmsgdef(defpool));
  }
};

using MyTypes = ::testing::Types<Proto2Type, Edition2023Type>;
TYPED_TEST_SUITE(RequiredFieldsTest, MyTypes);

// message HasRequiredField {
//   required int32 required_int32 = 1;
// }
//
// message TestRequiredFields {
//   required EmptyMessage required_message = 1;
//   optional TestRequiredFields optional_message = 2;
//   repeated HasRequiredField repeated_message = 3;
//   map<int32, HasRequiredField> map_int32_message = 4;
// }
TYPED_TEST(RequiredFieldsTest, TestRequired) {
  TestFixture::CheckRequired(R"json({})json", {"required_message"});
  TestFixture::CheckRequired(R"json({"required_message": {}})json", {});
  TestFixture::CheckRequired(
      R"json(
      {
        "optional_message": {}
      }
      )json",
      {"required_message", "optional_message.required_message"});

  // Repeated field.
  TestFixture::CheckRequired(
      R"json(
      {
        "optional_message": {
          "repeated_message": [
            {"required_int32": 1},
            {},
            {"required_int32": 2}
          ]
        }
      }
      )json",
      {"required_message", "optional_message.required_message",
       "optional_message.repeated_message[1].required_int32"});

  // Int32 map key.
  TestFixture::CheckRequired(
      R"json(
      {
        "required_message": {},
        "map_int32_message": {
          "1": {"required_int32": 1},
          "5": {},
          "9": {"required_int32": 1}
        }
      }
      )json",
      {"map_int32_message[5].required_int32"});

  // Int64 map key.
  TestFixture::CheckRequired(
      R"json(
      {
        "required_message": {},
        "map_int64_message": {
          "1": {"required_int32": 1},
          "5": {},
          "9": {"required_int32": 1}
        }
      }
      )json",
      {"map_int64_message[5].required_int32"});

  // Uint32 map key.
  TestFixture::CheckRequired(
      R"json(
      {
        "required_message": {},
        "map_uint32_message": {
          "1": {"required_int32": 1},
          "5": {},
          "9": {"required_int32": 1}
        }
      }
      )json",
      {"map_uint32_message[5].required_int32"});

  // Uint64 map key.
  TestFixture::CheckRequired(
      R"json(
      {
        "required_message": {},
        "map_uint64_message": {
          "1": {"required_int32": 1},
          "5": {},
          "9": {"required_int32": 1}
        }
      }
      )json",
      {"map_uint64_message[5].required_int32"});

  // Bool map key.
  TestFixture::CheckRequired(
      R"json(
      {
        "required_message": {},
        "map_bool_message": {
          "false": {"required_int32": 1},
          "true": {}
        }
      }
      )json",
      {"map_bool_message[true].required_int32"});

  // String map key.
  TestFixture::CheckRequired(
      R"json(
      {
        "required_message": {},
        "map_string_message": {
          "abc": {"required_int32": 1},
          "d\"ef": {}
        }
      }
      )json",
      {R"(map_string_message["d\"ef"].required_int32)"});
}
