greenplumn CFileTest 源码

2022-08-18 浏览 (287)

greenplumn CFileTest 代码

文件路径:/src/backend/gporca/libgpos/server/src/unittest/gpos/io/CFileTest.cpp

/---------------------------------------------------------------------------
/	Greenplum Database
/	Copyright (C) 2011 EMC Corp.
/
/	@filename:
/		CFileTest.cpp
/
/	@doc:
/		Tests for CFileWriter and CFileReader
/---------------------------------------------------------------------------

#include "unittest/gpos/io/CFileTest.h"

#include "gpos/assert.h"
#include "gpos/error/CMessage.h"
#include "gpos/io/CFileReader.h"
#include "gpos/io/CFileWriter.h"
#include "gpos/io/ioutils.h"
#include "gpos/string/CStringStatic.h"
#include "gpos/task/CAutoTraceFlag.h"
#include "gpos/test/CUnittest.h"

using namespace gpos;


/---------------------------------------------------------------------------
/	@function:
/		CFileTest::EresUnittest
/
/	@doc:
/		Driver for unittests
/---------------------------------------------------------------------------
GPOS_RESULT
CFileTest::EresUnittest()
{
	CUnittest rgut[] = {
		GPOS_UNITTEST_FUNC(CFileTest::EresUnittest_Invalid),
		GPOS_UNITTEST_FUNC(CFileTest::EresUnittest_FileContent),
		GPOS_UNITTEST_FUNC(CFileTest::EresUnittest_InconsistentSize),
	};

	return CUnittest::EresExecute(rgut, GPOS_ARRAY_SIZE(rgut));
}


/---------------------------------------------------------------------------
/	@function:
/		CFileTest::EresUnittest_Invalid
/
/	@doc:
/		Test for open files with invalid operations
/
/---------------------------------------------------------------------------
GPOS_RESULT
CFileTest::EresUnittest_Invalid()
{
	CHAR szTmpDir[GPOS_FILE_NAME_BUF_SIZE];
	CHAR szTmpFile[GPOS_FILE_NAME_BUF_SIZE];

	const ULONG ulWrPerms = S_IWUSR | S_IRGRP | S_IROTH;
	const ULONG ulRdPerms = S_IRUSR | S_IRGRP | S_IROTH;


	/ make a unique temporary file name
	Unittest_MkTmpFile(szTmpDir, szTmpFile);

	GPOS_TRY
	{
		/ open a nonexistent file by CFileReader,
		/ it will catch an exception
		CFileReader rd1;
		Unittest_CheckError(&rd1, &CFileReader::Open, (const CHAR *) szTmpFile,
							ulRdPerms, CException::ExmiIOError);

		/ create, or truncate the file only permit to write
		CFileWriter wr;
		wr.Open(szTmpFile, ulWrPerms);

		/ close file
		wr.Close();

		/ open a write only file by CFileReader,
		/ it will catch an exception
		CFileReader rd2;
		Unittest_CheckError(&rd2, &CFileReader::Open, (const CHAR *) szTmpFile,
							ulRdPerms, CException::ExmiIOError);
	}
	GPOS_CATCH_EX(ex)
	{
		/ delete tmp file and dir
		Unittest_DeleteTmpDir(szTmpDir, szTmpFile);

		GPOS_RETHROW(ex);
	}
	GPOS_CATCH_END;

	/ delete tmp file and dir
	Unittest_DeleteTmpDir(szTmpDir, szTmpFile);

	return GPOS_OK;
}


