mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
[BinaryFormat] Add MessagePack reader/writer
Add support for reading and writing MessagePack, a binary object serialization format which aims to be more compact than text formats like JSON or YAML. The specification can be found at https://github.com/msgpack/msgpack/blob/master/spec.md Will be used for encoding metadata in AMDGPU code objects. Differential Revision: https://reviews.llvm.org/D44429 llvm-svn: 340457
This commit is contained in:
parent
d02128f555
commit
c46ffa9c82
108
include/llvm/BinaryFormat/MsgPack.def
Normal file
108
include/llvm/BinaryFormat/MsgPack.def
Normal file
@ -0,0 +1,108 @@
|
||||
//===- MsgPack.def - MessagePack definitions --------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Macros for running through MessagePack enumerators.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if !( \
|
||||
defined HANDLE_MP_FIRST_BYTE || defined HANDLE_MP_FIX_BITS || \
|
||||
defined HANDLE_MP_FIX_BITS_MASK || defined HANDLE_MP_FIX_MAX || \
|
||||
defined HANDLE_MP_FIX_LEN || defined HANDLE_MP_FIX_MIN)
|
||||
#error "Missing macro definition of HANDLE_MP*"
|
||||
#endif
|
||||
|
||||
#ifndef HANDLE_MP_FIRST_BYTE
|
||||
#define HANDLE_MP_FIRST_BYTE(ID, NAME)
|
||||
#endif
|
||||
|
||||
#ifndef HANDLE_MP_FIX_BITS
|
||||
#define HANDLE_MP_FIX_BITS(ID, NAME)
|
||||
#endif
|
||||
|
||||
#ifndef HANDLE_MP_FIX_BITS_MASK
|
||||
#define HANDLE_MP_FIX_BITS_MASK(ID, NAME)
|
||||
#endif
|
||||
|
||||
#ifndef HANDLE_MP_FIX_MAX
|
||||
#define HANDLE_MP_FIX_MAX(ID, NAME)
|
||||
#endif
|
||||
|
||||
#ifndef HANDLE_MP_FIX_LEN
|
||||
#define HANDLE_MP_FIX_LEN(ID, NAME)
|
||||
#endif
|
||||
|
||||
#ifndef HANDLE_MP_FIX_MIN
|
||||
#define HANDLE_MP_FIX_MIN(ID, NAME)
|
||||
#endif
|
||||
|
||||
HANDLE_MP_FIRST_BYTE(0xc0, Nil)
|
||||
HANDLE_MP_FIRST_BYTE(0xc2, False)
|
||||
HANDLE_MP_FIRST_BYTE(0xc3, True)
|
||||
HANDLE_MP_FIRST_BYTE(0xc4, Bin8)
|
||||
HANDLE_MP_FIRST_BYTE(0xc5, Bin16)
|
||||
HANDLE_MP_FIRST_BYTE(0xc6, Bin32)
|
||||
HANDLE_MP_FIRST_BYTE(0xc7, Ext8)
|
||||
HANDLE_MP_FIRST_BYTE(0xc8, Ext16)
|
||||
HANDLE_MP_FIRST_BYTE(0xc9, Ext32)
|
||||
HANDLE_MP_FIRST_BYTE(0xca, Float32)
|
||||
HANDLE_MP_FIRST_BYTE(0xcb, Float64)
|
||||
HANDLE_MP_FIRST_BYTE(0xcc, UInt8)
|
||||
HANDLE_MP_FIRST_BYTE(0xcd, UInt16)
|
||||
HANDLE_MP_FIRST_BYTE(0xce, UInt32)
|
||||
HANDLE_MP_FIRST_BYTE(0xcf, UInt64)
|
||||
HANDLE_MP_FIRST_BYTE(0xd0, Int8)
|
||||
HANDLE_MP_FIRST_BYTE(0xd1, Int16)
|
||||
HANDLE_MP_FIRST_BYTE(0xd2, Int32)
|
||||
HANDLE_MP_FIRST_BYTE(0xd3, Int64)
|
||||
HANDLE_MP_FIRST_BYTE(0xd4, FixExt1)
|
||||
HANDLE_MP_FIRST_BYTE(0xd5, FixExt2)
|
||||
HANDLE_MP_FIRST_BYTE(0xd6, FixExt4)
|
||||
HANDLE_MP_FIRST_BYTE(0xd7, FixExt8)
|
||||
HANDLE_MP_FIRST_BYTE(0xd8, FixExt16)
|
||||
HANDLE_MP_FIRST_BYTE(0xd9, Str8)
|
||||
HANDLE_MP_FIRST_BYTE(0xda, Str16)
|
||||
HANDLE_MP_FIRST_BYTE(0xdb, Str32)
|
||||
HANDLE_MP_FIRST_BYTE(0xdc, Array16)
|
||||
HANDLE_MP_FIRST_BYTE(0xdd, Array32)
|
||||
HANDLE_MP_FIRST_BYTE(0xde, Map16)
|
||||
HANDLE_MP_FIRST_BYTE(0xdf, Map32)
|
||||
|
||||
HANDLE_MP_FIX_BITS(0x00, PositiveInt)
|
||||
HANDLE_MP_FIX_BITS(0x80, Map)
|
||||
HANDLE_MP_FIX_BITS(0x90, Array)
|
||||
HANDLE_MP_FIX_BITS(0xa0, String)
|
||||
HANDLE_MP_FIX_BITS(0xe0, NegativeInt)
|
||||
|
||||
HANDLE_MP_FIX_BITS_MASK(0x80, PositiveInt)
|
||||
HANDLE_MP_FIX_BITS_MASK(0xf0, Map)
|
||||
HANDLE_MP_FIX_BITS_MASK(0xf0, Array)
|
||||
HANDLE_MP_FIX_BITS_MASK(0xe0, String)
|
||||
HANDLE_MP_FIX_BITS_MASK(0xe0, NegativeInt)
|
||||
|
||||
HANDLE_MP_FIX_MAX(0x7f, PositiveInt)
|
||||
HANDLE_MP_FIX_MAX(0x0f, Map)
|
||||
HANDLE_MP_FIX_MAX(0x0f, Array)
|
||||
HANDLE_MP_FIX_MAX(0x1f, String)
|
||||
|
||||
HANDLE_MP_FIX_LEN(0x01, Ext1)
|
||||
HANDLE_MP_FIX_LEN(0x02, Ext2)
|
||||
HANDLE_MP_FIX_LEN(0x04, Ext4)
|
||||
HANDLE_MP_FIX_LEN(0x08, Ext8)
|
||||
HANDLE_MP_FIX_LEN(0x10, Ext16)
|
||||
|
||||
HANDLE_MP_FIX_MIN(-0x20, NegativeInt)
|
||||
|
||||
#undef HANDLE_MP_FIRST_BYTE
|
||||
#undef HANDLE_MP_FIX_BITS
|
||||
#undef HANDLE_MP_FIX_BITS_MASK
|
||||
#undef HANDLE_MP_FIX_MAX
|
||||
#undef HANDLE_MP_FIX_LEN
|
||||
#undef HANDLE_MP_FIX_MIN
|
93
include/llvm/BinaryFormat/MsgPack.h
Normal file
93
include/llvm/BinaryFormat/MsgPack.h
Normal file
@ -0,0 +1,93 @@
|
||||
//===-- MsgPack.h - MessagePack Constants -----------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file contains constants used for implementing MessagePack support.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_BINARYFORMAT_MSGPACK_H
|
||||
#define LLVM_BINARYFORMAT_MSGPACK_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace msgpack {
|
||||
|
||||
/// The endianness of all multi-byte encoded values in MessagePack.
|
||||
constexpr support::endianness Endianness = support::big;
|
||||
|
||||
/// The first byte identifiers of MessagePack object formats.
|
||||
namespace FirstByte {
|
||||
#define HANDLE_MP_FIRST_BYTE(ID, NAME) constexpr uint8_t NAME = ID;
|
||||
#include "llvm/BinaryFormat/MsgPack.def"
|
||||
}
|
||||
|
||||
/// Most significant bits used to identify "Fix" variants in MessagePack.
|
||||
///
|
||||
/// For example, FixStr objects encode their size in the five least significant
|
||||
/// bits of their first byte, which is identified by the bit pattern "101" in
|
||||
/// the three most significant bits. So FixBits::String contains 0b10100000.
|
||||
///
|
||||
/// A corresponding mask of the bit pattern is found in \c FixBitsMask.
|
||||
namespace FixBits {
|
||||
#define HANDLE_MP_FIX_BITS(ID, NAME) constexpr uint8_t NAME = ID;
|
||||
#include "llvm/BinaryFormat/MsgPack.def"
|
||||
}
|
||||
|
||||
/// Mask of bits used to identify "Fix" variants in MessagePack.
|
||||
///
|
||||
/// For example, FixStr objects encode their size in the five least significant
|
||||
/// bits of their first byte, which is identified by the bit pattern "101" in
|
||||
/// the three most significant bits. So FixBitsMask::String contains
|
||||
/// 0b11100000.
|
||||
///
|
||||
/// The corresponding bit pattern to mask for is found in FixBits.
|
||||
namespace FixBitsMask {
|
||||
#define HANDLE_MP_FIX_BITS_MASK(ID, NAME) constexpr uint8_t NAME = ID;
|
||||
#include "llvm/BinaryFormat/MsgPack.def"
|
||||
}
|
||||
|
||||
/// The maximum value or size encodable in "Fix" variants of formats.
|
||||
///
|
||||
/// For example, FixStr objects encode their size in the five least significant
|
||||
/// bits of their first byte, so the largest encodable size is 0b00011111.
|
||||
namespace FixMax {
|
||||
#define HANDLE_MP_FIX_MAX(ID, NAME) constexpr uint8_t NAME = ID;
|
||||
#include "llvm/BinaryFormat/MsgPack.def"
|
||||
}
|
||||
|
||||
/// The exact size encodable in "Fix" variants of formats.
|
||||
///
|
||||
/// The only objects for which an exact size makes sense are of Extension type.
|
||||
///
|
||||
/// For example, FixExt4 stores an extension type containing exactly four bytes.
|
||||
namespace FixLen {
|
||||
#define HANDLE_MP_FIX_LEN(ID, NAME) constexpr uint8_t NAME = ID;
|
||||
#include "llvm/BinaryFormat/MsgPack.def"
|
||||
}
|
||||
|
||||
/// The minimum value or size encodable in "Fix" variants of formats.
|
||||
///
|
||||
/// The only object for which a minimum makes sense is a negative FixNum.
|
||||
///
|
||||
/// Negative FixNum objects encode their signed integer value in one byte, but
|
||||
/// they must have the pattern "111" as their three most significant bits. This
|
||||
/// means all values are negative, and the smallest representable value is
|
||||
/// 0b11100000.
|
||||
namespace FixMin {
|
||||
#define HANDLE_MP_FIX_MIN(ID, NAME) constexpr int8_t NAME = ID;
|
||||
#include "llvm/BinaryFormat/MsgPack.def"
|
||||
}
|
||||
|
||||
} // end namespace msgpack
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_BINARYFORMAT_MSGPACK_H
|
148
include/llvm/BinaryFormat/MsgPackReader.h
Normal file
148
include/llvm/BinaryFormat/MsgPackReader.h
Normal file
@ -0,0 +1,148 @@
|
||||
//===- MsgPackReader.h - Simple MsgPack reader ------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This is a MessagePack reader.
|
||||
///
|
||||
/// See https://github.com/msgpack/msgpack/blob/master/spec.md for the full
|
||||
/// standard.
|
||||
///
|
||||
/// Typical usage:
|
||||
/// \code
|
||||
/// StringRef input = GetInput();
|
||||
/// msgpack::Reader MPReader(input);
|
||||
/// msgpack::Object Obj;
|
||||
///
|
||||
/// while (MPReader.read(Obj)) {
|
||||
/// switch (Obj.Kind) {
|
||||
/// case msgpack::Type::Int:
|
||||
// // Use Obj.Int
|
||||
/// break;
|
||||
/// // ...
|
||||
/// }
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_MSGPACKREADER_H
|
||||
#define LLVM_SUPPORT_MSGPACKREADER_H
|
||||
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstdint>
|
||||
|
||||
namespace llvm {
|
||||
namespace msgpack {
|
||||
|
||||
/// MessagePack types as defined in the standard, with the exception of Integer
|
||||
/// being divided into a signed Int and unsigned UInt variant in order to map
|
||||
/// directly to C++ types.
|
||||
///
|
||||
/// The types map onto corresponding union members of the \c Object struct.
|
||||
enum class Type : uint8_t {
|
||||
Int,
|
||||
UInt,
|
||||
Nil,
|
||||
Boolean,
|
||||
Float,
|
||||
String,
|
||||
Binary,
|
||||
Array,
|
||||
Map,
|
||||
Extension,
|
||||
};
|
||||
|
||||
/// Extension types are composed of a user-defined type ID and an uninterpreted
|
||||
/// sequence of bytes.
|
||||
struct ExtensionType {
|
||||
/// User-defined extension type.
|
||||
int8_t Type;
|
||||
/// Raw bytes of the extension object.
|
||||
StringRef Bytes;
|
||||
};
|
||||
|
||||
/// MessagePack object, represented as a tagged union of C++ types.
|
||||
///
|
||||
/// All types except \c Type::Nil (which has only one value, and so is
|
||||
/// completely represented by the \c Kind itself) map to a exactly one union
|
||||
/// member.
|
||||
struct Object {
|
||||
Type Kind;
|
||||
union {
|
||||
/// Value for \c Type::Int.
|
||||
int64_t Int;
|
||||
/// Value for \c Type::Uint.
|
||||
uint64_t UInt;
|
||||
/// Value for \c Type::Boolean.
|
||||
bool Bool;
|
||||
/// Value for \c Type::Float.
|
||||
double Float;
|
||||
/// Value for \c Type::String and \c Type::Binary.
|
||||
StringRef Raw;
|
||||
/// Value for \c Type::Array and \c Type::Map.
|
||||
size_t Length;
|
||||
/// Value for \c Type::Extension.
|
||||
ExtensionType Extension;
|
||||
};
|
||||
|
||||
Object() : Kind(Type::Int), Int(0) {}
|
||||
};
|
||||
|
||||
/// Reads MessagePack objects from memory, one at a time.
|
||||
class Reader {
|
||||
public:
|
||||
/// Construct a reader, keeping a reference to the \p InputBuffer.
|
||||
Reader(MemoryBufferRef InputBuffer);
|
||||
/// Construct a reader, keeping a reference to the \p Input.
|
||||
Reader(StringRef Input);
|
||||
|
||||
Reader(const Reader &) = delete;
|
||||
Reader &operator=(const Reader &) = delete;
|
||||
|
||||
/// Read one object from the input buffer, advancing past it.
|
||||
///
|
||||
/// The \p Obj is updated with the kind of the object read, and the
|
||||
/// corresponding union member is updated.
|
||||
///
|
||||
/// For the collection objects (Array and Map), only the length is read, and
|
||||
/// the caller must make and additional \c N calls (in the case of Array) or
|
||||
/// \c N*2 calls (in the case of Map) to \c Read to retrieve the collection
|
||||
/// elements.
|
||||
///
|
||||
/// \param [out] Obj filled with next object on success.
|
||||
///
|
||||
/// \returns true when object successfully read, false when at end of
|
||||
/// input (and so \p Obj was not updated), otherwise an error.
|
||||
Expected<bool> read(Object &Obj);
|
||||
|
||||
private:
|
||||
MemoryBufferRef InputBuffer;
|
||||
StringRef::iterator Current;
|
||||
StringRef::iterator End;
|
||||
|
||||
size_t remainingSpace() {
|
||||
// The rest of the code maintains the invariant that End >= Current, so
|
||||
// that this cast is always defined behavior.
|
||||
return static_cast<size_t>(End - Current);
|
||||
}
|
||||
|
||||
template <class T> Expected<bool> readRaw(Object &Obj);
|
||||
template <class T> Expected<bool> readInt(Object &Obj);
|
||||
template <class T> Expected<bool> readUInt(Object &Obj);
|
||||
template <class T> Expected<bool> readLength(Object &Obj);
|
||||
template <class T> Expected<bool> readExt(Object &Obj);
|
||||
Expected<bool> createRaw(Object &Obj, uint32_t Size);
|
||||
Expected<bool> createExt(Object &Obj, uint32_t Size);
|
||||
};
|
||||
|
||||
} // end namespace msgpack
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_SUPPORT_MSGPACKREADER_H
|
131
include/llvm/BinaryFormat/MsgPackWriter.h
Normal file
131
include/llvm/BinaryFormat/MsgPackWriter.h
Normal file
@ -0,0 +1,131 @@
|
||||
//===- MsgPackWriter.h - Simple MsgPack writer ------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file contains a MessagePack writer.
|
||||
///
|
||||
/// See https://github.com/msgpack/msgpack/blob/master/spec.md for the full
|
||||
/// specification.
|
||||
///
|
||||
/// Typical usage:
|
||||
/// \code
|
||||
/// raw_ostream output = GetOutputStream();
|
||||
/// msgpack::Writer MPWriter(output);
|
||||
/// MPWriter.writeNil();
|
||||
/// MPWriter.write(false);
|
||||
/// MPWriter.write("string");
|
||||
/// // ...
|
||||
/// \endcode
|
||||
///
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_MSGPACKPARSER_H
|
||||
#define LLVM_SUPPORT_MSGPACKPARSER_H
|
||||
|
||||
#include "llvm/BinaryFormat/MsgPack.h"
|
||||
#include "llvm/Support/EndianStream.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace msgpack {
|
||||
|
||||
/// Writes MessagePack objects to an output stream, one at a time.
|
||||
class Writer {
|
||||
public:
|
||||
/// Construct a writer, optionally enabling "Compatibility Mode" as defined
|
||||
/// in the MessagePack specification.
|
||||
///
|
||||
/// When in \p Compatible mode, the writer will write \c Str16 formats
|
||||
/// instead of \c Str8 formats, and will refuse to write any \c Bin formats.
|
||||
///
|
||||
/// \param OS stream to output MessagePack objects to.
|
||||
/// \param Compatible when set, write in "Compatibility Mode".
|
||||
Writer(raw_ostream &OS, bool Compatible = false);
|
||||
|
||||
Writer(const Writer &) = delete;
|
||||
Writer &operator=(const Writer &) = delete;
|
||||
|
||||
/// Write a \em Nil to the output stream.
|
||||
///
|
||||
/// The output will be the \em nil format.
|
||||
void writeNil();
|
||||
|
||||
/// Write a \em Boolean to the output stream.
|
||||
///
|
||||
/// The output will be a \em bool format.
|
||||
void write(bool b);
|
||||
|
||||
/// Write a signed integer to the output stream.
|
||||
///
|
||||
/// The output will be in the smallest possible \em int format.
|
||||
///
|
||||
/// The format chosen may be for an unsigned integer.
|
||||
void write(int64_t i);
|
||||
|
||||
/// Write an unsigned integer to the output stream.
|
||||
///
|
||||
/// The output will be in the smallest possible \em int format.
|
||||
void write(uint64_t u);
|
||||
|
||||
/// Write a floating point number to the output stream.
|
||||
///
|
||||
/// The output will be in the smallest possible \em float format.
|
||||
void write(double d);
|
||||
|
||||
/// Write a string to the output stream.
|
||||
///
|
||||
/// The output will be in the smallest possible \em str format.
|
||||
void write(StringRef s);
|
||||
|
||||
/// Write a memory buffer to the output stream.
|
||||
///
|
||||
/// The output will be in the smallest possible \em bin format.
|
||||
///
|
||||
/// \warning Do not use this overload if in \c Compatible mode.
|
||||
void write(MemoryBufferRef Buffer);
|
||||
|
||||
/// Write the header for an \em Array of the given size.
|
||||
///
|
||||
/// The output will be in the smallest possible \em array format.
|
||||
//
|
||||
/// The header contains an identifier for the \em array format used, as well
|
||||
/// as an encoding of the size of the array.
|
||||
///
|
||||
/// N.B. The caller must subsequently call \c Write an additional \p Size
|
||||
/// times to complete the array.
|
||||
void writeArraySize(uint32_t Size);
|
||||
|
||||
/// Write the header for a \em Map of the given size.
|
||||
///
|
||||
/// The output will be in the smallest possible \em map format.
|
||||
//
|
||||
/// The header contains an identifier for the \em map format used, as well
|
||||
/// as an encoding of the size of the map.
|
||||
///
|
||||
/// N.B. The caller must subsequently call \c Write and additional \c Size*2
|
||||
/// times to complete the map. Each even numbered call to \c Write defines a
|
||||
/// new key, and each odd numbered call defines the previous key's value.
|
||||
void writeMapSize(uint32_t Size);
|
||||
|
||||
/// Write a typed memory buffer (an extension type) to the output stream.
|
||||
///
|
||||
/// The output will be in the smallest possible \em ext format.
|
||||
void writeExt(int8_t Type, MemoryBufferRef Buffer);
|
||||
|
||||
private:
|
||||
support::endian::Writer EW;
|
||||
bool Compatible;
|
||||
};
|
||||
|
||||
} // end namespace msgpack
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_SUPPORT_MSGPACKPARSER_H
|
@ -1,6 +1,8 @@
|
||||
add_llvm_library(LLVMBinaryFormat
|
||||
Dwarf.cpp
|
||||
Magic.cpp
|
||||
MsgPackReader.cpp
|
||||
MsgPackWriter.cpp
|
||||
Wasm.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
|
255
lib/BinaryFormat/MsgPackReader.cpp
Normal file
255
lib/BinaryFormat/MsgPackReader.cpp
Normal file
@ -0,0 +1,255 @@
|
||||
//===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file implements a MessagePack reader.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/BinaryFormat/MsgPackReader.h"
|
||||
#include "llvm/BinaryFormat/MsgPack.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::support;
|
||||
using namespace msgpack;
|
||||
|
||||
Reader::Reader(MemoryBufferRef InputBuffer)
|
||||
: InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
|
||||
End(InputBuffer.getBufferEnd()) {}
|
||||
|
||||
Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
|
||||
|
||||
Expected<bool> Reader::read(Object &Obj) {
|
||||
if (Current == End)
|
||||
return false;
|
||||
|
||||
uint8_t FB = static_cast<uint8_t>(*Current++);
|
||||
|
||||
switch (FB) {
|
||||
case FirstByte::Nil:
|
||||
Obj.Kind = Type::Nil;
|
||||
return true;
|
||||
case FirstByte::True:
|
||||
Obj.Kind = Type::Boolean;
|
||||
Obj.Bool = true;
|
||||
return true;
|
||||
case FirstByte::False:
|
||||
Obj.Kind = Type::Boolean;
|
||||
Obj.Bool = false;
|
||||
return true;
|
||||
case FirstByte::Int8:
|
||||
Obj.Kind = Type::Int;
|
||||
return readInt<int8_t>(Obj);
|
||||
case FirstByte::Int16:
|
||||
Obj.Kind = Type::Int;
|
||||
return readInt<int16_t>(Obj);
|
||||
case FirstByte::Int32:
|
||||
Obj.Kind = Type::Int;
|
||||
return readInt<int32_t>(Obj);
|
||||
case FirstByte::Int64:
|
||||
Obj.Kind = Type::Int;
|
||||
return readInt<int64_t>(Obj);
|
||||
case FirstByte::UInt8:
|
||||
Obj.Kind = Type::UInt;
|
||||
return readUInt<uint8_t>(Obj);
|
||||
case FirstByte::UInt16:
|
||||
Obj.Kind = Type::UInt;
|
||||
return readUInt<uint16_t>(Obj);
|
||||
case FirstByte::UInt32:
|
||||
Obj.Kind = Type::UInt;
|
||||
return readUInt<uint32_t>(Obj);
|
||||
case FirstByte::UInt64:
|
||||
Obj.Kind = Type::UInt;
|
||||
return readUInt<uint64_t>(Obj);
|
||||
case FirstByte::Float32:
|
||||
Obj.Kind = Type::Float;
|
||||
if (sizeof(float) > remainingSpace())
|
||||
return make_error<StringError>(
|
||||
"Invalid Float32 with insufficient payload",
|
||||
std::make_error_code(std::errc::invalid_argument));
|
||||
Obj.Float = BitsToFloat(endian::read<uint32_t, Endianness>(Current));
|
||||
Current += sizeof(float);
|
||||
return true;
|
||||
case FirstByte::Float64:
|
||||
Obj.Kind = Type::Float;
|
||||
if (sizeof(double) > remainingSpace())
|
||||
return make_error<StringError>(
|
||||
"Invalid Float64 with insufficient payload",
|
||||
std::make_error_code(std::errc::invalid_argument));
|
||||
Obj.Float = BitsToDouble(endian::read<uint64_t, Endianness>(Current));
|
||||
Current += sizeof(double);
|
||||
return true;
|
||||
case FirstByte::Str8:
|
||||
Obj.Kind = Type::String;
|
||||
return readRaw<uint8_t>(Obj);
|
||||
case FirstByte::Str16:
|
||||
Obj.Kind = Type::String;
|
||||
return readRaw<uint16_t>(Obj);
|
||||
case FirstByte::Str32:
|
||||
Obj.Kind = Type::String;
|
||||
return readRaw<uint32_t>(Obj);
|
||||
case FirstByte::Bin8:
|
||||
Obj.Kind = Type::Binary;
|
||||
return readRaw<uint8_t>(Obj);
|
||||
case FirstByte::Bin16:
|
||||
Obj.Kind = Type::Binary;
|
||||
return readRaw<uint16_t>(Obj);
|
||||
case FirstByte::Bin32:
|
||||
Obj.Kind = Type::Binary;
|
||||
return readRaw<uint32_t>(Obj);
|
||||
case FirstByte::Array16:
|
||||
Obj.Kind = Type::Array;
|
||||
return readLength<uint16_t>(Obj);
|
||||
case FirstByte::Array32:
|
||||
Obj.Kind = Type::Array;
|
||||
return readLength<uint32_t>(Obj);
|
||||
case FirstByte::Map16:
|
||||
Obj.Kind = Type::Map;
|
||||
return readLength<uint16_t>(Obj);
|
||||
case FirstByte::Map32:
|
||||
Obj.Kind = Type::Map;
|
||||
return readLength<uint32_t>(Obj);
|
||||
case FirstByte::FixExt1:
|
||||
Obj.Kind = Type::Extension;
|
||||
return createExt(Obj, FixLen::Ext1);
|
||||
case FirstByte::FixExt2:
|
||||
Obj.Kind = Type::Extension;
|
||||
return createExt(Obj, FixLen::Ext2);
|
||||
case FirstByte::FixExt4:
|
||||
Obj.Kind = Type::Extension;
|
||||
return createExt(Obj, FixLen::Ext4);
|
||||
case FirstByte::FixExt8:
|
||||
Obj.Kind = Type::Extension;
|
||||
return createExt(Obj, FixLen::Ext8);
|
||||
case FirstByte::FixExt16:
|
||||
Obj.Kind = Type::Extension;
|
||||
return createExt(Obj, FixLen::Ext16);
|
||||
case FirstByte::Ext8:
|
||||
Obj.Kind = Type::Extension;
|
||||
return readExt<uint8_t>(Obj);
|
||||
case FirstByte::Ext16:
|
||||
Obj.Kind = Type::Extension;
|
||||
return readExt<uint16_t>(Obj);
|
||||
case FirstByte::Ext32:
|
||||
Obj.Kind = Type::Extension;
|
||||
return readExt<uint32_t>(Obj);
|
||||
}
|
||||
|
||||
if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {
|
||||
Obj.Kind = Type::Int;
|
||||
int8_t I;
|
||||
static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes");
|
||||
memcpy(&I, &FB, sizeof(FB));
|
||||
Obj.Int = I;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {
|
||||
Obj.Kind = Type::UInt;
|
||||
Obj.UInt = FB;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((FB & FixBitsMask::String) == FixBits::String) {
|
||||
Obj.Kind = Type::String;
|
||||
uint8_t Size = FB & ~FixBitsMask::String;
|
||||
return createRaw(Obj, Size);
|
||||
}
|
||||
|
||||
if ((FB & FixBitsMask::Array) == FixBits::Array) {
|
||||
Obj.Kind = Type::Array;
|
||||
Obj.Length = FB & ~FixBitsMask::Array;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((FB & FixBitsMask::Map) == FixBits::Map) {
|
||||
Obj.Kind = Type::Map;
|
||||
Obj.Length = FB & ~FixBitsMask::Map;
|
||||
return true;
|
||||
}
|
||||
|
||||
return make_error<StringError>(
|
||||
"Invalid first byte", std::make_error_code(std::errc::invalid_argument));
|
||||
}
|
||||
|
||||
template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
|
||||
if (sizeof(T) > remainingSpace())
|
||||
return make_error<StringError>(
|
||||
"Invalid Raw with insufficient payload",
|
||||
std::make_error_code(std::errc::invalid_argument));
|
||||
T Size = endian::read<T, Endianness>(Current);
|
||||
Current += sizeof(T);
|
||||
return createRaw(Obj, Size);
|
||||
}
|
||||
|
||||
template <class T> Expected<bool> Reader::readInt(Object &Obj) {
|
||||
if (sizeof(T) > remainingSpace())
|
||||
return make_error<StringError>(
|
||||
"Invalid Int with insufficient payload",
|
||||
std::make_error_code(std::errc::invalid_argument));
|
||||
Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));
|
||||
Current += sizeof(T);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
|
||||
if (sizeof(T) > remainingSpace())
|
||||
return make_error<StringError>(
|
||||
"Invalid Int with insufficient payload",
|
||||
std::make_error_code(std::errc::invalid_argument));
|
||||
Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));
|
||||
Current += sizeof(T);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T> Expected<bool> Reader::readLength(Object &Obj) {
|
||||
if (sizeof(T) > remainingSpace())
|
||||
return make_error<StringError>(
|
||||
"Invalid Map/Array with invalid length",
|
||||
std::make_error_code(std::errc::invalid_argument));
|
||||
Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current));
|
||||
Current += sizeof(T);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T> Expected<bool> Reader::readExt(Object &Obj) {
|
||||
if (sizeof(T) > remainingSpace())
|
||||
return make_error<StringError>(
|
||||
"Invalid Ext with invalid length",
|
||||
std::make_error_code(std::errc::invalid_argument));
|
||||
T Size = endian::read<T, Endianness>(Current);
|
||||
Current += sizeof(T);
|
||||
return createExt(Obj, Size);
|
||||
}
|
||||
|
||||
Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
|
||||
if (Size > remainingSpace())
|
||||
return make_error<StringError>(
|
||||
"Invalid Raw with insufficient payload",
|
||||
std::make_error_code(std::errc::invalid_argument));
|
||||
Obj.Raw = StringRef(Current, Size);
|
||||
Current += Size;
|
||||
return true;
|
||||
}
|
||||
|
||||
Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
|
||||
if (Current == End)
|
||||
return make_error<StringError>(
|
||||
"Invalid Ext with no type",
|
||||
std::make_error_code(std::errc::invalid_argument));
|
||||
Obj.Extension.Type = *Current++;
|
||||
if (Size > remainingSpace())
|
||||
return make_error<StringError>(
|
||||
"Invalid Ext with insufficient payload",
|
||||
std::make_error_code(std::errc::invalid_argument));
|
||||
Obj.Extension.Bytes = StringRef(Current, Size);
|
||||
Current += Size;
|
||||
return true;
|
||||
}
|
208
lib/BinaryFormat/MsgPackWriter.cpp
Normal file
208
lib/BinaryFormat/MsgPackWriter.cpp
Normal file
@ -0,0 +1,208 @@
|
||||
//===- MsgPackWriter.cpp - Simple MsgPack writer ----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file implements a MessagePack writer.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/BinaryFormat/MsgPackWriter.h"
|
||||
#include "llvm/BinaryFormat/MsgPack.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace msgpack;
|
||||
|
||||
Writer::Writer(raw_ostream &OS, bool Compatible)
|
||||
: EW(OS, Endianness), Compatible(Compatible) {}
|
||||
|
||||
void Writer::writeNil() { EW.write(FirstByte::Nil); }
|
||||
|
||||
void Writer::write(bool b) { EW.write(b ? FirstByte::True : FirstByte::False); }
|
||||
|
||||
void Writer::write(int64_t i) {
|
||||
if (i >= 0) {
|
||||
write(static_cast<uint64_t>(i));
|
||||
return;
|
||||
}
|
||||
|
||||
if (i >= FixMin::NegativeInt) {
|
||||
EW.write(static_cast<int8_t>(i));
|
||||
return;
|
||||
}
|
||||
|
||||
if (i >= INT8_MIN) {
|
||||
EW.write(FirstByte::Int8);
|
||||
EW.write(static_cast<int8_t>(i));
|
||||
return;
|
||||
}
|
||||
|
||||
if (i >= INT16_MIN) {
|
||||
EW.write(FirstByte::Int16);
|
||||
EW.write(static_cast<int16_t>(i));
|
||||
return;
|
||||
}
|
||||
|
||||
if (i >= INT32_MIN) {
|
||||
EW.write(FirstByte::Int32);
|
||||
EW.write(static_cast<int32_t>(i));
|
||||
return;
|
||||
}
|
||||
|
||||
EW.write(FirstByte::Int64);
|
||||
EW.write(i);
|
||||
}
|
||||
|
||||
void Writer::write(uint64_t u) {
|
||||
if (u <= FixMax::PositiveInt) {
|
||||
EW.write(static_cast<uint8_t>(u));
|
||||
return;
|
||||
}
|
||||
|
||||
if (u <= UINT8_MAX) {
|
||||
EW.write(FirstByte::UInt8);
|
||||
EW.write(static_cast<uint8_t>(u));
|
||||
return;
|
||||
}
|
||||
|
||||
if (u <= UINT16_MAX) {
|
||||
EW.write(FirstByte::UInt16);
|
||||
EW.write(static_cast<uint16_t>(u));
|
||||
return;
|
||||
}
|
||||
|
||||
if (u <= UINT32_MAX) {
|
||||
EW.write(FirstByte::UInt32);
|
||||
EW.write(static_cast<uint32_t>(u));
|
||||
return;
|
||||
}
|
||||
|
||||
EW.write(FirstByte::UInt64);
|
||||
EW.write(u);
|
||||
}
|
||||
|
||||
void Writer::write(double d) {
|
||||
// If no loss of precision, encode as a Float32.
|
||||
float f = static_cast<float>(d);
|
||||
if (static_cast<double>(f) == d) {
|
||||
EW.write(FirstByte::Float32);
|
||||
EW.write(f);
|
||||
} else {
|
||||
EW.write(FirstByte::Float64);
|
||||
EW.write(d);
|
||||
}
|
||||
}
|
||||
|
||||
void Writer::write(StringRef s) {
|
||||
size_t Size = s.size();
|
||||
|
||||
if (Size <= FixMax::String)
|
||||
EW.write(static_cast<uint8_t>(FixBits::String | Size));
|
||||
else if (!Compatible && Size <= UINT8_MAX) {
|
||||
EW.write(FirstByte::Str8);
|
||||
EW.write(static_cast<uint8_t>(Size));
|
||||
} else if (Size <= UINT16_MAX) {
|
||||
EW.write(FirstByte::Str16);
|
||||
EW.write(static_cast<uint16_t>(Size));
|
||||
} else {
|
||||
assert(Size <= UINT32_MAX && "String object too long to be encoded");
|
||||
EW.write(FirstByte::Str32);
|
||||
EW.write(static_cast<uint32_t>(Size));
|
||||
}
|
||||
|
||||
EW.OS << s;
|
||||
}
|
||||
|
||||
void Writer::write(MemoryBufferRef Buffer) {
|
||||
assert(!Compatible && "Attempt to write Bin format in compatible mode");
|
||||
|
||||
size_t Size = Buffer.getBufferSize();
|
||||
|
||||
if (Size <= UINT8_MAX) {
|
||||
EW.write(FirstByte::Bin8);
|
||||
EW.write(static_cast<uint8_t>(Size));
|
||||
} else if (Size <= UINT16_MAX) {
|
||||
EW.write(FirstByte::Bin16);
|
||||
EW.write(static_cast<uint16_t>(Size));
|
||||
} else {
|
||||
assert(Size <= UINT32_MAX && "Binary object too long to be encoded");
|
||||
EW.write(FirstByte::Bin32);
|
||||
EW.write(static_cast<uint32_t>(Size));
|
||||
}
|
||||
|
||||
EW.OS.write(Buffer.getBufferStart(), Size);
|
||||
}
|
||||
|
||||
void Writer::writeArraySize(uint32_t Size) {
|
||||
if (Size <= FixMax::Array) {
|
||||
EW.write(static_cast<uint8_t>(FixBits::Array | Size));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Size <= UINT16_MAX) {
|
||||
EW.write(FirstByte::Array16);
|
||||
EW.write(static_cast<uint16_t>(Size));
|
||||
return;
|
||||
}
|
||||
|
||||
EW.write(FirstByte::Array32);
|
||||
EW.write(Size);
|
||||
}
|
||||
|
||||
void Writer::writeMapSize(uint32_t Size) {
|
||||
if (Size <= FixMax::Map) {
|
||||
EW.write(static_cast<uint8_t>(FixBits::Map | Size));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Size <= UINT16_MAX) {
|
||||
EW.write(FirstByte::Map16);
|
||||
EW.write(static_cast<uint16_t>(Size));
|
||||
return;
|
||||
}
|
||||
|
||||
EW.write(FirstByte::Map32);
|
||||
EW.write(Size);
|
||||
}
|
||||
|
||||
void Writer::writeExt(int8_t Type, MemoryBufferRef Buffer) {
|
||||
size_t Size = Buffer.getBufferSize();
|
||||
|
||||
switch (Size) {
|
||||
case FixLen::Ext1:
|
||||
EW.write(FirstByte::FixExt1);
|
||||
break;
|
||||
case FixLen::Ext2:
|
||||
EW.write(FirstByte::FixExt2);
|
||||
break;
|
||||
case FixLen::Ext4:
|
||||
EW.write(FirstByte::FixExt4);
|
||||
break;
|
||||
case FixLen::Ext8:
|
||||
EW.write(FirstByte::FixExt8);
|
||||
break;
|
||||
case FixLen::Ext16:
|
||||
EW.write(FirstByte::FixExt16);
|
||||
break;
|
||||
default:
|
||||
if (Size <= UINT8_MAX) {
|
||||
EW.write(FirstByte::Ext8);
|
||||
EW.write(static_cast<uint8_t>(Size));
|
||||
} else if (Size <= UINT16_MAX) {
|
||||
EW.write(FirstByte::Ext16);
|
||||
EW.write(static_cast<uint16_t>(Size));
|
||||
} else {
|
||||
assert(Size <= UINT32_MAX && "Ext size too large to be encoded");
|
||||
EW.write(FirstByte::Ext32);
|
||||
EW.write(static_cast<uint32_t>(Size));
|
||||
}
|
||||
}
|
||||
|
||||
EW.write(Type);
|
||||
EW.OS.write(Buffer.getBufferStart(), Size);
|
||||
}
|
@ -5,6 +5,8 @@ set(LLVM_LINK_COMPONENTS
|
||||
add_llvm_unittest(BinaryFormatTests
|
||||
DwarfTest.cpp
|
||||
MachOTest.cpp
|
||||
MsgPackReaderTest.cpp
|
||||
MsgPackWriterTest.cpp
|
||||
TestFileMagic.cpp
|
||||
)
|
||||
|
||||
|
891
unittests/BinaryFormat/MsgPackReaderTest.cpp
Normal file
891
unittests/BinaryFormat/MsgPackReaderTest.cpp
Normal file
@ -0,0 +1,891 @@
|
||||
//===- MsgPackReaderTest.cpp ------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/BinaryFormat/MsgPackReader.h"
|
||||
#include "llvm/BinaryFormat/MsgPack.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::msgpack;
|
||||
|
||||
struct MsgPackReader : testing::Test {
|
||||
std::string Buffer;
|
||||
Object Obj;
|
||||
};
|
||||
|
||||
TEST_F(MsgPackReader, TestReadMultiple) {
|
||||
Buffer = "\xc0\xc2";
|
||||
Reader MPReader(Buffer);
|
||||
{
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Nil);
|
||||
}
|
||||
{
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Boolean);
|
||||
EXPECT_EQ(Obj.Bool, false);
|
||||
}
|
||||
{
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_FALSE(*ContinueOrErr);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadNil) {
|
||||
Buffer = "\xc0";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Nil);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadBoolFalse) {
|
||||
Buffer = "\xc2";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Boolean);
|
||||
EXPECT_EQ(Obj.Bool, false);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadBoolTrue) {
|
||||
Buffer = "\xc3";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Boolean);
|
||||
EXPECT_EQ(Obj.Bool, true);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixNegativeInt) {
|
||||
// Positive values will be written in a UInt form, so max FixNegativeInt is -1
|
||||
//
|
||||
// FixNegativeInt form bitpattern starts with 111, so min FixNegativeInt
|
||||
// is 11100000 = -32
|
||||
for (int8_t i = -1; i >= -32; --i) {
|
||||
Buffer.assign(1, static_cast<char>(i));
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Int);
|
||||
EXPECT_EQ(Obj.Int, i);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadInt8Max) {
|
||||
Buffer = "\xd0\x7f";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Int);
|
||||
EXPECT_EQ(Obj.Int, INT8_MAX);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadInt8Zero) {
|
||||
Buffer.assign("\xd0\x00", 2);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Int);
|
||||
EXPECT_EQ(Obj.Int, 0);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadInt8Min) {
|
||||
Buffer = "\xd0\x80";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Int);
|
||||
EXPECT_EQ(Obj.Int, INT8_MIN);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadInt16Max) {
|
||||
Buffer = "\xd1\x7f\xff";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Int);
|
||||
EXPECT_EQ(Obj.Int, INT16_MAX);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadInt16Zero) {
|
||||
Buffer.assign("\xd1\x00\x00", 3);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Int);
|
||||
EXPECT_EQ(Obj.Int, 0);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadInt16Min) {
|
||||
Buffer.assign("\xd1\x80\x00", 3);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Int);
|
||||
EXPECT_EQ(Obj.Int, INT16_MIN);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadInt32Max) {
|
||||
Buffer = "\xd2\x7f\xff\xff\xff";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Int);
|
||||
EXPECT_EQ(Obj.Int, INT32_MAX);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadInt32Zero) {
|
||||
Buffer.assign("\xd2\x00\x00\x00\x00", 5);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Int);
|
||||
EXPECT_EQ(Obj.Int, 0);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadInt32Min) {
|
||||
Buffer.assign("\xd2\x80\x00\x00\x00", 5);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Int);
|
||||
EXPECT_EQ(Obj.Int, INT32_MIN);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadInt64Max) {
|
||||
Buffer = "\xd3\x7f\xff\xff\xff\xff\xff\xff\xff";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Int);
|
||||
EXPECT_EQ(Obj.Int, INT64_MAX);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadInt64Zero) {
|
||||
Buffer.assign("\xd3\x00\x00\x00\x00\x00\x00\x00\x00", 9);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Int);
|
||||
EXPECT_EQ(Obj.Int, 0);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadInt64Min) {
|
||||
Buffer.assign("\xd3\x80\x00\x00\x00\x00\x00\x00\x00", 9);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Int);
|
||||
EXPECT_EQ(Obj.Int, INT64_MIN);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixPositiveInt) {
|
||||
// FixPositiveInt form bitpattern starts with 0, so max FixPositiveInt
|
||||
// is 01111111 = 127
|
||||
for (uint64_t u = 0; u <= 127; ++u) {
|
||||
Buffer.assign(1, static_cast<char>(u));
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::UInt);
|
||||
EXPECT_EQ(Obj.UInt, u);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadUInt8Zero) {
|
||||
Buffer.assign("\xcc\x00", 2);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::UInt);
|
||||
EXPECT_EQ(Obj.UInt, 0u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadUInt8One) {
|
||||
Buffer = "\xcc\x01";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::UInt);
|
||||
EXPECT_EQ(Obj.UInt, 1u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadUInt8Max) {
|
||||
Buffer = "\xcc\xff";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::UInt);
|
||||
EXPECT_EQ(Obj.UInt, static_cast<uint8_t>(UINT8_MAX));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadUInt16Zero) {
|
||||
Buffer.assign("\xcd\x00\x00", 3);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::UInt);
|
||||
EXPECT_EQ(Obj.UInt, 0u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadUInt16One) {
|
||||
Buffer.assign("\xcd\x00\x01", 3);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::UInt);
|
||||
EXPECT_EQ(Obj.UInt, 1u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadUInt16Max) {
|
||||
Buffer = "\xcd\xff\xff";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::UInt);
|
||||
EXPECT_EQ(Obj.UInt, static_cast<uint16_t>(UINT16_MAX));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadUInt32Zero) {
|
||||
Buffer.assign("\xce\x00\x00\x00\x00", 5);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::UInt);
|
||||
EXPECT_EQ(Obj.UInt, 0u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadUInt32One) {
|
||||
Buffer.assign("\xce\x00\x00\x00\x01", 5);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::UInt);
|
||||
EXPECT_EQ(Obj.UInt, 1u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadUInt32Max) {
|
||||
Buffer = "\xce\xff\xff\xff\xff";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::UInt);
|
||||
EXPECT_EQ(Obj.UInt, static_cast<uint32_t>(UINT32_MAX));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadUInt64Zero) {
|
||||
Buffer.assign("\xcf\x00\x00\x00\x00\x00\x00\x00\x00", 9);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::UInt);
|
||||
EXPECT_EQ(Obj.UInt, 0u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadUInt64One) {
|
||||
Buffer.assign("\xcf\x00\x00\x00\x00\x00\x00\x00\x01", 9);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::UInt);
|
||||
EXPECT_EQ(Obj.UInt, 1u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadUInt64Max) {
|
||||
Buffer = "\xcf\xff\xff\xff\xff\xff\xff\xff\xff";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::UInt);
|
||||
EXPECT_EQ(Obj.UInt, static_cast<uint64_t>(UINT64_MAX));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFloat32) {
|
||||
Buffer = "\xca\xee\xee\xee\xef";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Float);
|
||||
EXPECT_EQ(Obj.Float, -3.6973142664068907e+28f);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFloat64) {
|
||||
Buffer = "\xcb\xee\xee\xee\xee\xee\xee\xee\xef";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Float);
|
||||
EXPECT_EQ(Obj.Float, -2.2899894549927042e+226);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixStrZero) {
|
||||
Buffer = "\xa0";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::String);
|
||||
EXPECT_EQ(Obj.Raw, StringRef());
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixStrOne) {
|
||||
std::string Result(1, 'a');
|
||||
Buffer = std::string("\xa1") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::String);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixStrMax) {
|
||||
// FixStr format's size is a 5 bit unsigned integer, so max is 11111 = 31
|
||||
std::string Result(31, 'a');
|
||||
Buffer = std::string("\xbf") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::String);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadStr8Zero) {
|
||||
Buffer.assign("\xd9\x00", 2);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::String);
|
||||
EXPECT_EQ(Obj.Raw, StringRef());
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadStr8One) {
|
||||
std::string Result(1, 'a');
|
||||
Buffer = std::string("\xd9\x01") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::String);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadStr8Max) {
|
||||
std::string Result(UINT8_MAX, 'a');
|
||||
Buffer = std::string("\xd9\xff") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::String);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadStr16Zero) {
|
||||
Buffer.assign("\xda\x00\x00", 3);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::String);
|
||||
EXPECT_EQ(Obj.Raw, StringRef());
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadStr16One) {
|
||||
std::string Result(1, 'a');
|
||||
Buffer = std::string("\xda\x00\x01", 3) + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::String);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadStr16Max) {
|
||||
std::string Result(UINT16_MAX, 'a');
|
||||
Buffer = std::string("\xda\xff\xff") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::String);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadStr32Zero) {
|
||||
Buffer.assign("\xdb\x00\x00\x00\x00", 5);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::String);
|
||||
EXPECT_EQ(Obj.Raw, StringRef());
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadStr32One) {
|
||||
std::string Result(1, 'a');
|
||||
Buffer = std::string("\xdb\x00\x00\x00\x01", 5) + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::String);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadStr32Max) {
|
||||
std::string Result(static_cast<uint32_t>(UINT16_MAX) + 1, 'a');
|
||||
Buffer = std::string("\xdb\x00\x01\x00\x00", 5) + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::String);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadBin8Zero) {
|
||||
Buffer.assign("\xc4\x00", 2);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Binary);
|
||||
EXPECT_EQ(Obj.Raw, StringRef());
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadBin8One) {
|
||||
std::string Result(1, 'a');
|
||||
Buffer = std::string("\xc4\x01") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Binary);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadBin8Max) {
|
||||
std::string Result(UINT8_MAX, 'a');
|
||||
Buffer = std::string("\xc4\xff") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Binary);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadBin16Zero) {
|
||||
Buffer.assign("\xc5\x00\x00", 3);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Binary);
|
||||
EXPECT_EQ(Obj.Raw, StringRef());
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadBin16One) {
|
||||
std::string Result(1, 'a');
|
||||
Buffer = std::string("\xc5\x00\x01", 3) + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Binary);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadBin16Max) {
|
||||
std::string Result(UINT16_MAX, 'a');
|
||||
Buffer = std::string("\xc5\xff\xff") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Binary);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadBin32Zero) {
|
||||
Buffer.assign("\xc6\x00\x00\x00\x00", 5);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Binary);
|
||||
EXPECT_EQ(Obj.Raw, StringRef());
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadBin32One) {
|
||||
std::string Result(1, 'a');
|
||||
Buffer = std::string("\xc6\x00\x00\x00\x01", 5) + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Binary);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadBin32Max) {
|
||||
std::string Result(static_cast<uint32_t>(UINT16_MAX) + 1, 'a');
|
||||
Buffer = std::string("\xc6\x00\x01\x00\x00", 5) + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Binary);
|
||||
EXPECT_EQ(Obj.Raw, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixArrayZero) {
|
||||
Buffer = "\x90";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Array);
|
||||
EXPECT_EQ(Obj.Length, 0u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixArrayOne) {
|
||||
Buffer = "\x91";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Array);
|
||||
EXPECT_EQ(Obj.Length, 1u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixArrayMax) {
|
||||
Buffer = "\x9f";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Array);
|
||||
// FixArray format's size is a 4 bit unsigned integer, so max is 1111 = 15
|
||||
EXPECT_EQ(Obj.Length, 15u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadArray16Zero) {
|
||||
Buffer.assign("\xdc\x00\x00", 3);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Array);
|
||||
EXPECT_EQ(Obj.Length, 0u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadArray16One) {
|
||||
Buffer.assign("\xdc\x00\x01", 3);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Array);
|
||||
EXPECT_EQ(Obj.Length, 1u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadArray16Max) {
|
||||
Buffer = "\xdc\xff\xff";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Array);
|
||||
EXPECT_EQ(Obj.Length, static_cast<uint16_t>(UINT16_MAX));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadArray32Zero) {
|
||||
Buffer.assign("\xdd\x00\x00\x00\x00", 5);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Array);
|
||||
EXPECT_EQ(Obj.Length, 0u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadArray32One) {
|
||||
Buffer.assign("\xdd\x00\x00\x00\x01", 5);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Array);
|
||||
EXPECT_EQ(Obj.Length, 1u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadArray32Max) {
|
||||
Buffer = "\xdd\xff\xff\xff\xff";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Array);
|
||||
EXPECT_EQ(Obj.Length, static_cast<uint32_t>(UINT32_MAX));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixMapZero) {
|
||||
Buffer = "\x80";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Map);
|
||||
EXPECT_EQ(Obj.Length, 0u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixMapOne) {
|
||||
Buffer = "\x81";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Map);
|
||||
EXPECT_EQ(Obj.Length, 1u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixMapMax) {
|
||||
Buffer = "\x8f";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Map);
|
||||
// FixMap format's size is a 4 bit unsigned integer, so max is 1111 = 15
|
||||
EXPECT_EQ(Obj.Length, 15u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadMap16Zero) {
|
||||
Buffer.assign("\xde\x00\x00", 3);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Map);
|
||||
EXPECT_EQ(Obj.Length, 0u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadMap16One) {
|
||||
Buffer.assign("\xde\x00\x01", 3);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Map);
|
||||
EXPECT_EQ(Obj.Length, 1u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadMap16Max) {
|
||||
Buffer = "\xde\xff\xff";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Map);
|
||||
EXPECT_EQ(Obj.Length, static_cast<uint16_t>(UINT16_MAX));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadMap32Zero) {
|
||||
Buffer.assign("\xdf\x00\x00\x00\x00", 5);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Map);
|
||||
EXPECT_EQ(Obj.Length, 0u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadMap32One) {
|
||||
Buffer.assign("\xdf\x00\x00\x00\x01", 5);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Map);
|
||||
EXPECT_EQ(Obj.Length, 1u);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadMap32Max) {
|
||||
Buffer = "\xdf\xff\xff\xff\xff";
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Map);
|
||||
EXPECT_EQ(Obj.Length, static_cast<uint32_t>(UINT32_MAX));
|
||||
}
|
||||
|
||||
// FixExt formats are only available for these specific lengths: 1, 2, 4, 8, 16
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixExt1) {
|
||||
std::string Result(1, 'a');
|
||||
Buffer = std::string("\xd4\x01") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Extension);
|
||||
EXPECT_EQ(Obj.Extension.Type, 0x01);
|
||||
EXPECT_EQ(Obj.Extension.Bytes, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixExt2) {
|
||||
std::string Result(2, 'a');
|
||||
Buffer = std::string("\xd5\x01") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Extension);
|
||||
EXPECT_EQ(Obj.Extension.Type, 0x01);
|
||||
EXPECT_EQ(Obj.Extension.Bytes, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixExt4) {
|
||||
std::string Result(4, 'a');
|
||||
Buffer = std::string("\xd6\x01") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Extension);
|
||||
EXPECT_EQ(Obj.Extension.Type, 0x01);
|
||||
EXPECT_EQ(Obj.Extension.Bytes, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixExt8) {
|
||||
std::string Result(8, 'a');
|
||||
Buffer = std::string("\xd7\x01") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Extension);
|
||||
EXPECT_EQ(Obj.Extension.Type, 0x01);
|
||||
EXPECT_EQ(Obj.Extension.Bytes, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadFixExt16) {
|
||||
std::string Result(16, 'a');
|
||||
Buffer = std::string("\xd8\x01") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Extension);
|
||||
EXPECT_EQ(Obj.Extension.Type, 0x01);
|
||||
EXPECT_EQ(Obj.Extension.Bytes, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadExt8Min) {
|
||||
// There are fix variants for sizes 1 and 2
|
||||
Buffer.assign("\xc7\x00\x01", 3);
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Extension);
|
||||
EXPECT_EQ(Obj.Extension.Type, 0x01);
|
||||
EXPECT_EQ(Obj.Extension.Bytes, StringRef());
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadExt8Max) {
|
||||
std::string Result(UINT8_MAX, 'a');
|
||||
Buffer = std::string("\xc7\xff\x01", 3) + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Extension);
|
||||
EXPECT_EQ(Obj.Extension.Type, 0x01);
|
||||
EXPECT_EQ(Obj.Extension.Bytes, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadExt16Min) {
|
||||
std::string Result(static_cast<uint16_t>(UINT8_MAX) + 1, 'a');
|
||||
Buffer = std::string("\xc8\x01\x00\x01", 4) + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Extension);
|
||||
EXPECT_EQ(Obj.Extension.Type, 0x01);
|
||||
EXPECT_EQ(Obj.Extension.Bytes, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadExt16Max) {
|
||||
std::string Result(UINT16_MAX, 'a');
|
||||
Buffer = std::string("\xc8\xff\xff\x01") + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Extension);
|
||||
EXPECT_EQ(Obj.Extension.Type, 0x01);
|
||||
EXPECT_EQ(Obj.Extension.Bytes, Result);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackReader, TestReadExt32Min) {
|
||||
std::string Result(static_cast<uint32_t>(UINT16_MAX) + 1, 'a');
|
||||
Buffer = std::string("\xc9\x00\x01\x00\x00\x01", 6) + Result;
|
||||
Reader MPReader(Buffer);
|
||||
auto ContinueOrErr = MPReader.read(Obj);
|
||||
EXPECT_TRUE(static_cast<bool>(ContinueOrErr));
|
||||
EXPECT_TRUE(*ContinueOrErr);
|
||||
EXPECT_EQ(Obj.Kind, Type::Extension);
|
||||
EXPECT_EQ(Obj.Extension.Type, 0x01);
|
||||
EXPECT_EQ(Obj.Extension.Bytes, Result);
|
||||
}
|
523
unittests/BinaryFormat/MsgPackWriterTest.cpp
Normal file
523
unittests/BinaryFormat/MsgPackWriterTest.cpp
Normal file
@ -0,0 +1,523 @@
|
||||
//===- MsgPackWriterTest.cpp ------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/BinaryFormat/MsgPackWriter.h"
|
||||
#include "llvm/BinaryFormat/MsgPack.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::msgpack;
|
||||
|
||||
struct MsgPackWriter : testing::Test {
|
||||
std::string Buffer;
|
||||
llvm::raw_string_ostream OStream;
|
||||
Writer MPWriter;
|
||||
|
||||
MsgPackWriter() : OStream(Buffer), MPWriter(OStream) {}
|
||||
};
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteNil) {
|
||||
MPWriter.writeNil();
|
||||
EXPECT_EQ(OStream.str(), "\xc0");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteBool) {
|
||||
MPWriter.write(true);
|
||||
MPWriter.write(false);
|
||||
EXPECT_EQ(OStream.str(), "\xc3\xc2");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixPositiveInt) {
|
||||
// FixPositiveInt form bitpattern starts with 0, so max FixPositiveInt
|
||||
// is 01111111 = 127
|
||||
for (uint64_t u = 0; u <= 127; ++u) {
|
||||
Buffer.clear();
|
||||
MPWriter.write(u);
|
||||
std::string Output = OStream.str();
|
||||
EXPECT_EQ(Output.size(), 1u);
|
||||
EXPECT_EQ(Output.data()[0], static_cast<uint8_t>(u));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteUInt8Min) {
|
||||
// See TestWriteFixPositiveInt for why 128 is the min non-fix Int8
|
||||
uint64_t u = 128;
|
||||
MPWriter.write(u);
|
||||
EXPECT_EQ(OStream.str(), "\xcc\x80");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteUInt8) {
|
||||
uint64_t u = 221;
|
||||
MPWriter.write(u);
|
||||
EXPECT_EQ(OStream.str(), "\xcc\xdd");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteUInt8Max) {
|
||||
uint64_t u = UINT8_MAX;
|
||||
MPWriter.write(u);
|
||||
EXPECT_EQ(OStream.str(), "\xcc\xff");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteUInt16Min) {
|
||||
uint64_t u = static_cast<uint64_t>(UINT8_MAX) + 1;
|
||||
MPWriter.write(u);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xcd\x01\x00", 3));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteUInt16) {
|
||||
uint64_t u = 43981;
|
||||
MPWriter.write(u);
|
||||
EXPECT_EQ(OStream.str(), "\xcd\xab\xcd");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteUInt16Max) {
|
||||
uint64_t u = UINT16_MAX;
|
||||
MPWriter.write(u);
|
||||
EXPECT_EQ(OStream.str(), "\xcd\xff\xff");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteUInt32Min) {
|
||||
uint64_t u = static_cast<uint64_t>(UINT16_MAX) + 1;
|
||||
MPWriter.write(u);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xce\x00\x01\x00\x00", 5));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteUInt32) {
|
||||
uint64_t u = 2882400186;
|
||||
MPWriter.write(u);
|
||||
EXPECT_EQ(OStream.str(), "\xce\xab\xcd\xef\xba");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteUInt32Max) {
|
||||
uint64_t u = UINT32_MAX;
|
||||
MPWriter.write(u);
|
||||
EXPECT_EQ(OStream.str(), "\xce\xff\xff\xff\xff");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteUInt64Min) {
|
||||
uint64_t u = static_cast<uint64_t>(UINT32_MAX) + 1;
|
||||
MPWriter.write(u);
|
||||
EXPECT_EQ(OStream.str(),
|
||||
std::string("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", 9));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteUInt64) {
|
||||
uint64_t u = 0x010203040506074a;
|
||||
MPWriter.write(u);
|
||||
EXPECT_EQ(OStream.str(), "\xcf\x01\x02\x03\x04\x05\x06\x07\x4a");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteUInt64Max) {
|
||||
uint64_t u = UINT64_MAX;
|
||||
MPWriter.write(u);
|
||||
EXPECT_EQ(OStream.str(), "\xcf\xff\xff\xff\xff\xff\xff\xff\xff");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixNegativeInt) {
|
||||
// Positive values will be written in a UInt form, so max FixNegativeInt is -1
|
||||
//
|
||||
// FixNegativeInt form bitpattern starts with 111, so min FixNegativeInt
|
||||
// is 11100000 = -32
|
||||
for (int64_t i = -1; i >= -32; --i) {
|
||||
Buffer.clear();
|
||||
MPWriter.write(i);
|
||||
std::string Output = OStream.str();
|
||||
EXPECT_EQ(Output.size(), 1u);
|
||||
EXPECT_EQ(Output.data()[0], static_cast<int8_t>(i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteInt8Max) {
|
||||
// See TestWriteFixNegativeInt for why -33 is the max non-fix Int8
|
||||
int64_t i = -33;
|
||||
MPWriter.write(i);
|
||||
EXPECT_EQ(OStream.str(), "\xd0\xdf");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteInt8) {
|
||||
int64_t i = -40;
|
||||
MPWriter.write(i);
|
||||
EXPECT_EQ(OStream.str(), "\xd0\xd8");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteInt8Min) {
|
||||
int64_t i = INT8_MIN;
|
||||
MPWriter.write(i);
|
||||
EXPECT_EQ(OStream.str(), "\xd0\x80");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteInt16Max) {
|
||||
int64_t i = static_cast<int64_t>(INT8_MIN) - 1;
|
||||
MPWriter.write(i);
|
||||
EXPECT_EQ(OStream.str(), "\xd1\xff\x7f");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteInt16) {
|
||||
int64_t i = -4369;
|
||||
MPWriter.write(i);
|
||||
EXPECT_EQ(OStream.str(), "\xd1\xee\xef");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteInt16Min) {
|
||||
int64_t i = INT16_MIN;
|
||||
MPWriter.write(i);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xd1\x80\x00", 3));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteInt32Max) {
|
||||
int64_t i = static_cast<int64_t>(INT16_MIN) - 1;
|
||||
MPWriter.write(i);
|
||||
EXPECT_EQ(OStream.str(), "\xd2\xff\xff\x7f\xff");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteInt32) {
|
||||
int64_t i = -286331153;
|
||||
MPWriter.write(i);
|
||||
EXPECT_EQ(OStream.str(), "\xd2\xee\xee\xee\xef");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteInt32Min) {
|
||||
int64_t i = INT32_MIN;
|
||||
MPWriter.write(i);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xd2\x80\x00\x00\x00", 5));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteInt64Max) {
|
||||
int64_t i = static_cast<int64_t>(INT32_MIN) - 1;
|
||||
MPWriter.write(i);
|
||||
EXPECT_EQ(OStream.str(), "\xd3\xff\xff\xff\xff\x7f\xff\xff\xff");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteInt64) {
|
||||
int64_t i = -1229782938247303441;
|
||||
MPWriter.write(i);
|
||||
EXPECT_EQ(OStream.str(), "\xd3\xee\xee\xee\xee\xee\xee\xee\xef");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteInt64Min) {
|
||||
int64_t i = INT64_MIN;
|
||||
MPWriter.write(i);
|
||||
EXPECT_EQ(OStream.str(),
|
||||
std::string("\xd3\x80\x00\x00\x00\x00\x00\x00\x00", 9));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFloat32) {
|
||||
float f = -3.6973142664068907e+28;
|
||||
MPWriter.write(f);
|
||||
EXPECT_EQ(OStream.str(), "\xca\xee\xee\xee\xef");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFloat64) {
|
||||
double d = -2.2899894549927042e+226;
|
||||
MPWriter.write(d);
|
||||
EXPECT_EQ(OStream.str(), "\xcb\xee\xee\xee\xee\xee\xee\xee\xef");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixStrMin) {
|
||||
std::string s;
|
||||
MPWriter.write(s);
|
||||
EXPECT_EQ(OStream.str(), "\xa0");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixStr) {
|
||||
std::string s = "foo";
|
||||
MPWriter.write(s);
|
||||
EXPECT_EQ(OStream.str(), "\xa3"
|
||||
"foo");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixStrMax) {
|
||||
// FixStr format's size is a 5 bit unsigned integer, so max is 11111 = 31
|
||||
std::string s(31, 'a');
|
||||
MPWriter.write(s);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xbf") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteStr8Min) {
|
||||
// See TestWriteFixStrMax for why 32 is the min non-fix Str8
|
||||
std::string s(32, 'a');
|
||||
MPWriter.write(s);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xd9\x20") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteStr8) {
|
||||
std::string s(33, 'a');
|
||||
MPWriter.write(s);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xd9\x21") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteStr8Max) {
|
||||
std::string s(UINT8_MAX, 'a');
|
||||
MPWriter.write(s);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xd9\xff") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteStr16Min) {
|
||||
std::string s(static_cast<uint64_t>(UINT8_MAX) + 1, 'a');
|
||||
MPWriter.write(s);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xda\x01\x00", 3) + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteStr16) {
|
||||
std::string s(511, 'a');
|
||||
MPWriter.write(s);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xda\x01\xff") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteStr16Max) {
|
||||
std::string s(UINT16_MAX, 'a');
|
||||
MPWriter.write(s);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xda\xff\xff") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteStr32Min) {
|
||||
std::string s(static_cast<uint64_t>(UINT16_MAX) + 1, 'a');
|
||||
MPWriter.write(s);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xdb\x00\x01\x00\x00", 5) + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteStr32) {
|
||||
std::string s(131071, 'a');
|
||||
MPWriter.write(s);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xdb\x00\x01\xff\xff", 5) + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteBin8Min) {
|
||||
std::string s;
|
||||
MPWriter.write(MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc4\x00", 2) + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteBin8) {
|
||||
std::string s(5, 'a');
|
||||
MPWriter.write(MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc4\x05") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteBin8Max) {
|
||||
std::string s(UINT8_MAX, 'a');
|
||||
MPWriter.write(MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc4\xff") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteBin16Min) {
|
||||
std::string s(static_cast<uint64_t>(UINT8_MAX) + 1, 'a');
|
||||
MPWriter.write(MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc5\x01\x00", 3) + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteBin16) {
|
||||
std::string s(511, 'a');
|
||||
MPWriter.write(MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), "\xc5\x01\xff" + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteBin16Max) {
|
||||
std::string s(UINT16_MAX, 'a');
|
||||
MPWriter.write(MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc5\xff\xff") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteBin32Min) {
|
||||
std::string s(static_cast<uint64_t>(UINT16_MAX) + 1, 'a');
|
||||
MPWriter.write(MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc6\x00\x01\x00\x00", 5) + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteBin32) {
|
||||
std::string s(131071, 'a');
|
||||
MPWriter.write(MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc6\x00\x01\xff\xff", 5) + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixArrayMin) {
|
||||
MPWriter.writeArraySize(0);
|
||||
EXPECT_EQ(OStream.str(), "\x90");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixArray) {
|
||||
MPWriter.writeArraySize(4);
|
||||
EXPECT_EQ(OStream.str(), "\x94");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixArrayMax) {
|
||||
// FixArray format's size is a 4 bit unsigned integer, so max is 1111 = 15
|
||||
MPWriter.writeArraySize(15);
|
||||
EXPECT_EQ(OStream.str(), "\x9f");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteArray16Min) {
|
||||
// See TestWriteFixArrayMax for why 16 is the min non-fix Array16
|
||||
MPWriter.writeArraySize(16);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xdc\x00\x10", 3));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteArray16) {
|
||||
MPWriter.writeArraySize(273);
|
||||
EXPECT_EQ(OStream.str(), "\xdc\x01\x11");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteArray16Max) {
|
||||
MPWriter.writeArraySize(UINT16_MAX);
|
||||
EXPECT_EQ(OStream.str(), "\xdc\xff\xff");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteArray32Min) {
|
||||
MPWriter.writeArraySize(static_cast<uint64_t>(UINT16_MAX) + 1);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xdd\x00\x01\x00\x00", 5));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteArray32) {
|
||||
MPWriter.writeArraySize(131071);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xdd\x00\x01\xff\xff", 5));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteArray32Max) {
|
||||
MPWriter.writeArraySize(UINT32_MAX);
|
||||
EXPECT_EQ(OStream.str(), "\xdd\xff\xff\xff\xff");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixMapMin) {
|
||||
MPWriter.writeMapSize(0);
|
||||
EXPECT_EQ(OStream.str(), "\x80");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixMap) {
|
||||
MPWriter.writeMapSize(4);
|
||||
EXPECT_EQ(OStream.str(), "\x84");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixMapMax) {
|
||||
// FixMap format's size is a 4 bit unsigned integer, so max is 1111 = 15
|
||||
MPWriter.writeMapSize(15);
|
||||
EXPECT_EQ(OStream.str(), "\x8f");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteMap16Min) {
|
||||
// See TestWriteFixMapMax for why 16 is the min non-fix Map16
|
||||
MPWriter.writeMapSize(16);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xde\x00\x10", 3));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteMap16) {
|
||||
MPWriter.writeMapSize(273);
|
||||
EXPECT_EQ(OStream.str(), "\xde\x01\x11");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteMap16Max) {
|
||||
MPWriter.writeMapSize(UINT16_MAX);
|
||||
EXPECT_EQ(OStream.str(), "\xde\xff\xff");
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteMap32Min) {
|
||||
MPWriter.writeMapSize(static_cast<uint64_t>(UINT16_MAX) + 1);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xdf\x00\x01\x00\x00", 5));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteMap32) {
|
||||
MPWriter.writeMapSize(131071);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xdf\x00\x01\xff\xff", 5));
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteMap32Max) {
|
||||
MPWriter.writeMapSize(UINT32_MAX);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xdf\xff\xff\xff\xff", 5));
|
||||
}
|
||||
|
||||
// FixExt formats are only available for these specific lengths: 1, 2, 4, 8, 16
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixExt1) {
|
||||
std::string s(1, 'a');
|
||||
MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xd4\x01") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixExt2) {
|
||||
std::string s(2, 'a');
|
||||
MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xd5\x01") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixExt4) {
|
||||
std::string s(4, 'a');
|
||||
MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xd6\x01") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixExt8) {
|
||||
std::string s(8, 'a');
|
||||
MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xd7\x01") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteFixExt16) {
|
||||
std::string s(16, 'a');
|
||||
MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xd8\x01") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteExt8Min) {
|
||||
std::string s;
|
||||
MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc7\x00\x01", 3) + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteExt8) {
|
||||
std::string s(0x2a, 'a');
|
||||
MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc7\x2a\x01") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteExt8Max) {
|
||||
std::string s(UINT8_MAX, 'a');
|
||||
MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc7\xff\x01") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteExt16Min) {
|
||||
std::string s(static_cast<uint16_t>(UINT8_MAX) + 1, 'a');
|
||||
MPWriter.writeExt(0x02, MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc8\x01\x00\x02", 4) + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteExt16) {
|
||||
std::string s(273, 'a');
|
||||
MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc8\x01\x11\x01") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteExt16Max) {
|
||||
std::string s(UINT16_MAX, 'a');
|
||||
MPWriter.writeExt(0x01, MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc8\xff\xff\x01") + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteExt32Min) {
|
||||
std::string s(static_cast<uint32_t>(UINT16_MAX) + 1, 'a');
|
||||
MPWriter.writeExt(0x02, MemoryBufferRef(s, ""));
|
||||
EXPECT_EQ(OStream.str(), std::string("\xc9\x00\x01\x00\x00\x02", 6) + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteCompatibleNoStr8) {
|
||||
Writer CompatWriter(OStream, true);
|
||||
std::string s(32, 'a');
|
||||
CompatWriter.write(s);
|
||||
EXPECT_EQ(OStream.str(), std::string("\xda\x00\x20", 3) + s);
|
||||
}
|
||||
|
||||
TEST_F(MsgPackWriter, TestWriteCompatibleNoBin) {
|
||||
Writer CompatWriter(OStream, true);
|
||||
std::string s;
|
||||
|
||||
#ifdef GTEST_HAS_DEATH_TEST
|
||||
#ifndef NDEBUG
|
||||
EXPECT_DEATH(CompatWriter.write(MemoryBufferRef(s, "")), "compatible mode");
|
||||
#endif
|
||||
#endif
|
||||
}
|
Loading…
Reference in New Issue
Block a user