blob: 5f9b32ccfd40a81708c3d5b97876901634702c52 [file] [log] [blame]
/*
* 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 <vector>
#include <utility>
#include <sstream>
#include <ts/ts.h>
#include "swoc/TextView.h"
#include "tscpp/api/Continuation.h"
// TSReleaseAssert() doesn't seem to produce any logging output for a debug build, so do both kinds of assert.
//
#define ALWAYS_ASSERT(EXPR) \
{ \
TSAssert(EXPR); \
TSReleaseAssert(EXPR); \
}
std::vector<void (*)()> testList;
struct ATest {
ATest(void (*testFuncPtr)()) { testList.push_back(testFuncPtr); }
};
// Put a test function, whose name is the actual parameter for TEST_FUNC, into testList, the list of test functions.
//
#define TEST(TEST_FUNC) ATest t(TEST_FUNC);
// TextView test. This is not testing the actual TextView code, just that it works to call functions in TextView.cc in the core
// from a plugin.
//
namespace TextViewTest
{
void
f()
{
swoc::TextView tv("abcdefg");
std::ostringstream oss;
oss << tv;
ALWAYS_ASSERT(memcmp(swoc::TextView(oss.str()), tv) == 0)
}
TEST(f)
} // end namespace TextViewTest
// Test for Continuation class.
//
namespace ContinuationTest
{
struct {
TSEvent event;
void *edata;
} passedToEventFunc;
bool
checkPassed(TSEvent event, void *edata)
{
return (passedToEventFunc.event == event) and (passedToEventFunc.edata == edata);
}
class TestCont : public atscppapi::Continuation
{
public:
TestCont(Mutex m) : atscppapi::Continuation(m) {}
TestCont() = default;
private:
int
_run(TSEvent event, void *edata) override
{
passedToEventFunc.event = event;
passedToEventFunc.edata = edata;
return 666;
}
};
void
f()
{
TestCont::Mutex m(TSMutexCreate());
TestCont c(m);
ALWAYS_ASSERT(!!c)
ALWAYS_ASSERT(c.asTSCont() != nullptr)
ALWAYS_ASSERT(c.mutex() == m)
TestCont c2(std::move(c));
ALWAYS_ASSERT(!!c2)
ALWAYS_ASSERT(c2.asTSCont() != nullptr)
ALWAYS_ASSERT(c2.mutex() == m)
// clang-analyzer warns about use-after-move for the following, but the
// atscppapi::Continuation API is designed to support use after move and this
// test intentionally exercises this behavior. Thus we disable clang-analyzer
// for this code.
#if !defined(__clang_analyzer__) && !defined(__COVERITY__)
ALWAYS_ASSERT(!c)
ALWAYS_ASSERT(c.asTSCont() == nullptr)
ALWAYS_ASSERT(c.mutex() == nullptr)
#endif
TestCont c3;
ALWAYS_ASSERT(!c3)
ALWAYS_ASSERT(c3.asTSCont() == nullptr)
ALWAYS_ASSERT(c3.mutex() == nullptr)
c3 = std::move(c2);
ALWAYS_ASSERT(!!c3)
ALWAYS_ASSERT(c3.asTSCont() != nullptr)
ALWAYS_ASSERT(c3.mutex() == m)
// See the user-after-move comment above for the reason we disable
// clang-analyzer here.
#ifndef __clang_analyzer__
ALWAYS_ASSERT(!c2)
ALWAYS_ASSERT(c2.asTSCont() == nullptr)
ALWAYS_ASSERT(c2.mutex() == nullptr)
#endif
c3.destroy();
ALWAYS_ASSERT(!c3)
ALWAYS_ASSERT(c3.asTSCont() == nullptr)
ALWAYS_ASSERT(c3.mutex() == nullptr)
c = TestCont(m);
ALWAYS_ASSERT(!!c)
ALWAYS_ASSERT(c.asTSCont() != nullptr)
ALWAYS_ASSERT(c.mutex() == m)
}
TEST(f)
} // end namespace ContinuationTest
// Run all the tests.
//
void
TSPluginInit(int, const char **)
{
TSPluginRegistrationInfo info;
info.plugin_name = "test_cppapi";
info.vendor_name = "Apache Software Foundation";
info.support_email = "dev@trafficserver.apache.org";
ALWAYS_ASSERT(TSPluginRegister(&info) == TS_SUCCESS)
for (auto fp : testList) {
fp();
}
}