/---------------------------------------------------------------------------
/	@function:
/		CFileTest::EresUnittest_FileContent
/
/	@doc:
/		Test for write data, and read the written data
/
/---------------------------------------------------------------------------
GPOS_RESULT
CFileTest::EresUnittest_FileContent()
{
	CHAR szTmpDir[GPOS_FILE_NAME_BUF_SIZE];
	CHAR szTmpFile[GPOS_FILE_NAME_BUF_SIZE];

	const ULONG ulWrPerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
	const ULONG ulRdPerms = S_IRUSR | S_IRGRP | S_IROTH;
	const CHAR szData[] = "Test file content for CFileTest_file\n";
	const INT iLineNum = 100;
	const ULONG ulLineLength = GPOS_ARRAY_SIZE(szData);

	CFileReader rd;
	CFileWriterInternal wr;

	/ make a unique temporary file name
	Unittest_MkTmpFile(szTmpDir, szTmpFile);

	GPOS_TRY
	{
		/ open file for writing by CFileWriter
		wr.Open(szTmpFile, ulWrPerms);

		/ write file line by line
		for (INT i = 0; i < iLineNum; i++)
		{
			wr.Write((BYTE *) szData, ulLineLength);
		}

		/ test file size
		GPOS_ASSERT((wr.FileSize() == (ulLineLength * iLineNum)) &&
					(wr.UllSizeInternal() == wr.FileSize()));

		/ close file
		wr.Close();

		/ read data written to file above line by line
		rd.Open(szTmpFile, ulRdPerms);

		CHAR szRdBuf[ulLineLength];
		CHAR szRdData[ulLineLength];
#ifdef GPOS_DEBUG
		ULONG_PTR ulpRdLen = 0;
#endif	/ GPOS_DEBUG
		CStringStatic strRdData(szRdData, GPOS_ARRAY_SIZE(szRdData));

		/ read file content line by line,
		/ and test if it is equal to what is written
		for (INT i = 0; i < iLineNum; i++)
		{
#ifdef GPOS_DEBUG
			ulpRdLen = rd.ReadBytesToBuffer((BYTE *) szRdBuf, ulLineLength);
#endif	/ GPOS_DEBUG
			strRdData.AppendBuffer((const CHAR *) szRdBuf);

			GPOS_ASSERT(strRdData.Equals((CHAR *) szData));
			GPOS_ASSERT(ulpRdLen == ulLineLength);

			strRdData.Reset();
		}

		GPOS_ASSERT(rd.FileReadSize() == (ulLineLength * iLineNum));

		/ when the EOF is reached, read again will return zero
		GPOS_ASSERT(0 == rd.ReadBytesToBuffer((BYTE *) szRdBuf, ulLineLength));

		/close file
		rd.Close();
	}
	GPOS_CATCH_EX(ex)
	{
		/ delete tmp file and dir
		Unittest_DeleteTmpDir(szTmpDir, szTmpFile);

		GPOS_RETHROW(ex);
	}
	GPOS_CATCH_END;

	/ delete temporary file and dir
	Unittest_DeleteTmpDir(szTmpDir, szTmpFile);

	return GPOS_OK;
}


/---------------------------------------------------------------------------
/	@function:
/		CFileTest::EresUnittest_InconsistentSize
/
/	@doc:
/		Test for write and read file with given length
/		not equal to buffer size
/
/---------------------------------------------------------------------------
GPOS_RESULT
CFileTest::EresUnittest_InconsistentSize()
{
	CHAR szTmpDir[GPOS_FILE_NAME_BUF_SIZE];
	CHAR szTmpFile[GPOS_FILE_NAME_BUF_SIZE];

	/ make a unique temporary file name
	Unittest_MkTmpFile(szTmpDir, szTmpFile);

	GPOS_TRY
	{
		/ write data with inconsistent size with write buffer
		Unittest_WriteInconsistentSize(szTmpFile);

		/ read data with inconsistent size with read buffer
		Unittest_ReadInconsistentSize(szTmpFile);
	}
	GPOS_CATCH_EX(ex)
	{
		/ delete tmp file and dir
		Unittest_DeleteTmpDir(szTmpDir, szTmpFile);

		GPOS_RETHROW(ex);
	}
	GPOS_CATCH_END;

	/ delete tmp file and dir
	Unittest_DeleteTmpDir(szTmpDir, szTmpFile);

	return GPOS_OK;
}


