// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file tests some public interface methods of AttributeList.
#include "shill/net/attribute_list.h"

#include <linux/netlink.h>

#include <string>

#include <base/bind.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "shill/net/byte_string.h"

using testing::_;
using testing::InSequence;
using testing::Mock;
using testing::Return;
using testing::Test;

namespace shill {

class AttributeListTest : public Test {
 public:
  MOCK_METHOD2(AttributeMethod, bool(int id, const ByteString& value));

 protected:
  static const uint16_t kHeaderLength = 4;
  static const uint16_t kType1 = 1;
  static const uint16_t kType2 = 2;
  static const uint16_t kType3 = 3;

  static ByteString MakeNetlinkAttribute(uint16_t len,
                                         uint16_t type,
                                         const std::string& payload) {
    nlattr attribute{ len, type };
    ByteString data(reinterpret_cast<const char*>(&attribute),
                    sizeof(attribute));
    data.Append(ByteString(payload, false));
    return data;
  }

  static ByteString MakePaddedNetlinkAttribute(uint16_t len,
                                               uint16_t type,
                                               const std::string& payload) {
    ByteString data(MakeNetlinkAttribute(len, type, payload));
    ByteString padding(NLA_ALIGN(data.GetLength()) - data.GetLength());
    data.Append(padding);
    return data;
  }
};

MATCHER_P(PayloadIs, payload, "") {
  return arg.Equals(ByteString(std::string(payload), false));
}

TEST_F(AttributeListTest, IterateEmptyPayload) {
  EXPECT_CALL(*this, AttributeMethod(_, _)).Times(0);
  AttributeListRefPtr list(new AttributeList());
  EXPECT_TRUE(list->IterateAttributes(
      ByteString(), 0,
      base::Bind(&AttributeListTest::AttributeMethod, base::Unretained(this))));
}

TEST_F(AttributeListTest, IteratePayload) {
  ByteString payload;
  payload.Append(MakePaddedNetlinkAttribute(
      kHeaderLength + 10, kType1, "0123456789"));
  const uint16_t kLength1 = kHeaderLength + 10 + 2;  // 2 bytes padding.
  ASSERT_EQ(kLength1, payload.GetLength());
  payload.Append(MakePaddedNetlinkAttribute(kHeaderLength + 3, kType2, "123"));
  const uint16_t kLength2 = kLength1 + kHeaderLength + 3 + 1;  // 1 byte pad.
  ASSERT_EQ(kLength2, payload.GetLength());

  payload.Append(MakeNetlinkAttribute(kHeaderLength + 5, kType3, "12345"));
  const uint16_t kLength3 = kLength2 + kHeaderLength + 5;
  ASSERT_EQ(kLength3, payload.GetLength());

  InSequence seq;
  EXPECT_CALL(*this, AttributeMethod(kType1, PayloadIs("0123456789")))
      .WillOnce(Return(true));
  EXPECT_CALL(*this, AttributeMethod(kType2, PayloadIs("123")))
      .WillOnce(Return(true));
  EXPECT_CALL(*this, AttributeMethod(kType3, PayloadIs("12345")))
      .WillOnce(Return(true));
  AttributeListRefPtr list(new AttributeList());
  EXPECT_TRUE(list->IterateAttributes(
      payload, 0,
      base::Bind(&AttributeListTest::AttributeMethod, base::Unretained(this))));
  Mock::VerifyAndClearExpectations(this);

  // If a valid offset is provided only the attributes that follow should
  // be enumerated.
  EXPECT_CALL(*this, AttributeMethod(kType1, _)).Times(0);
  EXPECT_CALL(*this, AttributeMethod(kType2, PayloadIs("123")))
      .WillOnce(Return(true));
  EXPECT_CALL(*this, AttributeMethod(kType3, PayloadIs("12345")))
      .WillOnce(Return(true));
  EXPECT_TRUE(list->IterateAttributes(
      payload, kLength1,
      base::Bind(&AttributeListTest::AttributeMethod, base::Unretained(this))));
  Mock::VerifyAndClearExpectations(this);

  // If one of the attribute methods returns false, the iteration should abort.
  EXPECT_CALL(*this, AttributeMethod(kType1, PayloadIs("0123456789")))
      .WillOnce(Return(true));
  EXPECT_CALL(*this, AttributeMethod(kType2, PayloadIs("123")))
      .WillOnce(Return(false));
  EXPECT_CALL(*this, AttributeMethod(kType3, PayloadIs("12345"))).Times(0);
  EXPECT_FALSE(list->IterateAttributes(
      payload, 0,
      base::Bind(&AttributeListTest::AttributeMethod, base::Unretained(this))));
  Mock::VerifyAndClearExpectations(this);
}

TEST_F(AttributeListTest, SmallPayloads) {
  // A payload must be at least 4 bytes long to incorporate the nlattr header.
  EXPECT_CALL(*this, AttributeMethod(_, _)).Times(0);
  AttributeListRefPtr list(new AttributeList());
  EXPECT_FALSE(list->IterateAttributes(
      MakeNetlinkAttribute(kHeaderLength - 1, kType1, "0123"), 0,
      base::Bind(&AttributeListTest::AttributeMethod, base::Unretained(this))));
  Mock::VerifyAndClearExpectations(this);

  // This is a minimal valid payload.
  EXPECT_CALL(*this, AttributeMethod(
      kType2, PayloadIs(""))).WillOnce(Return(true));
  EXPECT_TRUE(list->IterateAttributes(
      MakeNetlinkAttribute(kHeaderLength, kType2, ""), 0,
      base::Bind(&AttributeListTest::AttributeMethod, base::Unretained(this))));
  Mock::VerifyAndClearExpectations(this);

  // This is a minmal payload except there are not enough bytes to retrieve
  // the attribute value.
  const uint16_t kType3 = 1;
  EXPECT_CALL(*this, AttributeMethod(_, _)).Times(0);
  EXPECT_FALSE(list->IterateAttributes(
      MakeNetlinkAttribute(kHeaderLength + 1, kType3, ""), 0,
      base::Bind(&AttributeListTest::AttributeMethod, base::Unretained(this))));
}

TEST_F(AttributeListTest, TrailingGarbage) {
  // +---------+
  // | Attr #1 |
  // +-+-+-+-+-+
  // |LEN|TYP|0|
  // +-+-+-+-+-+
  // Well formed frame.
  ByteString payload(MakeNetlinkAttribute(kHeaderLength + 1, kType1, "0"));
  EXPECT_CALL(*this, AttributeMethod(kType1, PayloadIs("0")))
      .WillOnce(Return(true));
  AttributeListRefPtr list(new AttributeList());
  EXPECT_TRUE(list->IterateAttributes(
      payload, 0,
      base::Bind(&AttributeListTest::AttributeMethod, base::Unretained(this))));
  Mock::VerifyAndClearExpectations(this);

  // +---------------+
  // | Attr #1 + pad |
  // +-+-+-+-+-+-+-+-+
  // |LEN|TYP|0|1|2|3|
  // +-+-+-+-+-+-+-+-+
  // "123" assumed to be padding for attr1.
  payload.Append(ByteString(std::string("123"), false));
  EXPECT_CALL(*this, AttributeMethod(kType1, PayloadIs("0")))
      .WillOnce(Return(true));
  EXPECT_TRUE(list->IterateAttributes(
      payload, 0,
      base::Bind(&AttributeListTest::AttributeMethod, base::Unretained(this))));
  Mock::VerifyAndClearExpectations(this);

  // +---------------+-----+
  // | Attr #1 + pad |RUNT |
  // +-+-+-+-+-+-+-+-+-+-+-+
  // |LEN|TYP|0|1|2|3|4|5|6|
  // +-+-+-+-+-+-+-+-+-+-+-+
  // "456" is acceptable since it is not long enough to complete an netlink
  // attribute header.
  payload.Append(ByteString(std::string("456"), false));
  EXPECT_CALL(*this, AttributeMethod(kType1, PayloadIs("0")))
      .WillOnce(Return(true));
  EXPECT_TRUE(list->IterateAttributes(
      payload, 0,
      base::Bind(&AttributeListTest::AttributeMethod, base::Unretained(this))));
  Mock::VerifyAndClearExpectations(this);

  // +---------------+-------+
  // | Attr #1 + pad |Broken |
  // +-+-+-+-+-+-+-+-+-+-+-+-+
  // |LEN|TYP|0|1|2|3|4|5|6|7|
  // +-+-+-+-+-+-+-+-+-+-+-+-+
  // This is a broken frame, since '4567' can be interpreted as a complete
  // nlatter header, but is malformed since there is not enough payload to
  // satisfy the "length" parameter.
  payload.Append(ByteString(std::string("7"), false));
  EXPECT_CALL(*this, AttributeMethod(kType1, PayloadIs("0")))
      .WillOnce(Return(true));
  EXPECT_FALSE(list->IterateAttributes(
      payload, 0,
      base::Bind(&AttributeListTest::AttributeMethod, base::Unretained(this))));
  Mock::VerifyAndClearExpectations(this);
}

}  // namespace shill
