// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <errno.h>
#include <stdarg.h>
#include <unistd.h>

#include <memory>
#include <string>
#include <utility>

#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/util/json_util.h>
#include <google/protobuf/util/type_resolver_util.h>
#include <google/protobuf/stubs/status.h>
#include <google/protobuf/stubs/statusor.h>
#include "conformance.pb.h"
#include "conformance.pb.h"
#include <google/protobuf/test_messages_proto2.pb.h>
#include <google/protobuf/test_messages_proto3.pb.h>
#include <google/protobuf/test_messages_proto3.pb.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/stubs/status.h>
#include <google/protobuf/stubs/status_macros.h>

// Must be included last.
#include <google/protobuf/port_def.inc>

namespace google {
namespace protobuf {
namespace {
using ::conformance::ConformanceRequest;
using ::conformance::ConformanceResponse;
using ::google::protobuf::util::BinaryToJsonString;
using ::google::protobuf::util::JsonParseOptions;
using ::google::protobuf::util::JsonToBinaryString;
using ::google::protobuf::util::NewTypeResolverForDescriptorPool;
using ::google::protobuf::util::TypeResolver;
using ::protobuf_test_messages::proto2::TestAllTypesProto2;
using ::protobuf_test_messages::proto3::TestAllTypesProto3;

util::Status ReadFd(int fd, char* buf, size_t len) {
  while (len > 0) {
    ssize_t bytes_read = read(fd, buf, len);

    if (bytes_read == 0) {
      return util::DataLossError("unexpected EOF");
    }

    if (bytes_read < 0) {
      return util::ErrnoToStatus(errno, "error reading from test runner");
    }

    len -= bytes_read;
    buf += bytes_read;
  }
  return util::OkStatus();
}

util::Status WriteFd(int fd, const void* buf, size_t len) {
  if (write(fd, buf, len) != len) {
    return util::ErrnoToStatus(errno, "error reading to test runner");
  }
  return util::OkStatus();
}

class Harness {
 public:
  Harness() {
    google::protobuf::LinkMessageReflection<TestAllTypesProto2>();
    google::protobuf::LinkMessageReflection<TestAllTypesProto3>();

    resolver_.reset(NewTypeResolverForDescriptorPool(
        "type.googleapis.com", DescriptorPool::generated_pool()));
    type_url_ = StrCat("type.googleapis.com/",
                             TestAllTypesProto3::GetDescriptor()->full_name());
  }

  util::StatusOr<ConformanceResponse> RunTest(
      const ConformanceRequest& request);

  // Returns Ok(true) if we're done processing requests.
  util::StatusOr<bool> ServeConformanceRequest();

 private:
  bool verbose_ = false;
  std::unique_ptr<TypeResolver> resolver_;
  std::string type_url_;
};

util::StatusOr<ConformanceResponse> Harness::RunTest(
    const ConformanceRequest& request) {
  const Descriptor* descriptor =
      DescriptorPool::generated_pool()->FindMessageTypeByName(
          request.message_type());
  if (descriptor == nullptr) {
    return util::NotFoundError(
        StrCat("No such message type: ", request.message_type()));
  }

  std::unique_ptr<Message> test_message(
      MessageFactory::generated_factory()->GetPrototype(descriptor)->New());
  ConformanceResponse response;

  switch (request.payload_case()) {
    case ConformanceRequest::kProtobufPayload: {
      if (!test_message->ParseFromString(request.protobuf_payload())) {
        response.set_parse_error("parse error (no more details available)");
        return response;
      }
      break;
    }

    case ConformanceRequest::kJsonPayload: {
      JsonParseOptions options;
      options.ignore_unknown_fields =
          (request.test_category() ==
           conformance::JSON_IGNORE_UNKNOWN_PARSING_TEST);

      std::string proto_binary;
      util::Status status =
          JsonToBinaryString(resolver_.get(), type_url_, request.json_payload(),
                             &proto_binary, options);
      if (!status.ok()) {
        response.set_parse_error(
            StrCat("parse error: ", status.message()));
        return response;
      }

      if (!test_message->ParseFromString(proto_binary)) {
        response.set_runtime_error(
            "parsing JSON generated invalid proto output");
        return response;
      }

      break;
    }

    case ConformanceRequest::kTextPayload: {
      if (!TextFormat::ParseFromString(request.text_payload(),
                                       test_message.get())) {
        response.set_parse_error("parse error (no more details available)");
        return response;
      }
      break;
    }

    case ConformanceRequest::PAYLOAD_NOT_SET:
      return util::InvalidArgumentError("request didn't have payload");

    default:
      return util::InvalidArgumentError(
          StrCat("unknown payload type", request.payload_case()));
  }

  switch (request.requested_output_format()) {
    case conformance::UNSPECIFIED:
      return util::InvalidArgumentError("unspecified output format");

    case conformance::PROTOBUF: {
      GOOGLE_CHECK(
          test_message->SerializeToString(response.mutable_protobuf_payload()));
      break;
    }

    case conformance::JSON: {
      std::string proto_binary;
      GOOGLE_CHECK(test_message->SerializeToString(&proto_binary));
      util::Status status =
          BinaryToJsonString(resolver_.get(), type_url_, proto_binary,
                             response.mutable_json_payload());
      if (!status.ok()) {
        response.set_serialize_error(StrCat(
            "failed to serialize JSON output: ", status.message()));
      }
      break;
    }

    case conformance::TEXT_FORMAT: {
      TextFormat::Printer printer;
      printer.SetHideUnknownFields(!request.print_unknown_fields());
      GOOGLE_CHECK(printer.PrintToString(*test_message,
                                  response.mutable_text_payload()));
      break;
    }

    default:
      return util::InvalidArgumentError(StrCat(
          "unknown output format", request.requested_output_format()));
  }

  return response;
}

util::StatusOr<bool> Harness::ServeConformanceRequest() {
  uint32_t in_len;
  if (!ReadFd(STDIN_FILENO, reinterpret_cast<char*>(&in_len), sizeof(in_len))
           .ok()) {
    // EOF means we're done.
    return true;
  }

  std::string serialized_input;
  serialized_input.resize(in_len);
  RETURN_IF_ERROR(ReadFd(STDIN_FILENO, serialized_input.data(), in_len));

  ConformanceRequest request;
  GOOGLE_CHECK(request.ParseFromString(serialized_input));

  util::StatusOr<ConformanceResponse> response = RunTest(request);
  RETURN_IF_ERROR(response.status());

  std::string serialized_output;
  response->SerializeToString(&serialized_output);

  uint32_t out_len = static_cast<uint32_t>(serialized_output.size());
  RETURN_IF_ERROR(WriteFd(STDOUT_FILENO, &out_len, sizeof(out_len)));
  RETURN_IF_ERROR(WriteFd(STDOUT_FILENO, serialized_output.data(), out_len));

  if (verbose_) {
    GOOGLE_LOG(INFO) << "conformance-cpp: request=" << request.ShortDebugString()
              << ", response=" << response->ShortDebugString();
  }
  return false;
}
}  // namespace
}  // namespace protobuf
}  // namespace google

int main() {
  google::protobuf::Harness harness;
  int total_runs = 0;
  while (true) {
    auto is_done = harness.ServeConformanceRequest();
    if (!is_done.ok()) {
      GOOGLE_LOG(FATAL) << is_done.status();
    }
    if (*is_done) {
      break;
    }
    total_runs++;
  }
  GOOGLE_LOG(INFO) << "conformance-cpp: received EOF from test runner after "
            << total_runs << " tests";
}
