0
0
mirror of https://github.com/nodejs/node.git synced 2024-12-01 16:10:02 +01:00
nodejs/test/cctest/util.cc
Timothy Gu e7a3add531 src: clean up MaybeStackBuffer
- Add IsInvalidated() method
- Add capacity() method for finding out the actual capacity, not the
  current size, of the buffer
- Make IsAllocated() work for invalidated buffers
- Allow multiple calls to AllocateSufficientStorage() and Invalidate()
- Assert buffer is malloc'd in Release()
- Assert buffer has not been invalidated in AllocateSufficientStorage()
- Add more descriptive comments describing the purpose of the methods
- Add cctest for MaybeStackBuffer

PR-URL: https://github.com/nodejs/node/pull/11464
Reviewed-By: Steven R Loomis <srloomis@us.ibm.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
2017-02-24 17:49:41 -08:00

259 lines
7.6 KiB
C++

#include "util.h"
#include "util-inl.h"
#include "gtest/gtest.h"
TEST(UtilTest, ListHead) {
struct Item { node::ListNode<Item> node_; };
typedef node::ListHead<Item, &Item::node_> List;
List list;
EXPECT_TRUE(list.IsEmpty());
Item one;
EXPECT_TRUE(one.node_.IsEmpty());
list.PushBack(&one);
EXPECT_FALSE(list.IsEmpty());
EXPECT_FALSE(one.node_.IsEmpty());
{
List::Iterator it = list.begin();
EXPECT_NE(list.end(), it);
EXPECT_EQ(&one, *it);
++it;
EXPECT_FALSE(it != list.end()); // Iterator only implements != operator.
}
Item two;
list.PushBack(&two);
{
List::Iterator it = list.begin();
EXPECT_NE(list.end(), it);
EXPECT_EQ(&one, *it);
++it;
EXPECT_NE(list.end(), it);
EXPECT_EQ(&two, *it);
++it;
EXPECT_FALSE(it != list.end()); // Iterator only implements != operator.
}
EXPECT_EQ(&one, list.PopFront());
EXPECT_TRUE(one.node_.IsEmpty());
EXPECT_FALSE(list.IsEmpty());
{
List::Iterator it = list.begin();
EXPECT_NE(list.end(), it);
EXPECT_EQ(&two, *it);
++it;
EXPECT_FALSE(it != list.end()); // Iterator only implements != operator.
}
EXPECT_EQ(&two, list.PopFront());
EXPECT_TRUE(two.node_.IsEmpty());
EXPECT_TRUE(list.IsEmpty());
EXPECT_FALSE(list.begin() != list.end());
}
TEST(UtilTest, StringEqualNoCase) {
using node::StringEqualNoCase;
EXPECT_FALSE(StringEqualNoCase("a", "b"));
EXPECT_TRUE(StringEqualNoCase("", ""));
EXPECT_TRUE(StringEqualNoCase("equal", "equal"));
EXPECT_TRUE(StringEqualNoCase("equal", "EQUAL"));
EXPECT_TRUE(StringEqualNoCase("EQUAL", "EQUAL"));
EXPECT_FALSE(StringEqualNoCase("equal", "equals"));
EXPECT_FALSE(StringEqualNoCase("equals", "equal"));
}
TEST(UtilTest, StringEqualNoCaseN) {
using node::StringEqualNoCaseN;
EXPECT_FALSE(StringEqualNoCaseN("a", "b", strlen("a")));
EXPECT_TRUE(StringEqualNoCaseN("", "", strlen("")));
EXPECT_TRUE(StringEqualNoCaseN("equal", "equal", strlen("equal")));
EXPECT_TRUE(StringEqualNoCaseN("equal", "EQUAL", strlen("equal")));
EXPECT_TRUE(StringEqualNoCaseN("EQUAL", "EQUAL", strlen("equal")));
EXPECT_TRUE(StringEqualNoCaseN("equal", "equals", strlen("equal")));
EXPECT_FALSE(StringEqualNoCaseN("equal", "equals", strlen("equals")));
EXPECT_TRUE(StringEqualNoCaseN("equals", "equal", strlen("equal")));
EXPECT_FALSE(StringEqualNoCaseN("equals", "equal", strlen("equals")));
EXPECT_TRUE(StringEqualNoCaseN("abc\0abc", "abc\0efg", strlen("abcdefgh")));
EXPECT_FALSE(StringEqualNoCaseN("abc\0abc", "abcd\0efg", strlen("abcdefgh")));
}
TEST(UtilTest, ToLower) {
using node::ToLower;
EXPECT_EQ('0', ToLower('0'));
EXPECT_EQ('a', ToLower('a'));
EXPECT_EQ('a', ToLower('A'));
}
namespace node {
void LowMemoryNotification() {}
}
#define TEST_AND_FREE(expression) \
do { \
auto pointer = expression; \
EXPECT_NE(nullptr, pointer); \
free(pointer); \
} while (0)
TEST(UtilTest, Malloc) {
using node::Malloc;
TEST_AND_FREE(Malloc<char>(0));
TEST_AND_FREE(Malloc<char>(1));
TEST_AND_FREE(Malloc(0));
TEST_AND_FREE(Malloc(1));
}
TEST(UtilTest, Calloc) {
using node::Calloc;
TEST_AND_FREE(Calloc<char>(0));
TEST_AND_FREE(Calloc<char>(1));
TEST_AND_FREE(Calloc(0));
TEST_AND_FREE(Calloc(1));
}
TEST(UtilTest, UncheckedMalloc) {
using node::UncheckedMalloc;
TEST_AND_FREE(UncheckedMalloc<char>(0));
TEST_AND_FREE(UncheckedMalloc<char>(1));
TEST_AND_FREE(UncheckedMalloc(0));
TEST_AND_FREE(UncheckedMalloc(1));
}
TEST(UtilTest, UncheckedCalloc) {
using node::UncheckedCalloc;
TEST_AND_FREE(UncheckedCalloc<char>(0));
TEST_AND_FREE(UncheckedCalloc<char>(1));
TEST_AND_FREE(UncheckedCalloc(0));
TEST_AND_FREE(UncheckedCalloc(1));
}
template <typename T>
static void MaybeStackBufferBasic() {
using node::MaybeStackBuffer;
MaybeStackBuffer<T> buf;
size_t old_length;
size_t old_capacity;
/* Default constructor */
EXPECT_EQ(0U, buf.length());
EXPECT_FALSE(buf.IsAllocated());
EXPECT_GT(buf.capacity(), buf.length());
/* SetLength() expansion */
buf.SetLength(buf.capacity());
EXPECT_EQ(buf.capacity(), buf.length());
EXPECT_FALSE(buf.IsAllocated());
/* Means of accessing raw buffer */
EXPECT_EQ(buf.out(), *buf);
EXPECT_EQ(&buf[0], *buf);
/* Basic I/O */
for (size_t i = 0; i < buf.length(); i++)
buf[i] = static_cast<T>(i);
for (size_t i = 0; i < buf.length(); i++)
EXPECT_EQ(static_cast<T>(i), buf[i]);
/* SetLengthAndZeroTerminate() */
buf.SetLengthAndZeroTerminate(buf.capacity() - 1);
EXPECT_EQ(buf.capacity() - 1, buf.length());
for (size_t i = 0; i < buf.length(); i++)
EXPECT_EQ(static_cast<T>(i), buf[i]);
buf.SetLength(buf.capacity());
EXPECT_EQ(0, buf[buf.length() - 1]);
/* Initial Realloc */
old_length = buf.length() - 1;
old_capacity = buf.capacity();
buf.AllocateSufficientStorage(buf.capacity() * 2);
EXPECT_EQ(buf.capacity(), buf.length());
EXPECT_TRUE(buf.IsAllocated());
for (size_t i = 0; i < old_length; i++)
EXPECT_EQ(static_cast<T>(i), buf[i]);
EXPECT_EQ(0, buf[old_length]);
/* SetLength() reduction and expansion */
for (size_t i = 0; i < buf.length(); i++)
buf[i] = static_cast<T>(i);
buf.SetLength(10);
for (size_t i = 0; i < buf.length(); i++)
EXPECT_EQ(static_cast<T>(i), buf[i]);
buf.SetLength(buf.capacity());
for (size_t i = 0; i < buf.length(); i++)
EXPECT_EQ(static_cast<T>(i), buf[i]);
/* Subsequent Realloc */
old_length = buf.length();
old_capacity = buf.capacity();
buf.AllocateSufficientStorage(old_capacity * 1.5);
EXPECT_EQ(buf.capacity(), buf.length());
EXPECT_EQ(static_cast<size_t>(old_capacity * 1.5), buf.length());
EXPECT_TRUE(buf.IsAllocated());
for (size_t i = 0; i < old_length; i++)
EXPECT_EQ(static_cast<T>(i), buf[i]);
/* Basic I/O on Realloc'd buffer */
for (size_t i = 0; i < buf.length(); i++)
buf[i] = static_cast<T>(i);
for (size_t i = 0; i < buf.length(); i++)
EXPECT_EQ(static_cast<T>(i), buf[i]);
/* Release() */
T* rawbuf = buf.out();
buf.Release();
EXPECT_EQ(0U, buf.length());
EXPECT_FALSE(buf.IsAllocated());
EXPECT_GT(buf.capacity(), buf.length());
free(rawbuf);
}
TEST(UtilTest, MaybeStackBuffer) {
using node::MaybeStackBuffer;
MaybeStackBufferBasic<uint8_t>();
MaybeStackBufferBasic<uint16_t>();
// Constructor with size parameter
{
MaybeStackBuffer<unsigned char> buf(100);
EXPECT_EQ(100U, buf.length());
EXPECT_FALSE(buf.IsAllocated());
EXPECT_GT(buf.capacity(), buf.length());
buf.SetLength(buf.capacity());
EXPECT_EQ(buf.capacity(), buf.length());
EXPECT_FALSE(buf.IsAllocated());
for (size_t i = 0; i < buf.length(); i++)
buf[i] = static_cast<unsigned char>(i);
for (size_t i = 0; i < buf.length(); i++)
EXPECT_EQ(static_cast<unsigned char>(i), buf[i]);
MaybeStackBuffer<unsigned char> bigbuf(10000);
EXPECT_EQ(10000U, bigbuf.length());
EXPECT_TRUE(bigbuf.IsAllocated());
EXPECT_EQ(bigbuf.length(), bigbuf.capacity());
for (size_t i = 0; i < bigbuf.length(); i++)
bigbuf[i] = static_cast<unsigned char>(i);
for (size_t i = 0; i < bigbuf.length(); i++)
EXPECT_EQ(static_cast<unsigned char>(i), bigbuf[i]);
}
// Invalidated buffer
{
MaybeStackBuffer<char> buf;
buf.Invalidate();
EXPECT_TRUE(buf.IsInvalidated());
EXPECT_FALSE(buf.IsAllocated());
EXPECT_EQ(0U, buf.length());
EXPECT_EQ(0U, buf.capacity());
buf.Invalidate();
EXPECT_TRUE(buf.IsInvalidated());
}
}