blob: 8087921d51d5354b3a6dc5e28214b6f5b24eb7f8 [file] [log] [blame]
/***************************************************************************
*
* 26.valarray.cons.cpp - tests exercising valarray constructors
*
* $Id$
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
**************************************************************************/
#include <cstdlib> // for free(), strtol(), size_t
#include <valarray> // for indirect_array, valarray
#include <rw_value.h> // for UserClass
#include <rw_driver.h> // for rw_test()
#include <rw_printf.h> // for rw_asnprintf()
/**************************************************************************/
// returns an array of size elements of type T constructed from a string
// of comma-separated values
template <class T>
T*
make_array (const T*, const char *s, std::size_t *psize)
{
std::size_t nelems = psize ? *psize : 0;
T* const buf = new T [nelems ? nelems : 4096];
if (0 == nelems && (0 == s || '\0' == *s))
return buf;
std::size_t i;
for (i = 0; ; ++i) {
char *end = 0;
long val = s ? std::strtol (s, &end, 0) : 0L;
RW_ASSERT (0 == end || '\0' == *end || ',' == *end);
buf [i] = T (val);
if (0 == end || '\0' == *end) {
while (++i < nelems)
buf [i] = buf [i - 1];
break;
}
s = end + 1;
}
if (psize)
*psize = i;
return buf;
}
// deletes an array of elements of type T returned from make_array
template <class T>
void
delete_array (const T *array, std::size_t)
{
T* const a = _RWSTD_CONST_CAST (T*, array);
delete[] a;
}
template <class T>
const std::size_t* count (const T*) { return 0; }
template <class T>
T value (const T &val) { return val; }
/**************************************************************************/
// returns an array of size elements of type UserClass
// constructed from a string of comma-separated values
UserClass*
make_array (const UserClass*, const char *s, std::size_t *psize)
{
std::size_t nelems = psize ? *psize : 0;
const std::size_t size = sizeof (UserClass);
void* const raw = operator new ((nelems ? nelems : 1024) * size);
UserClass* const buf = _RWSTD_STATIC_CAST (UserClass*, raw);
if (0 == nelems && (0 == s || '\0' == *s))
return buf;
std::size_t i;
for (i = 0; ; ++i) {
char *end = 0;
long val = s ? std::strtol (s, &end, 0) : 0L;
RW_ASSERT (0 == end || '\0' == *end || ',' == *end);
new (buf + i) UserClass ();
buf [i].data_.val_ = int (val);
if (0 == end || '\0' == *end) {
while (++i < nelems)
new (buf + i) UserClass (buf [i - 1]);
break;
}
s = end + 1;
}
if (psize)
*psize = i;
return buf;
}
// deletes an array of elements of type T returned from make_array
void
delete_array (const UserClass *array, std::size_t nelems)
{
UserClass* const a = _RWSTD_CONST_CAST (UserClass*, array);
for (std::size_t i = 0; i != nelems; ++i)
(a + i)->~UserClass ();
operator delete (a);
}
const std::size_t* count (const UserClass*) { return &UserClass::count_; }
int value (const UserClass &val) { return val.data_.val_; }
/**************************************************************************/
enum CtorId {
DefaultCtor, // valarray<T>::valarray()
SizeCtor, // valarray<T>::valarra(size_t)
ValueCtor, // valarray<T>::valarray(const T&, size_t)
ArrayCtor // valarray<T>::valarray(const T*, size_t)
};
template <class T>
void
test_ctor (const T*, const char *tname, CtorId which, bool copy,
int line, const char *str, std::size_t nelems)
{
std::valarray<T> *pva = 0;
T* const array = make_array ((const T*)0, str, &nelems);
char* fname = 0;
std::size_t size = 0;
// pointer to a counter keepint track of all objects of type T
// in existence (non-null only for T=UserClass)
const std::size_t* const pcounter = count ((const T*)0);
// get the number of objects of type T before invoking the ctor
std::size_t nobjects = pcounter ? *pcounter : 0;
switch (which) {
case DefaultCtor:
rw_asnprintf (&fname, &size, "valarray<%s>::valarray()", tname);
pva = new std::valarray<T>;
break;
case SizeCtor:
rw_asnprintf (&fname, &size,
"valarray<%s>::valarray(size_t = %zu)",
tname, nelems);
pva = new std::valarray<T>(nelems);
break;
case ValueCtor: {
rw_asnprintf (&fname, &size,
"valarray<%s>::valarray(const %1$s& = %1$s(%d), "
"size_t = %zu)",
tname, value (array [0]), nelems);
pva = new std::valarray<T>(array [0], nelems);
break;
}
case ArrayCtor: {
rw_asnprintf (&fname, &size,
"valarray<%s>::valarray(const %1$s* = {%s}, "
"size_t = %zu)",
tname, str, nelems);
pva = new std::valarray<T>(array, nelems);
break;
}
}
std::valarray<T> *psave = 0;
if (copy) {
char *tmpbuf = 0;
std::size_t tmpsize = 0;
rw_asnprintf (&tmpbuf, &tmpsize, "valarray<%s>::valarray(%s)",
tname, fname);
std::free (fname);
fname = tmpbuf;
size = tmpsize;
// replace the stored object counter value
nobjects = pcounter ? *pcounter : 0;
// save the original and replace it with the new array
psave = pva;
// invoke the copy ctor
pva = new std::valarray<T>(*pva);
}
// verify the size of the array
rw_assert (pva->size () == nelems, 0, line,
"line %d. %s.size() == %zu, got %zu",
__LINE__, fname, nelems, pva->size ());
if (pcounter) {
// compute the number of objects of type T constructed
// by the ctor (valid only for T=UserClass)
nobjects = *pcounter - nobjects;
rw_assert (nobjects == nelems, 0, line,
"line %d. %s constucted %zu objects, expected %zu",
__LINE__, fname, nobjects, nelems);
}
// verify the element values
for (std::size_t i = 0; i != nelems; ++i) {
if (!((*pva)[i] == array [i])) {
rw_assert (i == nelems, 0, line,
"line %d. %s[%zu] == %s(%d), got %4$s(%d)",
__LINE__, fname, i, tname,
value (array [i]), value ((*pva)[i]));
break;
}
}
delete_array (array, nelems);
// get the number of objects of type T before invoking the dtor
nobjects = pcounter ? *pcounter : 0;
delete pva;
if (pcounter) {
// compute the number of objects of type T destroyed by the dtor
nobjects = nobjects - *pcounter;
// verify that all objects constructed by the ctor have been
// destroyed (i.e., none leaked)
rw_assert (nobjects == nelems, 0, line,
"line %d. %s dtor destroyed %zu objects, expected %zu",
__LINE__, fname, nobjects, nelems);
}
delete psave;
std::free (fname);
}
/**************************************************************************/
template <class T>
void
test_default_ctor (const T*, const char *tname, bool copy)
{
if (!copy)
rw_info (0, 0, __LINE__, "std::valarray<%s>::valarray()", tname);
test_ctor ((const T*)0, tname, DefaultCtor, copy, __LINE__, 0, 0);
}
/**************************************************************************/
template <class T>
void
test_size_ctor (const T*, const char *tname, bool copy)
{
if (!copy)
rw_info (0, 0, __LINE__, "std::valarray<%s>::valarray(size_t)",
tname);
#undef TEST
#define TEST(n) \
test_ctor ((const T*)0, tname, SizeCtor, copy, __LINE__, "0", n)
TEST (0);
TEST (1);
TEST (2);
TEST (3);
TEST (4);
TEST (5);
TEST (6);
TEST (7);
TEST (8);
TEST (9);
TEST (10);
TEST (123);
TEST (1023);
}
/**************************************************************************/
template <class T>
void
test_value_ctor (const T*, const char *tname, bool copy)
{
if (!copy)
rw_info (0, 0, __LINE__,
"std::valarray<%s>::valarray(const %1$s&, size_t)",
tname);
#undef TEST
#define TEST(str, n) \
test_ctor ((const T*)0, tname, ValueCtor, copy, __LINE__, str, n)
TEST ("0", 0);
TEST ("0", 1);
TEST ("1", 1);
TEST ("2", 2);
TEST ("3", 3);
TEST ("4", 4);
TEST ("5", 5);
TEST ("6", 12345);
}
/**************************************************************************/
template <class T>
void
test_array_ctor (const T*, const char *tname, bool copy)
{
if (!copy)
rw_info (0, 0, __LINE__,
"std::valarray<%s>::valarray(const %1$s*, size_t)",
tname);
#undef TEST
#define TEST(str) \
test_ctor ((const T*)0, tname, ArrayCtor, copy, __LINE__, str, 0)
TEST (""); // empty array
TEST ("0");
TEST ("0,1");
TEST ("0,1,2");
TEST ("0,1,2,3");
TEST ("0,1,2,3,4");
TEST ("0,1,2,3,4,5");
TEST ("0,1,2,3,4,5,6");
TEST ("0,1,2,3,4,5,6,7");
TEST ("0,1,2,3,4,5,6,7,8");
TEST ("0,1,2,3,4,5,6,7,8,9");
}
/**************************************************************************/
template <class T>
void
test_copy_ctor (const T*, const char *tname)
{
rw_info (0, 0, __LINE__,
"std::valarray<%s>::valarray(const valarray<%1$s>&)", tname);
}
/**************************************************************************/
template <class T>
void
test_ctors (const T*, const char *tname)
{
for (int i = 0; i != 2; ++i) {
// exercise the respective ctor in the first iteration
// and the copy ctor invoked an object constructed with
// the same respective ctor as in the first iteration
// then
const bool test_copy_ctor = 0 < i;
test_default_ctor ((T*)0, tname, test_copy_ctor);
test_size_ctor ((T*)0, tname, test_copy_ctor);
test_value_ctor ((T*)0, tname, test_copy_ctor);
test_array_ctor ((T*)0, tname, test_copy_ctor);
}
}
/**************************************************************************/
static int
run_test (int, char**)
{
#undef TEST
#define TEST(T) test_ctors ((const T*)0, #T)
TEST (char);
TEST (int);
TEST (double);
TEST (UserClass);
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
// FIXME: add command line options to enable/disable each operator
return rw_test (argc, argv, __FILE__,
"valarray.cons",
0 /* no comment */,
run_test,
"",
(void*)0 /* sentinel */);
}