Skip to content

Commit 5664f56

Browse files
committed
Include websocket tests by default
Signed-off-by: Nijat K <nijat.khanbabayev@gmail.com>
1 parent d70dce8 commit 5664f56

12 files changed

+264
-201
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ build-debug: ## build the library ( DEBUG ) - May need a make clean when switch
2424
SKBUILD_CONFIGURE_OPTIONS="" DEBUG=1 python setup.py build build_ext --inplace
2525

2626
build-conda: ## build the library in Conda
27-
python setup.py build build_ext --csp-no-vcpkg --inplace
27+
CSP_USE_CCACHE=0 python setup.py build build_ext --csp-no-vcpkg --inplace
2828

2929
install: ## install library
3030
python -m pip install .
@@ -83,7 +83,7 @@ checks: check
8383

8484
TEST_ARGS :=
8585
test-py: ## Clean and Make unit tests
86-
python -m pytest -v csp/tests --junitxml=junit.xml $(TEST_ARGS)
86+
python -m pytest -vv -s csp/tests --junitxml=junit.xml $(TEST_ARGS)
8787

8888
test-cpp: ## Make C++ unit tests
8989
ifneq ($(OS),Windows_NT)

cpp/csp/adapters/websocket/CMakeLists.txt

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
csp_autogen( csp.adapters.websocket_types websocket_types WEBSOCKET_HEADER WEBSOCKET_SOURCE )
22

