#include "input.h"
#include "output.h"
#include <library/cpp/testing/unittest/registar.h>
#include <util/system/file.h>
#include <util/system/yassert.h>
#ifdef _win_
#include <io.h>
#endif
class TMockStdIn {
public:
TMockStdIn()
: StdInCopy_(dup(0))
{
}
~TMockStdIn() {
close(StdInCopy_);
}
template <typename FuncType>
void ForInput(const TStringBuf text, const FuncType& func) {
TFile tempFile(TFile::Temporary("input_ut"));
tempFile.Write(text.data(), text.size());
tempFile.FlushData();
tempFile.Seek(0, sSet);
TFileHandle tempFh(tempFile.GetHandle());
tempFh.Duplicate2Posix(0);
tempFh.Release();
func();
Cin.ReadAll();
dup2(StdInCopy_, 0);
clearerr(stdin);
}
private:
int StdInCopy_;
};
class TNoInput: public IInputStream {
public:
TNoInput(ui64 size)
: Size_(size)
{
}
protected:
size_t DoRead(void*, size_t len) override {
len = Min(static_cast<ui64>(len), Size_);
Size_ -= len;
return len;
}
private:
ui64 Size_;
};
class TNoOutput: public IOutputStream {
public:
TNoOutput() = default;
protected:
void DoWrite(const void*, size_t) override {
}
};
class TSimpleStringInput: public IInputStream {
public:
TSimpleStringInput(const TString& string)
: String_(string)
{
}
protected:
size_t DoRead(void* buf, size_t len) override {
Y_ASSERT(len != 0);
if (String_.empty()) {
return 0;
}
*static_cast<char*>(buf) = String_[0];
String_.remove(0, 1);
return 1;
}
private:
TString String_;
};
Y_UNIT_TEST_SUITE(TInputTest) {
Y_UNIT_TEST(BigTransfer) {
ui64 size = 1024ull * 1024ull * 1024ull * 5;
TNoInput input(size);
TNoOutput output;
ui64 transferred = TransferData(&input, &output);
UNIT_ASSERT_VALUES_EQUAL(transferred, size);
}
Y_UNIT_TEST(TestReadTo) {
/* This one tests default implementation of ReadTo. */
TSimpleStringInput in("0123456789abc");
TString t;
UNIT_ASSERT_VALUES_EQUAL(in.ReadTo(t, '7'), 8);
UNIT_ASSERT_VALUES_EQUAL(t, "0123456");
UNIT_ASSERT_VALUES_EQUAL(in.ReadTo(t, 'z'), 5);
UNIT_ASSERT_VALUES_EQUAL(t, "89abc");
UNIT_ASSERT_VALUES_EQUAL(in.ReadTo(t, 'z'), 0);
UNIT_ASSERT_VALUES_EQUAL(t, "89abc");
}
Y_UNIT_TEST(TestReadLine) {
TSimpleStringInput in("1\n22\n333");
TString t;
UNIT_ASSERT_VALUES_EQUAL(in.ReadLine(t), 2);
UNIT_ASSERT_VALUES_EQUAL(t, "1");
UNIT_ASSERT_VALUES_EQUAL(in.ReadLine(t), 3);
UNIT_ASSERT_VALUES_EQUAL(t, "22");
UNIT_ASSERT_VALUES_EQUAL(in.ReadLine(t), 3);
UNIT_ASSERT_VALUES_EQUAL(t, "333");
UNIT_ASSERT_VALUES_EQUAL(in.ReadLine(t), 0);
UNIT_ASSERT_VALUES_EQUAL(t, "333");
}
Y_UNIT_TEST(TestStdInReadTo) {
std::pair<std::pair<TStringBuf, char>, TStringBuf> testPairs[] = {
{{"", '\n'}, ""},
{{"\n", '\n'}, ""},
{{"\n\t", '\t'}, "\n"},
{{"\t\n", '\n'}, "\t"},
{{"a\tb\n", '\t'}, "a"}};
TMockStdIn stdIn;
for (const auto& testPair : testPairs) {
const TStringBuf text = testPair.first.first;
const char delim = testPair.first.second;
const TStringBuf expectedValue = testPair.second;
stdIn.ForInput(text,
[=] {
TString value;
Cin.ReadTo(value, delim);
UNIT_ASSERT_VALUES_EQUAL(value, expectedValue);
});
}
}
}