brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.0 KiB · f4b9e90 Raw
123 lines · cpp
1//===-- unittests/Runtime/BufferTest.cpp ------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "flang-rt/runtime/buffer.h"10#include "CrashHandlerFixture.h"11#include "gtest/gtest.h"12#include <algorithm>13#include <cstdint>14#include <cstring>15#include <memory>16 17static constexpr std::size_t tinyBufferSize{32};18using FileOffset = std::int64_t;19using namespace Fortran::runtime;20using namespace Fortran::runtime::io;21 22class Store : public FileFrame<Store, tinyBufferSize> {23public:24  explicit Store(std::size_t bytes = 65536) : bytes_{bytes} {25    data_.reset(new char[bytes]);26    std::memset(&data_[0], 0, bytes);27  }28  std::size_t bytes() const { return bytes_; }29  void set_enforceSequence(bool yes = true) { enforceSequence_ = yes; }30  void set_expect(FileOffset to) { expect_ = to; }31 32  std::size_t Read(FileOffset at, char *to, std::size_t minBytes,33      std::size_t maxBytes, IoErrorHandler &handler) {34    if (enforceSequence_ && at != expect_) {35      handler.SignalError("Read(%d,%d,%d) not at expected %d",36          static_cast<int>(at), static_cast<int>(minBytes),37          static_cast<int>(maxBytes), static_cast<int>(expect_));38    } else if (at < 0 || at + minBytes > bytes_) {39      handler.SignalError("Read(%d,%d,%d) is out of bounds",40          static_cast<int>(at), static_cast<int>(minBytes),41          static_cast<int>(maxBytes));42    }43    auto result{std::min<std::size_t>(maxBytes, bytes_ - at)};44    std::memcpy(to, &data_[at], result);45    expect_ = at + result;46    return result;47  }48  std::size_t Write(FileOffset at, const char *from, std::size_t bytes,49      IoErrorHandler &handler) {50    if (enforceSequence_ && at != expect_) {51      handler.SignalError("Write(%d,%d) not at expected %d",52          static_cast<int>(at), static_cast<int>(bytes),53          static_cast<int>(expect_));54    } else if (at < 0 || at + bytes > bytes_) {55      handler.SignalError("Write(%d,%d) is out of bounds", static_cast<int>(at),56          static_cast<int>(bytes));57    }58    std::memcpy(&data_[at], from, bytes);59    expect_ = at + bytes;60    return bytes;61  }62 63private:64  std::size_t bytes_;65  std::unique_ptr<char[]> data_;66  bool enforceSequence_{false};67  FileOffset expect_{0};68};69 70inline int ChunkSize(int j, int most) {71  // 31, 1, 29, 3, 27, ...72  j %= tinyBufferSize;73  auto chunk{static_cast<int>(74      ((j % 2) ? j : (tinyBufferSize - 1 - j)) % tinyBufferSize)};75  return std::min(chunk, most);76}77 78inline int ValueFor(int at) { return (at ^ (at >> 8)) & 0xff; }79 80struct BufferTests : CrashHandlerFixture {};81 82TEST(BufferTests, TestFrameBufferReadAndWrite) {83  Terminator terminator{__FILE__, __LINE__};84  IoErrorHandler handler{terminator};85  Store store;86  store.set_enforceSequence(true);87  const auto bytes{static_cast<FileOffset>(store.bytes())};88  // Fill with an assortment of chunks89  int at{0}, j{0};90  while (at < bytes) {91    auto chunk{ChunkSize(j, static_cast<int>(bytes - at))};92    store.WriteFrame(at, chunk, handler);93    char *to{store.Frame()};94    for (int k{0}; k < chunk; ++k) {95      to[k] = ValueFor(at + k);96    }97    at += chunk;98    ++j;99  }100  store.Flush(handler);101  // Validate102  store.set_expect(0);103  at = 0;104  while (at < bytes) {105    auto chunk{ChunkSize(j, static_cast<int>(bytes - at))};106    std::size_t frame{store.ReadFrame(at, chunk, handler)};107    ASSERT_GE(frame, static_cast<std::size_t>(chunk))108        << "Badly-sized ReadFrame at " << at << ", chunk=" << chunk << ", got "109        << frame << '\n';110 111    const char *from{store.Frame()};112    for (int k{0}; k < chunk; ++k) {113      auto expect{static_cast<char>(ValueFor(at + k))};114      ASSERT_EQ(from[k], expect)115          << "At " << at << '+' << k << '(' << (at + k) << "), read "116          << (from[k] & 0xff) << ", expected " << static_cast<int>(expect)117          << '\n';118    }119    at += chunk;120    ++j;121  }122}123