/---------------------------------------------------------------------------
/	@function:
/		CFileTest::Unittest_MkTmpFile
/
/	@doc:
/		Make a unique temporary dir and file
/
/---------------------------------------------------------------------------
void
CFileTest::Unittest_MkTmpFile(CHAR *szTmpDir, CHAR *szTmpFile)
{
	GPOS_ASSERT(nullptr != szTmpDir);
	GPOS_ASSERT(nullptr != szTmpFile);

	CHAR szDir[] = "/tmp/CFileTest.XXXXXX";
	const CHAR szFile[] = "/CFileTest_file.txt";

	/ create unique temporary directory name under /tmp
	ioutils::CreateTempDir(szDir);

	/ copy the temporary directory name into szTmpDir
	CStringStatic strTmpDir(szTmpDir, GPOS_FILE_NAME_BUF_SIZE, szDir);
	CStringStatic strTmpFile(szTmpFile, GPOS_FILE_NAME_BUF_SIZE);

	/ unique temporary file name
	strTmpFile.AppendFormat("%s%s", szDir, szFile);
}


/---------------------------------------------------------------------------
/	@function:
/		CFileTest::Unittest_DeleteTmpDir
/
/	@doc:
/		Delete test files and directory
/
/---------------------------------------------------------------------------
void
CFileTest::Unittest_DeleteTmpDir(const CHAR *szDir, const CHAR *szFile)
{
	GPOS_ASSERT(nullptr != szDir);
	GPOS_ASSERT(nullptr != szFile);

	if (ioutils::PathExists(szFile))
	{
		/ delete temporary file
		ioutils::Unlink(szFile);
	}

	if (ioutils::PathExists(szDir))
	{
		/ delete temporary dir
		ioutils::RemoveDir(szDir);
	}
}


/---------------------------------------------------------------------------
/	@function:
/		CFileTest::Unittest_CheckError
/
/	@doc:
/		Check error for write, read and open
/
/---------------------------------------------------------------------------
template <typename T, typename R, typename ARG1, typename ARG2>
void
CFileTest::Unittest_CheckError(T *pt, R (T::*pfunc)(ARG1, ARG2), ARG1 argFirst,
							   ARG2 argSec, CException::ExMinor exmi)
{
	GPOS_ASSERT(nullptr != pt);
	GPOS_ASSERT(nullptr != pfunc);

	GPOS_TRY
	{
		(pt->*pfunc)(argFirst, argSec);
	}
	GPOS_CATCH_EX(ex)
	{
		if (!GPOS_MATCH_EX(ex, CException::ExmaSystem, (ULONG) exmi))
		{
			GPOS_RETHROW(ex);
		}

		GPOS_RESET_EX;
	}
	GPOS_CATCH_END;
}


/---------------------------------------------------------------------------
/	@function:
/		CFileTest::Unittest_WriteInconsistentSize
/
/	@doc:
/		Write data with inconsistent size with write buffer
/
/---------------------------------------------------------------------------
void
CFileTest::Unittest_WriteInconsistentSize(const CHAR *szTmpFile)
{
	GPOS_ASSERT(nullptr != szTmpFile);

	const ULONG ulWdPerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
	const BYTE szData[] = "Test file content for CFileTest_file\n";
	const ULONG length = GPOS_ARRAY_SIZE(szData);
	const ULONG ulShortfall = 5;

	ULONG ulExpectSize = length - ulShortfall;

	CFileWriterInternal wr;

	wr.Open(szTmpFile, ulWdPerms);

	/ try to write data with length smaller than buffer size
	wr.Write(szData, ulExpectSize);

	CFileWriterInternal wrInternal;

	/ test file size
	GPOS_ASSERT(ulExpectSize == wr.FileSize());
	GPOS_ASSERT(ulExpectSize == wr.UllSizeInternal());

	/ try to write data with length larger than buffer size
	ulExpectSize += (length + ulShortfall);
	wr.Write(szData, length + ulShortfall);

	/ test file size
	GPOS_ASSERT(ulExpectSize == wr.FileSize());
	GPOS_ASSERT(wr.UllSizeInternal() == wr.FileSize());

	wr.Close();
}


