// Copyright 2020 The Pigweed 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
//
//     https://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.

#include "pw_hdlc/encoder.h"

#include <algorithm>
#include <array>
#include <cstddef>
#include <cstring>

#include "pw_bytes/array.h"
#include "pw_hdlc/encoded_size.h"
#include "pw_hdlc/internal/protocol.h"
#include "pw_stream/memory_stream.h"
#include "pw_unit_test/framework.h"

using std::byte;

namespace pw::hdlc {
namespace {

constexpr uint8_t kAddress = 0x7B;  // 123
constexpr uint8_t kEncodedAddress = (kAddress << 1) | 1;

#define EXPECT_ENCODER_WROTE(...)                                           \
  do {                                                                      \
    constexpr auto expected_data = (__VA_ARGS__);                           \
    EXPECT_EQ(writer_.bytes_written(), expected_data.size());               \
    EXPECT_EQ(                                                              \
        std::memcmp(                                                        \
            writer_.data(), expected_data.data(), writer_.bytes_written()), \
        0);                                                                 \
  } while (0)

class WriteUnnumberedFrame : public ::testing::Test {
 protected:
  WriteUnnumberedFrame() : buffer_{}, writer_(buffer_) {}

  // Allocate a buffer that will fit any 7-byte payload.
  std::array<byte, MaxEncodedFrameSize(7)> buffer_;
  stream::MemoryWriter writer_;
};

constexpr byte kUnnumberedControl = byte{0x3};

TEST_F(WriteUnnumberedFrame, EmptyPayload) {
  ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, span<byte>(), writer_));
  EXPECT_ENCODER_WROTE(bytes::Concat(
      kFlag, kEncodedAddress, kUnnumberedControl, uint32_t{0x832d343f}, kFlag));
}

TEST_F(WriteUnnumberedFrame, OneBytePayload) {
  ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, bytes::String("A"), writer_));
  EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
                                     kEncodedAddress,
                                     kUnnumberedControl,
                                     'A',
                                     uint32_t{0x653c9e82},
                                     kFlag));
}

TEST_F(WriteUnnumberedFrame, OneBytePayload_Escape0x7d) {
  ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, bytes::Array<0x7d>(), writer_));
  EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
                                     kEncodedAddress,
                                     kUnnumberedControl,
                                     kEscape,
                                     byte{0x7d} ^ byte{0x20},
                                     uint32_t{0x4a53e205},
                                     kFlag));
}

TEST_F(WriteUnnumberedFrame, OneBytePayload_Escape0x7E) {
  ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, bytes::Array<0x7e>(), writer_));
  EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
                                     kEncodedAddress,
                                     kUnnumberedControl,
                                     kEscape,
                                     byte{0x7e} ^ byte{0x20},
                                     uint32_t{0xd35ab3bf},
                                     kFlag));
}

TEST_F(WriteUnnumberedFrame, AddressNeedsEscaping) {
  // Becomes 0x7d when encoded.
  constexpr uint8_t kEscapeRequiredAddress = 0x7d >> 1;
  ASSERT_EQ(OkStatus(),
            WriteUIFrame(kEscapeRequiredAddress, bytes::String("A"), writer_));
  EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
                                     kEscape,
                                     byte{0x5d},
                                     kUnnumberedControl,
                                     'A',
                                     uint32_t{0x899E00D4},
                                     kFlag));
}

TEST_F(WriteUnnumberedFrame, Crc32NeedsEscaping) {
  ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, bytes::String("aa"), writer_));

  // The CRC-32 of {kEncodedAddress, kUnnumberedControl, "aa"} is 0x7ee04473, so
  // the 0x7e must be escaped.
  constexpr auto expected_crc32 = bytes::Array<0x73, 0x44, 0xe0, 0x7d, 0x5e>();
  EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
                                     kEncodedAddress,
                                     kUnnumberedControl,
                                     bytes::String("aa"),
                                     expected_crc32,
                                     kFlag));
}

TEST_F(WriteUnnumberedFrame, MultiplePayloads) {
  ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, bytes::String("ABC"), writer_));
  ASSERT_EQ(OkStatus(), WriteUIFrame(kAddress, bytes::String("DEF"), writer_));
  EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
                                     kEncodedAddress,
                                     kUnnumberedControl,
                                     bytes::String("ABC"),
                                     uint32_t{0x72410ee4},
                                     kFlag,
                                     kFlag,
                                     kEncodedAddress,
                                     kUnnumberedControl,
                                     bytes::String("DEF"),
                                     uint32_t{0x4ba1ae47},
                                     kFlag));
}

TEST_F(WriteUnnumberedFrame, PayloadWithNoEscapes) {
  ASSERT_EQ(
      OkStatus(),
      WriteUIFrame(kAddress, bytes::String("1995 toyota corolla"), writer_));

  EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
                                     kEncodedAddress,
                                     kUnnumberedControl,
                                     bytes::String("1995 toyota corolla"),
                                     uint32_t{0x53ee911c},
                                     kFlag));
}

TEST_F(WriteUnnumberedFrame, MultibyteAddress) {
  ASSERT_EQ(OkStatus(), WriteUIFrame(0x3fff, bytes::String("abc"), writer_));

  EXPECT_ENCODER_WROTE(bytes::Concat(kFlag,
                                     bytes::String("\xfe\xff"),
                                     kUnnumberedControl,
                                     bytes::String("abc"),
                                     uint32_t{0x8cee2978},
                                     kFlag));
}

TEST_F(WriteUnnumberedFrame, PayloadWithMultipleEscapes) {
  ASSERT_EQ(
      OkStatus(),
      WriteUIFrame(kAddress,
                   bytes::Array<0x7E, 0x7B, 0x61, 0x62, 0x63, 0x7D, 0x7E>(),
                   writer_));
  EXPECT_ENCODER_WROTE(bytes::Concat(
      kFlag,
      kEncodedAddress,
      kUnnumberedControl,
      bytes::
          Array<0x7D, 0x5E, 0x7B, 0x61, 0x62, 0x63, 0x7D, 0x5D, 0x7D, 0x5E>(),
      uint32_t{0x1563a4e6},
      kFlag));
}

TEST_F(WriteUnnumberedFrame, PayloadTooLarge_WritesNothing) {
  constexpr auto data = bytes::Initialized<sizeof(buffer_)>(0x7e);
  EXPECT_EQ(Status::ResourceExhausted(), WriteUIFrame(kAddress, data, writer_));
  EXPECT_EQ(0u, writer_.bytes_written());
}

class ErrorWriter : public stream::NonSeekableWriter {
 private:
  Status DoWrite(ConstByteSpan) override { return Status::Unimplemented(); }
};

TEST(WriteUIFrame, WriterError) {
  ErrorWriter writer;
  EXPECT_EQ(Status::Unimplemented(),
            WriteUIFrame(kAddress, bytes::Array<0x01>(), writer));
}

}  // namespace
}  // namespace pw::hdlc
