aboutsummaryrefslogtreecommitdiff
path: root/src/test/cpp/helpers/charsetencodertestcase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/cpp/helpers/charsetencodertestcase.cpp')
-rw-r--r--src/test/cpp/helpers/charsetencodertestcase.cpp302
1 files changed, 302 insertions, 0 deletions
diff --git a/src/test/cpp/helpers/charsetencodertestcase.cpp b/src/test/cpp/helpers/charsetencodertestcase.cpp
new file mode 100644
index 0000000..74af926
--- /dev/null
+++ b/src/test/cpp/helpers/charsetencodertestcase.cpp
@@ -0,0 +1,302 @@
+/*
+ * 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 <log4cxx/helpers/charsetencoder.h>
+#include "../logunit.h"
+#include "../insertwide.h"
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/thread.h>
+#include <log4cxx/helpers/mutex.h>
+#include <log4cxx/helpers/condition.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <apr.h>
+#include <apr_atomic.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+LOGUNIT_CLASS(CharsetEncoderTestCase)
+{
+ LOGUNIT_TEST_SUITE(CharsetEncoderTestCase);
+ LOGUNIT_TEST(encode1);
+ LOGUNIT_TEST(encode2);
+ LOGUNIT_TEST(encode3);
+ LOGUNIT_TEST(encode4);
+#if APR_HAS_THREADS
+ LOGUNIT_TEST(thread1);
+#endif
+ LOGUNIT_TEST_SUITE_END();
+
+ enum { BUFSIZE = 256 };
+
+public:
+
+
+ void encode1() {
+ const LogString greeting(LOG4CXX_STR("Hello, World"));
+ CharsetEncoderPtr enc(CharsetEncoder::getEncoder(LOG4CXX_STR("US-ASCII")));
+ char buf[BUFSIZE];
+ ByteBuffer out(buf, BUFSIZE);
+ LogString::const_iterator iter = greeting.begin();
+ log4cxx_status_t stat = enc->encode(greeting, iter, out);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT(iter == greeting.end());
+
+ stat = enc->encode(greeting, iter, out);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT_EQUAL((size_t) 12, out.position());
+
+ out.flip();
+ std::string encoded((const char*) out.data(), out.limit());
+ LOGUNIT_ASSERT_EQUAL((std::string) "Hello, World", encoded);
+ LOGUNIT_ASSERT(iter == greeting.end());
+ }
+
+ void encode2() {
+ LogString greeting(BUFSIZE - 3, LOG4CXX_STR('A'));
+ greeting.append(LOG4CXX_STR("Hello"));
+
+ CharsetEncoderPtr enc(CharsetEncoder::getEncoder(LOG4CXX_STR("US-ASCII")));
+
+ char buf[BUFSIZE];
+ ByteBuffer out(buf, BUFSIZE);
+ LogString::const_iterator iter = greeting.begin();
+ log4cxx_status_t stat = enc->encode(greeting, iter, out);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT_EQUAL((size_t) 0, out.remaining());
+ LOGUNIT_ASSERT_EQUAL(LOG4CXX_STR('o'), *(iter+1));
+
+ out.flip();
+ std::string encoded((char*) out.data(), out.limit());
+ out.clear();
+
+ stat = enc->encode(greeting, iter, out);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT_EQUAL((size_t) 2, out.position());
+ LOGUNIT_ASSERT(iter == greeting.end());
+
+ stat = enc->encode(greeting, iter, out);
+ out.flip();
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ encoded.append(out.data(), out.limit());
+
+ std::string manyAs(BUFSIZE - 3, 'A');
+ LOGUNIT_ASSERT_EQUAL(manyAs, encoded.substr(0, BUFSIZE - 3));
+ LOGUNIT_ASSERT_EQUAL(std::string("Hello"), encoded.substr(BUFSIZE - 3));
+ }
+
+
+ void encode3() {
+#if LOG4CXX_LOGCHAR_IS_WCHAR || LOG4CXX_LOGCHAR_IS_UNICHAR
+ // arbitrary, hopefully meaningless, characters from
+ // Latin, Arabic, Armenian, Bengali, CJK and Cyrillic
+ const logchar greet[] = { L'A', 0x0605, 0x0530, 0x986, 0x4E03, 0x400, 0 };
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ const char greet[] = { 'A',
+ (char) 0xD8, (char) 0x85,
+ (char) 0xD4, (char) 0xB0,
+ (char) 0xE0, (char) 0xA6, (char) 0x86,
+ (char) 0xE4, (char) 0xB8, (char) 0x83,
+ (char) 0xD0, (char) 0x80,
+ 0 };
+#endif
+ LogString greeting(greet);
+
+ CharsetEncoderPtr enc(CharsetEncoder::getEncoder(LOG4CXX_STR("US-ASCII")));
+
+ char buf[BUFSIZE];
+ ByteBuffer out(buf, BUFSIZE);
+
+ LogString::const_iterator iter = greeting.begin();
+ log4cxx_status_t stat = enc->encode(greeting, iter, out);
+ out.flip();
+ LOGUNIT_ASSERT_EQUAL(true, CharsetEncoder::isError(stat));
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, out.limit());
+ LOGUNIT_ASSERT_EQUAL(greet[1], *iter);
+ LOGUNIT_ASSERT_EQUAL('A', out.data()[0]);
+ }
+
+
+ void encode4() {
+ const char utf8_greet[] = { 'A',
+ (char) 0xD8, (char) 0x85,
+ (char) 0xD4, (char) 0xB0,
+ (char) 0xE0, (char) 0xA6, (char) 0x86,
+ (char) 0xE4, (char) 0xB8, (char) 0x83,
+ (char) 0xD0, (char) 0x80,
+ 0 };
+#if LOG4CXX_LOGCHAR_IS_WCHAR || LOG4CXX_LOGCHAR_IS_UNICHAR
+ // arbitrary, hopefully meaningless, characters from
+ // Latin, Arabic, Armenian, Bengali, CJK and Cyrillic
+ const logchar greet[] = { L'A', 0x0605, 0x0530, 0x986, 0x4E03, 0x400, 0 };
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ const logchar *greet = utf8_greet;
+#endif
+ LogString greeting(greet);
+
+ CharsetEncoderPtr enc(CharsetEncoder::getEncoder(LOG4CXX_STR("UTF-8")));
+
+ char buf[BUFSIZE];
+ ByteBuffer out(buf, BUFSIZE);
+ LogString::const_iterator iter = greeting.begin();
+ log4cxx_status_t stat = enc->encode(greeting, iter, out);
+ LOGUNIT_ASSERT_EQUAL(false, CharsetEncoder::isError(stat));
+ stat = enc->encode(greeting, iter, out);
+ LOGUNIT_ASSERT_EQUAL(false, CharsetEncoder::isError(stat));
+
+ out.flip();
+ LOGUNIT_ASSERT_EQUAL((size_t) 13, out.limit());
+ for(size_t i = 0; i < out.limit(); i++) {
+ LOGUNIT_ASSERT_EQUAL((int) utf8_greet[i], (int) out.data()[i]);
+ }
+ LOGUNIT_ASSERT(iter == greeting.end());
+ }
+
+#if APR_HAS_THREADS
+ class ThreadPackage {
+ public:
+ ThreadPackage(CharsetEncoderPtr& enc, int repetitions) :
+ p(), lock(p), condition(p), passCount(0), failCount(0), enc(enc), repetitions(repetitions) {
+ }
+
+ void await() {
+ synchronized sync(lock);
+ condition.await(lock);
+ }
+
+ void signalAll() {
+ synchronized sync(lock);
+ condition.signalAll();
+ }
+
+ void fail() {
+ apr_atomic_inc32(&failCount);
+ }
+
+ void pass() {
+ apr_atomic_inc32(&passCount);
+ }
+
+ apr_uint32_t getFail() {
+ return apr_atomic_read32(&failCount);
+ }
+
+ apr_uint32_t getPass() {
+ return apr_atomic_read32(&passCount);
+ }
+
+ int getRepetitions() {
+ return repetitions;
+ }
+
+ CharsetEncoderPtr& getEncoder() {
+ return enc;
+ }
+
+ private:
+ ThreadPackage(const ThreadPackage&);
+ ThreadPackage& operator=(ThreadPackage&);
+ Pool p;
+ Mutex lock;
+ Condition condition;
+ volatile apr_uint32_t passCount;
+ volatile apr_uint32_t failCount;
+ CharsetEncoderPtr enc;
+ int repetitions;
+ };
+
+ static void* LOG4CXX_THREAD_FUNC thread1Action(apr_thread_t* /* thread */, void* data) {
+ ThreadPackage* package = (ThreadPackage*) data;
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ const logchar greet[] = { 'H', 'e', 'l', 'l', 'o', ' ',
+ (char) 0xC2, (char) 0xA2, // cent sign
+ (char) 0xC2, (char) 0xA9, // copyright
+ (char) 0xc3, (char) 0xb4, // latin small letter o with circumflex
+ 0 };
+#endif
+#if LOG4CXX_LOGCHAR_IS_WCHAR || LOG4CXX_LOGCHAR_IS_UNICHAR
+ // arbitrary, hopefully meaningless, characters from
+ // Latin, Arabic, Armenian, Bengali, CJK and Cyrillic
+ const logchar greet[] = { L'H', L'e', L'l', L'l', L'o', L' ',
+ 0x00A2, 0x00A9, 0x00F4 , 0 };
+#endif
+
+ const char expected[] = { 'H', 'e', 'l', 'l', 'o', ' ',
+ (char) 0x00A2, (char) 0x00A9, (char) 0x00F4 };
+
+ LogString greeting(greet);
+
+ package->await();
+ for(int i = 0; i < package->getRepetitions(); i++) {
+ bool pass = true;
+ char buf[BUFSIZE];
+ ByteBuffer out(buf, BUFSIZE);
+ LogString::const_iterator iter = greeting.begin();
+ log4cxx_status_t stat = package->getEncoder()->encode(greeting, iter, out);
+ pass = (false == CharsetEncoder::isError(stat));
+ if (pass) {
+ stat = package->getEncoder()->encode(greeting, iter, out);
+ pass = (false == CharsetEncoder::isError(stat));
+ if (pass) {
+ out.flip();
+ pass = (sizeof(expected) == out.limit());
+ for(size_t i = 0; i < out.limit() && pass; i++) {
+ pass = (expected[i] == out.data()[i]);
+ }
+ pass = pass && (iter == greeting.end());
+ }
+ }
+ if (pass) {
+ package->pass();
+ } else {
+ package->fail();
+ }
+ }
+ return 0;
+ }
+
+ void thread1() {
+ enum { THREAD_COUNT = 10, THREAD_REPS = 10000 };
+ Thread threads[THREAD_COUNT];
+ CharsetEncoderPtr enc(CharsetEncoder::getEncoder(LOG4CXX_STR("ISO-8859-1")));
+ ThreadPackage* package = new ThreadPackage(enc, THREAD_REPS);
+ { for(int i = 0; i < THREAD_COUNT; i++) {
+ threads[i].run(thread1Action, package);
+ } }
+ //
+ // give time for all threads to be launched so
+ // we don't signal before everybody is waiting.
+ Thread::sleep(100);
+ package->signalAll();
+ for(int i = 0; i < THREAD_COUNT; i++) {
+ threads[i].join();
+ }
+ LOGUNIT_ASSERT_EQUAL((apr_uint32_t) 0, package->getFail());
+ LOGUNIT_ASSERT_EQUAL((apr_uint32_t) THREAD_COUNT * THREAD_REPS, package->getPass());
+ delete package;
+ }
+#endif
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(CharsetEncoderTestCase);