/---------------------------------------------------------------------------
/	@function:
/		CFileTest::Unittest_ReadInconsistentSize
/
/	@doc:
/		Read data with inconsistent size with read buffer
/
/---------------------------------------------------------------------------
void
CFileTest::Unittest_ReadInconsistentSize(const CHAR *szTmpFile)
{
	GPOS_ASSERT(nullptr != szTmpFile);

	const ULONG ulWrPerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
	const ULONG ulRdPerms = S_IRUSR | S_IRGRP | S_IROTH;
	const BYTE szData[] = "Test file content for CFileTest_file\n";
	const ULONG length = GPOS_ARRAY_SIZE(szData);
	const ULONG ulShortfall = 5;

	CFileWriter wr;

	/ truncate file to zero, an then write specific data for reading
	wr.Open(szTmpFile, ulWrPerms);

	/ write two lines
	wr.Write(szData, length);
	wr.Write(szData, length);

	/ close file
	wr.Close();

	CFileReader rd;
	/ read buffer is oversized, because below we attempt to read past the end of
	/ the file
	CHAR szRdBuf[length + ulShortfall];

	/ open file by reader
	rd.Open(szTmpFile, ulRdPerms);

	/ read data with length smaller than read buffer size
#ifdef GPOS_DEBUG
	ULONG_PTR ulpRdSize =
		rd.ReadBytesToBuffer((BYTE *) szRdBuf, length - ulShortfall);
#endif	/ GPOS_DEBUG
	szRdBuf[length - ulShortfall] = CHAR_EOS;

	CHAR strBuf[length];
	CStringStatic strRdData(strBuf, GPOS_ARRAY_SIZE(strBuf));
	strRdData.AppendBuffer((const CHAR *) szRdBuf);

	CHAR szExpectData[] = "Test file content for CFileTest_f";
#ifdef GPOS_DEBUG
	ULONG ulExpectSize = length - ulShortfall;
#endif	/ GPOS_DEBUG

	/ test read data, and read size
	GPOS_ASSERT(ulExpectSize == ulpRdSize);
	GPOS_ASSERT(ulExpectSize == rd.FileReadSize());

	BOOL fEqual GPOS_ASSERTS_ONLY = strRdData.Equals(szExpectData);

	GPOS_ASSERT(fEqual);

	/ close file
	rd.Close();

	/ try to read more data than the read buffer size
	rd.Open(szTmpFile, ulRdPerms);
#ifdef GPOS_DEBUG
	ulExpectSize = length + ulShortfall;
	ulpRdSize = rd.ReadBytesToBuffer((BYTE *) szRdBuf, ulExpectSize);
#endif	/ GPOS_DEBUG

	strRdData.Reset();
	strRdData.AppendBuffer((const CHAR *) szRdBuf);

	/ test read size, and read data
	GPOS_ASSERT(ulpRdSize == ulExpectSize);
	GPOS_ASSERT(strRdData.Equals((const CHAR *) szData));

	/ close file
	rd.Close();
}


/---------------------------------------------------------------------------
/	@function:
/		CFileTest::CFileWriterInternal::UllSizeInternal
/
/	@doc:
/		Get file size by descriptor
/
/---------------------------------------------------------------------------
ULLONG
CFileTest::CFileWriterInternal::UllSizeInternal() const
{
	return ioutils::FileSize(GetFileDescriptor());
}


/---------------------------------------------------------------------------
/	@function:
/		CFileTest::CFileWriterInternal:: ~CFileWriterInternal
/
/	@doc:
/		Dtor
/
/---------------------------------------------------------------------------
CFileTest::CFileWriterInternal::~CFileWriterInternal() = default;

/ EOF

相关信息

greenplumn 源码目录

相关文章

greenplumn COstreamBasicTest 源码

greenplumn COstreamStringTest 源码

^