33
set(WS_CLIENT_HEADER_FILES
4-
WebsocketClientTypes.h
54
ClientAdapterManager.h
65
ClientInputAdapter.h
76
ClientOutputAdapter.h
@@ -13,7 +12,6 @@ set(WS_CLIENT_HEADER_FILES
1312
)
1413

1514
set(WS_CLIENT_SOURCE_FILES
16-
WebsocketClientTypes.cpp
1715
ClientAdapterManager.cpp
1816
ClientInputAdapter.cpp
1917
ClientOutputAdapter.cpp

cpp/csp/adapters/websocket/ClientAdapterManager.h

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
#include <csp/adapters/websocket/WebsocketEndpoint.h>
55
#include <csp/adapters/websocket/WebsocketEndpointManager.h>
6-
#include <csp/adapters/websocket/WebsocketClientTypes.h>
76
#include <csp/adapters/websocket/ClientInputAdapter.h>
87
#include <csp/adapters/websocket/ClientHeaderUpdateAdapter.h>
98
#include <csp/core/Enum.h>

cpp/csp/adapters/websocket/WebsocketClientTypes.cpp

-13
This file was deleted.

cpp/csp/adapters/websocket/WebsocketClientTypes.h

-26
This file was deleted.

cpp/csp/adapters/websocket/WebsocketEndpointManager.cpp

+23-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
#include <csp/adapters/websocket/WebsocketEndpointManager.h>
22

3+
namespace csp {
4+
5+
INIT_CSP_ENUM( adapters::websocket::ClientStatusType,
6+
"ACTIVE",
7+
"GENERIC_ERROR",
8+
"CONNECTION_FAILED",
9+
"CLOSED",
10+
"MESSAGE_SEND_FAIL",
11+
);
12+
13+
}
314
namespace csp::adapters::websocket {
415

516
WebsocketEndpointManager::WebsocketEndpointManager( ClientAdapterManager* mgr, const Dictionary & properties, Engine* engine )
@@ -96,7 +107,8 @@ void WebsocketEndpointManager::shutdownEndpoint(const std::string& endpoint_id)
96107
m_endpoints.erase(endpoint_it);
97108
std::stringstream ss;
98109
ss << "No more connections for endpoint={" << endpoint_id << "} Shutting down...";
99-
m_mgr -> pushStatus(StatusLevel::INFO, ClientStatusType::CLOSED, ss.str());
110+
std::string msg = ss.str();
111+
m_mgr -> pushStatus(StatusLevel::INFO, ClientStatusType::CLOSED, msg);
100112
}
101113

102114
void WebsocketEndpointManager::setupEndpoint(const std::string& endpoint_id,
@@ -135,9 +147,10 @@ void WebsocketEndpointManager::setupEndpoint(const std::string& endpoint_id,
135147
// should only happen if persist is False
136148
if ( !payload.empty() )
137149
endpoint -> send(payload);
138-
139-
m_mgr -> pushStatus(StatusLevel::INFO, ClientStatusType::ACTIVE,
140-
"Connected successfully for endpoint={" + endpoint_id +"}");
150+
std::stringstream ss;
151+
ss << "Connected successfully for endpoint={" << endpoint_id << "}";
152+
std::string msg = ss.str();
153+
m_mgr -> pushStatus(StatusLevel::INFO, ClientStatusType::ACTIVE, msg);
141154
// We remove the caller id, if it was the only one, then we shut down the endpoint
142155
if( !persist )
143156
removeEndpointForCallerId(endpoint_id, is_consumer, validated_id);
@@ -170,8 +183,9 @@ void WebsocketEndpointManager::setupEndpoint(const std::string& endpoint_id,
170183
stored_endpoint -> setOnSendFail(
171184
[ this, endpoint_id ]( const std::string& s ) {
172185
std::stringstream ss;
173-
ss << "Error: " << s << " for " << endpoint_id;
174-
m_mgr -> pushStatus( StatusLevel::ERROR, ClientStatusType::MESSAGE_SEND_FAIL, ss.str() );
186+
ss << "Error: " << s << " for endpoint={" << endpoint_id << "}";
187+
std::string msg = ss.str();
188+
m_mgr -> pushStatus( StatusLevel::ERROR, ClientStatusType::MESSAGE_SEND_FAIL, msg );
175189
}
176190
);
177191
stored_endpoint -> run();
@@ -214,10 +228,11 @@ void WebsocketEndpointManager::handleEndpointFailure(const std::string& endpoint
214228

215229
std::stringstream ss;
216230
ss << "Connection Failure for endpoint={" << endpoint_id << "} Due to: " << reason;
231+
std::string msg = ss.str();
217232
if ( status_type == ClientStatusType::CLOSED || status_type == ClientStatusType::ACTIVE )
218-
m_mgr -> pushStatus(StatusLevel::INFO, status_type, ss.str());
233+
m_mgr -> pushStatus(StatusLevel::INFO, status_type, msg);
219234
else{
220-
m_mgr -> pushStatus(StatusLevel::ERROR, status_type, ss.str());
235+
m_mgr -> pushStatus(StatusLevel::ERROR, status_type, msg);
221236
}
222237
};
223238

cpp/csp/adapters/websocket/WebsocketEndpointManager.h

+19-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#define WEBSOCKET_ENDPOINT_MANAGER_H
33

44
#include <boost/asio.hpp>
5-
#include <csp/adapters/websocket/WebsocketClientTypes.h>
65
#include <csp/adapters/websocket/WebsocketEndpoint.h>
76
#include <csp/adapters/websocket/ClientAdapterManager.h>
87
#include <csp/adapters/websocket/ClientInputAdapter.h>
@@ -70,6 +69,25 @@ struct EndpointCallbacks {
7069
std::function<void(const std::string&, void*, size_t)> onMessage;
7170
};
7271

72+
struct WebsocketClientStatusTypeTraits
73+
{
74+
enum _enum : unsigned char
75+
{
76+
ACTIVE = 0,
77+
GENERIC_ERROR = 1,
78+
CONNECTION_FAILED = 2,
79+
CLOSED = 3,
80+
MESSAGE_SEND_FAIL = 4,
81+
82+
NUM_TYPES
83+
};
84+
85+
protected:
86+
_enum m_value;
87+
};
88+
89+
using ClientStatusType = Enum<WebsocketClientStatusTypeTraits>;
90+
7391
class WebsocketEndpointManager {
7492
public:
7593
explicit WebsocketEndpointManager(ClientAdapterManager* mgr, const Dictionary & properties, Engine* engine);

cpp/csp/engine/StatusAdapter.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class StatusAdapter : public PushInputAdapter
4444
m_statusAccess.meta = meta;
4545
m_statusAccess.level = meta -> getMetaField<int64_t>( "level", "Status" );
4646
m_statusAccess.statusCode = meta -> getMetaField<int64_t>( "status_code", "Status" );
47-
m_statusAccess.msg = meta -> getMetaField<std::string>( "msg", "Status" );
47+
m_statusAccess.msg = meta -> getMetaField<typename csp::StringStructField::CType>( "msg", "Status" );
4848
}
4949

5050
void pushStatus( int64_t level, int64_t statusCode, const std::string & msg, PushBatch *batch = nullptr )

cpp/csp/engine/Struct.h

+81-18
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <string>
88
#include <vector>
99
#include <unordered_map>
10+
#include <iostream>
1011

1112
namespace csp
1213
{
@@ -668,16 +669,69 @@ class StructMeta : public std::enable_shared_from_this<StructMeta>
668669
};
669670

670671
template<typename T>
671-
std::shared_ptr<typename StructField::upcast<T>::type> StructMeta::getMetaField( const char * fieldname, const char * expectedtype )
672-
{
673-
auto field_ = field( fieldname );
674-
if( !field_ )
675-
CSP_THROW( TypeError, "Struct type " << name() << " missing required field " << fieldname << " for " << expectedtype );
672+
std::shared_ptr<typename StructField::upcast<T>::type> StructMeta::getMetaField(const char* fieldname, const char* expectedtype) {
673+
std::cout << "\n=== getMetaField Debug ===\n";
674+
std::cout << "1. Looking for field: " << fieldname << "\n";
675+
676+
auto field_ = field(fieldname);
677+
if(!field_) {
678+
std::cout << "2. Field not found!\n";
679+
CSP_THROW(TypeError, "Struct type " << name() << " missing required field " << fieldname);
680+
}
681+
682+
std::cout << "2. Field found\n";
683+
std::cout << "3. Field name from object: " << field_->fieldname() << "\n";
684+
std::cout << "4. Field type from CspType: " << field_->type()->type() << "\n";
685+
std::cout << "5. Expected type: " << CspType::Type::fromCType<T>::type << "\n";
686+
687+
// Memory layout & pointer checks
688+
const StructField* field_ptr = field_.get();
689+
std::cout << "6. Field ptr value: " << field_ptr << "\n";
690+
std::cout << "7. Field use count: " << field_.use_count() << "\n";
691+
692+
// Detailed field information
693+
if(field_ptr) {
694+
std::cout << "8. Field metadata:\n";
695+
std::cout << " - Field offset: " << field_ptr->offset() << "\n";
696+
std::cout << " - Field size: " << field_ptr->size() << "\n";
697+
std::cout << " - Field alignment: " << field_ptr->alignment() << "\n";
698+
std::cout << " - Field mask offset: " << field_ptr->maskOffset() << "\n";
699+
std::cout << " - Field mask bit: " << static_cast<int>(field_ptr->maskBit()) << "\n";
700+
701+
// Type verification
702+
std::cout << "9. Type checks:\n";
703+
std::cout << " - Original type: " << typeid(field_).name() << "\n";
704+
std::cout << " - Target type: " << typeid(typename StructField::upcast<T>::type).name() << "\n";
705+
std::cout << " - Is native: " << field_ptr->isNative() << "\n";
706+
707+
// Test various casts
708+
std::cout << "10. Detailed cast tests:\n";
709+
std::cout << " Base classes:\n";
710+
std::cout << " - As StructField*: " << (dynamic_cast<const StructField*>(field_ptr) != nullptr) << "\n";
711+
std::cout << " - As NonNativeStructField*: " << (dynamic_cast<const NonNativeStructField*>(field_ptr) != nullptr) << "\n";
712+
std::cout << " Non-native implementations:\n";
713+
std::cout << " - As StringStructField*: " << (dynamic_cast<const StringStructField*>(field_ptr) != nullptr) << "\n";
714+
std::cout << " - As DialectGenericStructField*: " << (dynamic_cast<const DialectGenericStructField*>(field_ptr) != nullptr) << "\n";
715+
std::cout << " - As ArrayStructField<std::string>*: " << (dynamic_cast<const ArrayStructField<std::vector<std::string>>*>(field_ptr) != nullptr) << "\n";
716+
std::cout << " Native field test:\n";
717+
std::cout << " - As NativeStructField<int64_t>*: " << (dynamic_cast<const NativeStructField<int64_t>*>(field_ptr) != nullptr) << "\n";
718+
}
719+
720+
using TargetType = typename StructField::upcast<T>::type;
721+
auto typedfield = std::dynamic_pointer_cast<TargetType>(field_);
722+
std::cout << "11. Final dynamic_cast result: " << (typedfield ? "success" : "failure") << "\n";
676723

677-
std::shared_ptr<typename StructField::upcast<T>::type> typedfield = std::dynamic_pointer_cast<typename StructField::upcast<T>::type>( field_ );
678-
if( !typedfield )
679-
CSP_THROW( TypeError, expectedtype << " - provided struct type " << name() << " expected type " << CspType::Type::fromCType<T>::type << " for field " << fieldname
680-
<< " but got type " << field_ -> type() -> type() << " for " << expectedtype );
724+
if(!typedfield) {
725+
std::cout << "12. FAILED CAST DETAILS:\n";
726+
std::cout << " - Source type: " << typeid(StructField).name() << "\n";
727+
std::cout << " - Target type: " << typeid(TargetType).name() << "\n";
728+
729+
CSP_THROW(TypeError, expectedtype << " - provided struct type " << name()
730+
<< " expected type " << CspType::Type::fromCType<T>::type
731+
<< " for field " << fieldname
732+
<< " but got type " << field_->type()->type()
733+
<< " for " << expectedtype);
734+
}
681735

682736
return typedfield;
683737
}
@@ -773,22 +827,31 @@ class Struct
773827
friend class StructMeta;
774828

775829
//Note these members are not included on size(), they're stored before "this" ptr ( see operator new / delete )
776-
struct HiddenData
777-
{
778-
size_t refcount;
779-
std::shared_ptr<const StructMeta> meta;
780-
void * dialectPtr;
830+
struct alignas(8) HiddenData {
831+
alignas(8) size_t refcount; // 8 bytes at 0x0
832+
alignas(8) std::shared_ptr<const StructMeta> meta; // 16 bytes at 0x8
833+
alignas(8) void* dialectPtr; // 8 bytes at 0x18
834+
// Total: 32 bytes
781835
};
782836

783837
const HiddenData * hidden() const
784838
{
785839
return const_cast<Struct *>( this ) -> hidden();
786840
}
787841

788-
HiddenData * hidden()
789-
{
790-
return reinterpret_cast<HiddenData *>( reinterpret_cast<uint8_t *>( this ) - sizeof( HiddenData ) );
791-
}
842+
static constexpr size_t HIDDEN_OFFSET = 32; // sizeof(HiddenData) aligned to 8 bytes
843+
844+
HiddenData* hidden() {
845+
std::byte* base = reinterpret_cast<std::byte*>(this);
846+
// Force alignment to match shared_ptr requirements
847+
static_assert(alignof(HiddenData) >= alignof(std::shared_ptr<void>),
848+
"HiddenData must be aligned for shared_ptr");
849+
return reinterpret_cast<HiddenData*>(base - HIDDEN_OFFSET);
850+
}
851+
// HiddenData * hidden()
852+
// {
853+
// return reinterpret_cast<HiddenData *>( reinterpret_cast<uint8_t *>( this ) - sizeof( HiddenData ) );
854+
// }
792855

793856
//actual data is allocated past this point
794857
};

csp/adapters/websocket.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import csp
1010
from csp import ts
11+
from csp.adapters.dynamic_adapter_utils import AdapterInfo
1112
from csp.adapters.status import Status
1213
from csp.adapters.utils import (
1314
BytesMessageProtoMapper,
@@ -17,20 +18,20 @@
1718
RawBytesMessageMapper,
1819
RawTextMessageMapper,
1920
)
21+
from csp.adapters.websocket_types import ActionType, ConnectionRequest, WebsocketHeaderUpdate, WebsocketStatus
2022
from csp.impl.wiring import input_adapter_def, output_adapter_def, status_adapter_def
2123
from csp.impl.wiring.delayed_node import DelayedNodeWrapperDef
2224
from csp.lib import _websocketadapterimpl
2325

24-
from .dynamic_adapter_utils import AdapterInfo
25-
from .websocket_types import ActionType, ConnectionRequest, WebsocketHeaderUpdate, WebsocketStatus # noqa
26-
2726
# InternalConnectionRequest,
2827
_ = (
28+
ActionType,
2929
BytesMessageProtoMapper,
3030
DateTimeType,
3131
JSONTextMessageMapper,
3232
RawBytesMessageMapper,
3333
RawTextMessageMapper,
34+
WebsocketStatus,
3435
)
3536
T = TypeVar("T")
3637

@@ -577,7 +578,7 @@ def update_headers(self, x: ts[List[WebsocketHeaderUpdate]]):
577578

578579
def status(self, push_mode=csp.PushMode.NON_COLLAPSING):
579580
ts_type = Status
580-
return status_adapter_def(self, ts_type, push_mode=push_mode)
581+
return status_adapter_def(self, ts_type, push_mode)
581582

582583
def _create(self, engine, memo):
583584
"""method needs to return the wrapped c++ adapter manager"""

0 commit comments

Comments
 (0)