// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// 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.

#include "starboard/common/scoped_ptr.h"
#include "starboard/configuration.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace starboard {
namespace nplb {
namespace {

bool IsAligned(void* pointer, size_t alignment) {
  return (reinterpret_cast<uintptr_t>(pointer) % alignment) == 0;
}

size_t GetAlignment(void* pointer) {
  for (size_t alignment = static_cast<size_t>(1) << ((sizeof(size_t) * 8) - 1);
       alignment != 0; alignment /= 2) {
    if (IsAligned(pointer, alignment)) {
      return alignment;
    }
  }

  return 1;
}

struct AlignedFields {
  char unaligned1;
  SB_ALIGNAS(2) char by_2;
  char unaligned2;
  SB_ALIGNAS(4) char by_4;
  char unaligned3;
  SB_ALIGNAS(8) char by_8;
  char unaligned4;
  SB_ALIGNAS(16) char by_16;
  char unaligned5;
  SB_ALIGNAS(32) char by_32;
  char unaligned6;
  SB_ALIGNAS(64) char by_64;
  char unaligned7;
  SB_ALIGNAS(128) char by_128;
  char unaligned8;
  SB_ALIGNAS(256) char by_256;
  char unaligned9;
};

struct AlignedFieldsOf {
  char unaligned1;
  SB_ALIGNAS(SB_ALIGNOF(void*)) char by_void_star;
  char unaligned2;
  SB_ALIGNAS(SB_ALIGNOF(int)) char by_int;
  char unaligned3;
  SB_ALIGNAS(SB_ALIGNOF(uint64_t)) char by_uint64_t;
  char unaligned4;
};

TEST(SbAlignTest, AlignAsStructFieldOnStack) {
  char unaligned = 0;
  EXPECT_NE(1, unaligned);
  AlignedFields aligned;
  EXPECT_LE(2, GetAlignment(&(aligned.by_2)));
  EXPECT_LE(4, GetAlignment(&(aligned.by_4)));
  EXPECT_LE(8, GetAlignment(&(aligned.by_8)));
  EXPECT_LE(16, GetAlignment(&(aligned.by_16)));
  EXPECT_LE(32, GetAlignment(&(aligned.by_32)));
  EXPECT_LE(64, GetAlignment(&(aligned.by_64)));
  EXPECT_LE(128, GetAlignment(&(aligned.by_128)));
  EXPECT_LE(256, GetAlignment(&(aligned.by_256)));
}

TEST(SbAlignTest, AlignAsStackVariable) {
  char unaligned1 = 1;
  SB_ALIGNAS(2) char by_2;
  char unaligned2 = 2;
  EXPECT_NE(unaligned2, unaligned1);  // These are to try to keep the stack
                                      // variables around.
  SB_ALIGNAS(4) char by_4;
  char unaligned3 = 3;
  EXPECT_NE(unaligned3, unaligned1);
  SB_ALIGNAS(8) char by_8;
  char unaligned4 = 4;
  EXPECT_NE(unaligned4, unaligned1);
  SB_ALIGNAS(16) char by_16;
  char unaligned5 = 5;
  EXPECT_NE(unaligned5, unaligned1);

  EXPECT_LE(2, GetAlignment(&by_2));
  EXPECT_LE(4, GetAlignment(&by_4));
  EXPECT_LE(8, GetAlignment(&by_8));
  EXPECT_LE(16, GetAlignment(&by_16));

  SB_ALIGNAS(32) char by_32;
  char unaligned6 = 6;
  EXPECT_NE(unaligned6, unaligned1);
  SB_ALIGNAS(64) char by_64;
  char unaligned7 = 7;
  EXPECT_NE(unaligned7, unaligned1);
  SB_ALIGNAS(128) char by_128;
  char unaligned8 = 8;
  EXPECT_NE(unaligned8, unaligned1);
  SB_ALIGNAS(256) char by_256;
  char unaligned9 = 9;
  EXPECT_NE(unaligned9, unaligned1);

  EXPECT_LE(32, GetAlignment(&by_32));
  EXPECT_LE(64, GetAlignment(&by_64));
  EXPECT_LE(128, GetAlignment(&by_128));
  EXPECT_LE(256, GetAlignment(&by_256));
}

TEST(SbAlignTest, AlignOf) {
  EXPECT_LE(sizeof(uint8_t), SB_ALIGNOF(uint8_t));
  EXPECT_LE(sizeof(uint16_t), SB_ALIGNOF(uint16_t));
  EXPECT_LE(sizeof(uint32_t), SB_ALIGNOF(uint32_t));
  EXPECT_LE(sizeof(uint64_t), SB_ALIGNOF(uint64_t));
  EXPECT_LE(sizeof(uintptr_t), SB_ALIGNOF(uintptr_t));
  EXPECT_LE(sizeof(void*), SB_ALIGNOF(void*));
}

TEST(SbAlignTest, AlignAsAlignOfStructFieldOnStack) {
  char unaligned = 0;
  EXPECT_NE(1, unaligned);

  AlignedFieldsOf aligned;
  EXPECT_LE(SB_ALIGNOF(void*), GetAlignment(&(aligned.by_void_star)));
  EXPECT_LE(SB_ALIGNOF(int), GetAlignment(&(aligned.by_int)));
  EXPECT_LE(SB_ALIGNOF(uint64_t), GetAlignment(&(aligned.by_uint64_t)));
}

TEST(SbAlignTest, AlignAsAlignOfStackVariable) {
  char unaligned = 0;
  EXPECT_NE(1, unaligned);
  SB_ALIGNAS(SB_ALIGNOF(void*)) char by_void_star;
  SB_ALIGNAS(SB_ALIGNOF(int)) char by_int;
  SB_ALIGNAS(SB_ALIGNOF(uint64_t)) char by_uint64_t;

  EXPECT_LE(SB_ALIGNOF(void*), GetAlignment(&by_void_star));
  EXPECT_LE(SB_ALIGNOF(int), GetAlignment(&by_int));
  EXPECT_LE(SB_ALIGNOF(uint64_t), GetAlignment(&by_uint64_t));
}

}  // namespace
}  // namespace nplb
}  // namespace starboard
