├── CMakeLists.txt ├── COPYRIGHT ├── Makefile ├── NOSA GSC-18396-1.pdf ├── README.md ├── cfe_defs ├── cfe_mission_cfg.h ├── cfe_msgids.h ├── cfe_perfids.h └── cfe_platform_cfg.h ├── doc ├── Indv_CLA_SBNC.pdf ├── makefile ├── requirements.md └── requirements.pdf ├── fsw ├── public_inc │ ├── sbn_client_init.h │ └── sbn_client_wrappers.h ├── python_interface │ └── sbn_client.py └── src │ ├── sbn_client.c │ ├── sbn_client.h │ ├── sbn_client_defs.h │ ├── sbn_client_ingest.c │ ├── sbn_client_ingest.h │ ├── sbn_client_init.c │ ├── sbn_client_logger.c │ ├── sbn_client_logger.h │ ├── sbn_client_minders.c │ ├── sbn_client_minders.h │ ├── sbn_client_utils.c │ ├── sbn_client_utils.h │ ├── sbn_client_version.h │ └── sbn_client_wrappers.c ├── unit-test ├── CMakeLists.txt ├── helpers │ ├── sbn_client_common_test_utils.c │ ├── sbn_client_common_test_utils.h │ ├── sbn_client_wrapped_functions.c │ └── sbn_client_wrapped_functions.h ├── sbn_client_ingest_tests.c ├── sbn_client_init_tests.c ├── sbn_client_logger_tests.c ├── sbn_client_minders_tests.c ├── sbn_client_tests.c ├── sbn_client_tests_includes.h ├── sbn_client_utils_tests.c ├── sbn_client_wrappers_tests.c └── stubs │ ├── sbn_client_logger_stubs.c │ └── sbn_client_logger_stubs.h └── unwrap_symbols.txt /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6.4) 2 | project(CFS_SBN_CLIENT C) 3 | 4 | include_directories(fsw/public_inc) 5 | include_directories(${sbn_MISSION_DIR}/fsw/src) 6 | include_directories(${sbn_MISSION_DIR}/fsw/platform_inc) 7 | 8 | aux_source_directory(fsw/src APP_SRC_FILES) 9 | 10 | set(APP_NAME sbn_client) 11 | 12 | add_library(${APP_NAME} "SHARED" ${APP_SRC_FILES}) 13 | 14 | # Override the default behavior of attaching a "lib" prefix 15 | set_target_properties(${APP_NAME} PROPERTIES PREFIX "") 16 | # SBN? 17 | 18 | # Create the install targets for this shared/modular app 19 | foreach(TGT ${APP_INSTALL_LIST}) 20 | install(TARGETS ${APP_NAME} DESTINATION ${TGT}/${INSTALL_SUBDIR}) 21 | endforeach() 22 | 23 | if (ENABLE_UNIT_TESTS) 24 | add_subdirectory(unit-test) 25 | endif (ENABLE_UNIT_TESTS) 26 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright © 2019 United States Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S. Code. All Other Rights Reserved. 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SBN_CLIENT_SRC = ./fsw/src 2 | SBN_CLIENT_INC = -I./fsw/public_inc 3 | SBN_INC = -I../sbn/fsw/public_inc -I../sbn/fsw/platform_inc -I../sbn/fsw/src 4 | 5 | # cfe_platform_cfg.h is build specific, and comes from the defs folder. 6 | # Link the platform cfg you want (such as x86-64_platform_cfg.h) as cfe_defs/cfe_platform_cfg.h 7 | # The same goes for cfe_defs/cfe_mission_cfg.h, cfe_defs/cfe_msgids.h, cfe_defs/cfe_perfids.h 8 | CFE_DEFS = -I./cfe_defs 9 | 10 | CFE_INC = -I../../cfe/fsw/cfe-core/src/inc 11 | OSAL_INC = -I../../osal/src/os/inc 12 | OSAL_BSP_INC = -I../../osal/src/bsp/pc-linux/config 13 | PSP_INC = -I../../psp/fsw/inc 14 | PSP_BSP_INC = -I../../psp/fsw/pc-linux/inc 15 | 16 | LIBS = -lpthread 17 | 18 | SC_OBJS := sbn_client.a 19 | SC_OBJS += sbn_client_ingest.a 20 | SC_OBJS += sbn_client_init.a 21 | SC_OBJS += sbn_client_minders.a 22 | SC_OBJS += sbn_client_utils.a 23 | SC_OBJS += sbn_client_wrappers.a 24 | 25 | A_FILES := $(patsubst %.c,%.a,$(wildcard $(SBN_CLIENT_SRC)/*.c)) 26 | 27 | all: libsbn_client.so 28 | 29 | libsbn_client.so: $(A_FILES) 30 | gcc -shared $^ -o libsbn_client.so 31 | 32 | %.a : %.c 33 | gcc -Wall -Werror -c -fPIC $< $(SBN_CLIENT_INC) $(CFE_DEFS) $(CFE_INC) $(OSAL_INC) $(OSAL_BSP_INC) $(PSP_INC) $(PSP_BSP_INC) $(SBN_INC) $(LIBS) -o $@ 34 | objcopy --redefine-syms=unwrap_symbols.txt $@ 35 | 36 | clean: 37 | rm -f $(A_FILES) 38 | rm -f libsbn_client.so 39 | -------------------------------------------------------------------------------- /NOSA GSC-18396-1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/SBN-Client/8ab0cfb2136d87395ff5c2be56c6ac3fef818af1/NOSA GSC-18396-1.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SBN Client 2 | 3 | The Software Bus Network Client (SBNC) communicates with NASA's core Flight System (cFS) Software Bus Network (SBN) application. 4 | Its main purpose is to facilitate two-way communication from the cFS Software Bus service to an external application (i.e. an application that is not a child task of cFS). 5 | SBNC implements the SBN communication protocol and provides access to the Software Bus through a standalone C library. 6 | 7 | We also support using SBNC within existing cFS applications through a modified build system and function wrappers. 8 | The function wrappers allow the source code of the library to remain unchanged while optionally linking to cFS's libraries. 9 | This configuration allows the cFS application to be isolated in an OS process which provides memory isolation from the rest of cFS. 10 | 11 | SBNC is intended to support the rapid development of software concepts for future flight software and technology demonstrations. 12 | It is not intended to be used in flight software. 13 | 14 | ## Compatible cFS and SBN Version 15 | 16 | Currently works with the cFS integration candidate from 2020-05-27: [github.com/nasa/cFS](https://github.com/nasa/cFS/tree/da695db7daaf3ca417662b81c5b9ea48c67be78f), which uses cFE 6.7.19 [github.com/nasa/cFE](https://github.com/nasa/cFE/tree/ad2190af9a2b40c9b9d0f3b88f601e931ad4059d). 17 | 18 | Tested with SBN 1.11.0, specifically: [github.com/nasa/SBN](https://github.com/nasa/SBN/tree/ea45ea4a075b1e28e0fd3413c63a3ad6ce57aba0). 19 | 20 | ## Configuration 21 | 22 | Configuration is set by defines in [`sbn_client_defs.h`](./fsw/src/sbn_client_defs.h). 23 | For now, this is only the IP address and port used by SBN, which should match that in `sbn_conf_tbl.c`. 24 | 25 | ## Standalone Library 26 | 27 | This version is meant to allow an outside program to communicate with a [cFS](https://github.com/NASA/cFS) instantiation through the Software Bus, mediated by the [Software Bus Network](https://github.com/nasa/SBN). It may be used for bindings to other languages, such as Python, and does not require the rest of cFE to be linked. 28 | 29 | The SBN communicates with sbn_client via TCP/IP with the port and IP address set in the sbn_client_defs.h file. These may be updated for the user's particular instance. 30 | 31 | The functions provided are exported in sbn_client.h and the redefined symbols can be found in unwrap_sybmols.txt. 32 | 33 | ### Building 34 | 35 | The first thing to do is edit the `Makefile` and ensure that all of the included directories are set correctly. 36 | Headers from SBN, cFE, OSAL, and PSP are all required so that things like the message size matches between cFS and the standalone application. 37 | In addition, cFS has several generated headers in the mission defs folder that should be linked. 38 | Once done, running `make` should produce `sbn_client.so` which may be linked by your program. 39 | 40 | ## Process Application Library 41 | 42 | Intended to be used by cFS applications that are isolated as separate processes. 43 | 44 | ### Building 45 | 46 | The sbn_client directory should be located with all of the other cFS applications. 47 | The library will be built by cFS's CMake system. 48 | 49 | ## Why We Did It This Way 50 | 51 | There are a number of workarounds used to allow for SBN Client to be used in both environments, but ultimately these are preferable to having diverging source code. 52 | The crux of the problem is that for process applications the library needs to be linked alongside of the rest of cFS. 53 | Thus we have to wrap function names that we want to override for the process applications, and then unwrap those calls for standalone applications. 54 | 55 | ## License and Copyright 56 | 57 | Please refer to [NOSA GSC-18396-1.pdf](NOSA%20GSC-18396-1.pdf) and [COPYRIGHT](COPYRIGHT). 58 | 59 | ## Contributions 60 | 61 | Please open an issue if you find any problems. 62 | We are a small team, but will try to respond in a timely fashion. 63 | 64 | If you would like to contribute code, GREAT! 65 | First you will need to complete the [Individual Contributor License Agreement (pdf)](doc/Indv_CLA_SBNC.pdf) and email it to gsfc-softwarerequest@mail.nasa.gov with james.marshall-1@nasa.gov CCed. 66 | 67 | Next, please create an issue for the fix or feature and note that you intend to work on it. 68 | Fork the repository and create a branch with a name that starts with the issue number. 69 | Once done, submit your pull request and we'll take a look. 70 | You may want to make draft pull requests to solicit feedback on larger changes. 71 | -------------------------------------------------------------------------------- /cfe_defs/cfe_mission_cfg.h: -------------------------------------------------------------------------------- 1 | ../../../mps_defs/mps_mission_cfg.h -------------------------------------------------------------------------------- /cfe_defs/cfe_msgids.h: -------------------------------------------------------------------------------- 1 | ../../../mps_defs/x86-64_msgids.h -------------------------------------------------------------------------------- /cfe_defs/cfe_perfids.h: -------------------------------------------------------------------------------- 1 | ../../../mps_defs/mps_perfids.h -------------------------------------------------------------------------------- /cfe_defs/cfe_platform_cfg.h: -------------------------------------------------------------------------------- 1 | ../../../mps_defs/x86-64_platform_cfg.h -------------------------------------------------------------------------------- /doc/Indv_CLA_SBNC.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/SBN-Client/8ab0cfb2136d87395ff5c2be56c6ac3fef818af1/doc/Indv_CLA_SBNC.pdf -------------------------------------------------------------------------------- /doc/makefile: -------------------------------------------------------------------------------- 1 | all: requirements.pdf 2 | 3 | requirements.pdf: requirements.md 4 | pandoc -f markdown -t latex -V geometry:margin=1in --variable urlcolor=blue -o requirements.pdf requirements.md 5 | 6 | clean: 7 | rm -f *.pdf 8 | -------------------------------------------------------------------------------- /doc/requirements.md: -------------------------------------------------------------------------------- 1 | # Software Bus Network Client (SBNC) Requirements 2 | 3 | Refer to git commits for document history and revisions. 4 | 5 | The primary requirement of the software is that it must correctly implement the SBN communication protocol. 6 | Fulfillment of this requirement is confirmed via unit tests which are included with the source code. 7 | Functional testing is performed with demonstration projects (not yet publicly available). 8 | 9 | ## 1. Implement SBN Protocol 10 | 11 | SBNC shall implement the Software Bus Network (SBN) protocol for one or more of the supported modules (such as TCP / IP). 12 | This includes subscribing, sending, and receiving messages to and from the Software Bus. 13 | 14 | ## 2. Build for cFS Applications 15 | 16 | SBNC shall support building and linking as a library for cFS applications that are isolated from cFS as an external process. 17 | 18 | ## 3. Build as Standalone Library 19 | 20 | SBNC shall support building and linking as a standalone library for C applications (without linking cFS). 21 | 22 | ### 3.1 Language Support 23 | 24 | The standalone library shall be usable by programs written in other languages such as Python through foreign function interfaces. 25 | -------------------------------------------------------------------------------- /doc/requirements.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/SBN-Client/8ab0cfb2136d87395ff5c2be56c6ac3fef818af1/doc/requirements.pdf -------------------------------------------------------------------------------- /fsw/public_inc/sbn_client_init.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #ifndef _sbn_client_init_h_ 14 | #define _sbn_client_init_h_ 15 | 16 | /****************************************************************************** 17 | ** File: sbn_client_init.h 18 | ** 19 | ** Purpose: 20 | ** This header file contains the definition of the cFS sbn_client app's 21 | ** initialization function. The init function must be called by a cFS 22 | ** multi-process app in order to use the features of cFE that sbn_client 23 | ** provides. 24 | ** 25 | ** Author: A.Gibson/587 26 | ** 27 | ******************************************************************************/ 28 | /****************** Function Prototypes **********************/ 29 | 30 | /** @defgroup SBNCLIENTAPIInitialization sbn_client Init API 31 | * @{ 32 | */ 33 | 34 | /*****************************************************************************/ 35 | /** 36 | ** \brief Initialized the client by connecting to SBN. 37 | ** 38 | ** \par Description 39 | ** This function must be called by a multi-process cFS app that wants 40 | ** to use the cFE SB functions that sbn_client makes available. 41 | ** Without calling this, there will not be a communication channel set 42 | ** up with SBN running in a cFE instance. 43 | ** 44 | ** \par Assumptions, External Events, and Notes: 45 | ** There is a TCP/IP connection available to a cFE instance running 46 | ** SBN. The port and IP of that instance is defined in 47 | ** the sbn_client_defs.h file. 48 | ** 49 | ** 50 | ** \return Execution status 51 | ** \retval #CFE_SUCCESS The client connected and is ready for use 52 | ** \retval #SBN_CLIENT_BAD_SOCK_FD_EID Connect to server failed 53 | ** \retval #SBN_CLIENT_HEART_THREAD_CREATE_EID Heartbeat thread failed init 54 | ** \retval #SBN_CLIENT_RECEIVE_THREAD_CREATE_EID Receive thread failed init 55 | ** \retval #SBN_CLIENT_NO_STATUS_SET Default setting, function has a problem 56 | ** 57 | */ 58 | int32 SBN_Client_Init(void); 59 | /**@}*/ 60 | 61 | #endif /* _sbn_client_init_h_ */ 62 | /*****************************************************************************/ -------------------------------------------------------------------------------- /fsw/public_inc/sbn_client_wrappers.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #ifndef _sbn_client_wrappers_h_ 14 | #define _sbn_client_wrappers_h_ 15 | 16 | #include 17 | 18 | 19 | 20 | /****************** Function Prototypes **********************/ 21 | 22 | /** @defgroup SBNCLIENTAPISBPipe SBN_Client Pipe Management APIs 23 | * @{ 24 | */ 25 | 26 | /*****************************************************************************/ 27 | /** 28 | ** \brief SBN_Client replacement for CFE_SB_CreatePipe that creates a new 29 | ** software bus pipe. 30 | ** 31 | ** \par Description see \ref CFEAPISBPipe 32 | ** \copybrief CFE_SB_CreatePipe 33 | ** 34 | **/ 35 | int32 __wrap_CFE_SB_CreatePipe(CFE_SB_PipeId_t *, uint16, const char *); 36 | 37 | 38 | /*****************************************************************************/ 39 | /** 40 | ** \brief SBN_Client replacement for CFE_SB_DeletePipe that 41 | ** 42 | ** \par Description see \ref CFEAPISBPipe 43 | ** \copybrief CFE_SB_DeletePipe 44 | ** 45 | **/ 46 | int32 __wrap_CFE_SB_DeletePipe(CFE_SB_PipeId_t); 47 | /**@}*/ 48 | 49 | /** @defgroup SBNCLIENTAPISBSubscription sbn_client Message Subscription Control APIs 50 | * @{ 51 | */ 52 | 53 | /*****************************************************************************/ 54 | /** 55 | ** \brief SBN_Client replacement for CFE_SB_Subscribe that 56 | ** 57 | ** \par Description see \ref CFEAPISBSubscription 58 | ** \copybrief CFE_SB_Subscribe 59 | ** 60 | **/ 61 | int32 __wrap_CFE_SB_Subscribe(CFE_SB_MsgId_t, CFE_SB_PipeId_t); 62 | 63 | /*****************************************************************************/ 64 | /** 65 | ** \brief SBN_Client replacement for CFE_SB_SubscribeEx that 66 | ** 67 | ** \par Description see \ref CFEAPISBSubscription 68 | ** CFE_SB_SubscribeEx not yet implemented. 69 | ** 70 | **/ 71 | int32 __wrap_CFE_SB_SubscribeEx(CFE_SB_MsgId_t, CFE_SB_PipeId_t, 72 | CFE_SB_Qos_t, uint16); 73 | 74 | /*****************************************************************************/ 75 | /** 76 | ** \brief SBN_Client replacement for CFE_SB_SubscribeLocal that 77 | ** 78 | ** \par Description see \ref CFEAPISBSubscription 79 | ** CFE_SB_SubscribeLocal not yet implemented. 80 | ** 81 | **/ 82 | int32 __wrap_CFE_SB_SubscribeLocal(CFE_SB_MsgId_t, CFE_SB_PipeId_t, uint16); 83 | 84 | /*****************************************************************************/ 85 | /** 86 | ** \brief SBN_Client replacement for CFE_SB_Unsubscribe that 87 | ** 88 | ** \par Description see \ref CFEAPISBSubscription 89 | ** CFE_SB_Unsubscribe not yet implemented. 90 | ** 91 | **/ 92 | int32 __wrap_CFE_SB_Unsubscribe(CFE_SB_MsgId_t, CFE_SB_PipeId_t); 93 | 94 | /*****************************************************************************/ 95 | /** 96 | ** \brief SBN_Client replacement for CFE_SB_UnsubscribeLocal that 97 | ** 98 | ** \par Description see \ref CFEAPISBSubscription 99 | ** CFE_SB_UnsubscribeLocal not yet implemented. 100 | ** 101 | **/ 102 | int32 __wrap_CFE_SB_UnsubscribeLocal(CFE_SB_MsgId_t, CFE_SB_PipeId_t); 103 | /**@}*/ 104 | 105 | /** @defgroup SBNCLIENTAPISBMessage SBN_Client Send/Receive Message APIs 106 | * @{ 107 | */ 108 | 109 | /*****************************************************************************/ 110 | /** 111 | ** \brief SBN_Client replacement for CFE_SB_SendMsg that 112 | ** 113 | ** \par Description see \ref CFEAPISBMessage 114 | ** \copybrief CFE_SB_SendMsg 115 | ** 116 | **/ 117 | uint32 __wrap_CFE_SB_SendMsg(CFE_SB_Msg_t *); 118 | 119 | /*****************************************************************************/ 120 | /** 121 | ** \brief SBN_Client replacement for CFE_SB_RcvMsg that 122 | ** 123 | ** \par Description see \ref CFEAPISBMessage 124 | ** \copybrief CFE_SB_RcvMsg 125 | ** 126 | **/ 127 | int32 __wrap_CFE_SB_RcvMsg(CFE_SB_MsgPtr_t *, CFE_SB_PipeId_t, int32); 128 | 129 | /*****************************************************************************/ 130 | /** 131 | ** \brief SBN_Client replacement for CFE_SB_ZeroCopySend that 132 | ** 133 | ** \par Description 134 | ** CFE_SB_ZeroCopySend not yet implemented. 135 | ** 136 | **/ 137 | int32 __wrap_CFE_SB_ZeroCopySend(CFE_SB_Msg_t *, CFE_SB_ZeroCopyHandle_t); 138 | /**@}*/ 139 | 140 | #endif /* _sbn_client_wrappers_h_ */ 141 | /*****************************************************************************/ -------------------------------------------------------------------------------- /fsw/python_interface/sbn_client.py: -------------------------------------------------------------------------------- 1 | # 2 | # GSC-18396-1, “Software Bus Network Client for External Process” 3 | # 4 | # Copyright © 2019 United States Government as represented by 5 | # the Administrator of the National Aeronautics and Space Administration. 6 | # No copyright is claimed in the United States under Title 17, U.S. Code. 7 | # All Other Rights Reserved. 8 | # 9 | # Licensed under the NASA Open Source Agreement version 1.3 10 | # See "NOSA GSC-18396-1.pdf" 11 | # 12 | 13 | import ctypes 14 | from ctypes import * 15 | 16 | # SB 17 | CFE_SB_PEND_FOREVER = -1 18 | 19 | 20 | # typedef struct { 21 | # uint8 StreamId[2]; /* packet identifier word (stream ID) */ 22 | # /* bits shift ------------ description ---------------- */ 23 | # /* 0x07FF 0 : application ID */ 24 | # /* 0x0800 11 : secondary header: 0 = absent, 1 = present */ 25 | # /* 0x1000 12 : packet type: 0 = TLM, 1 = CMD */ 26 | # /* 0xE000 13 : CCSDS version: 0 = ver 1, 1 = ver 2 */ 27 | # uint8 Sequence[2]; /* packet sequence word */ 28 | # /* bits shift ------------ description ---------------- */ 29 | # /* 0x3FFF 0 : sequence count */ 30 | # /* 0xC000 14 : segmentation flags: 3 = complete packet */ 31 | # uint8 Length[2]; /* packet length word */ 32 | # /* bits shift ------------ description ---------------- */ 33 | # /* 0xFFFF 0 : (total packet length) - 7 */ 34 | # } CCSDS_PriHdr_t; 35 | 36 | # Version 2 of CCSDS has 4 extra bytes for the secondary header 37 | # typedef struct { 38 | # uint8 APIDQSubsystem[2]; 39 | # uint8 APIDQSystemId[2]; 40 | # } CCSDS_APIDqualifiers_t; 41 | 42 | # The time format is configurable... using 2 bytes right now 43 | # typedef struct { 44 | # uint8 Time[CCSDS_TIME_SIZE]; 45 | # } CCSDS_TlmSecHdr_t; 46 | 47 | # typedef union { 48 | # CCSDS_PriHdr_t Hdr; /**< \brief CCSDS Primary Header #CCSDS_PriHdr_t */ 49 | # CCSDS_SpacePacket_t SpacePacket; 50 | # uint32 Dword; /**< \brief Forces minimum of 32-bit alignment for this object */ 51 | # uint8 Byte[sizeof(CCSDS_PriHdr_t)]; /**< \brief Allows byte-level access */ 52 | # }CFE_SB_Msg_t; 53 | 54 | # Note: Not currently dealing with the whole union issue 55 | class Primary_Header_t(BigEndianStructure): 56 | _pack_ = 1 57 | _fields_ = [("StreamId", c_uint16), 58 | ("Sequence", c_uint16), 59 | ("Length", c_uint16)] 60 | 61 | class Secondary_Header_t(BigEndianStructure): 62 | _pack_ = 1 63 | _fields_ = [("Seconds", c_uint32), 64 | ("Subseconds", c_uint16)] 65 | 66 | # typedef struct { 67 | # uint8 FunctionCode; /* Command Function Code */ 68 | # /* bits shift ---------description-------- */ 69 | # /* 0x7F 0 Command function code */ 70 | # /* 0x80 7 Reserved */ 71 | # 72 | # uint8 Checksum; /* Command checksum (all bits, 0xFF) */ 73 | # } CCSDS_CmdSecHdr_t; 74 | 75 | class Command_Header_t(Structure): 76 | _pack_ = 1 77 | _fields_ = [("FunctionCode", c_uint8), 78 | ("Checksum", c_uint8)] 79 | 80 | class CFE_SB_Msg_t(Structure): 81 | _pack_ = 1 82 | _fields_ = [("Primary", Primary_Header_t), 83 | ("Secondary", Secondary_Header_t)] 84 | 85 | #for generic data type 86 | # TODO Should the max message size be hardcoded or somehow taken from the mps_defs directory? 87 | class sbn_data_generic_t(Structure): 88 | _pack_ = 1 89 | _fields_ = [("TlmHeader", CFE_SB_Msg_t), 90 | ("byte_array", c_ubyte * 65536)] 91 | 92 | sbn_client = None 93 | cmd_pipe = c_ushort() 94 | cmd_pipe_name = create_string_buffer(b'cmd_pipe') 95 | 96 | 97 | def print_header(message_p): 98 | recv_msg = message_p.contents 99 | print("Message Header: {} {} {}".format(hex(recv_msg.TlmHeader.Primary.StreamId), 100 | hex(recv_msg.TlmHeader.Primary.Sequence), 101 | hex(recv_msg.TlmHeader.Primary.Length))) 102 | print("Message Time: {} {}".format(hex(recv_msg.TlmHeader.Secondary.Seconds), 103 | hex(recv_msg.TlmHeader.Secondary.Subseconds))) 104 | 105 | # TODO: Common file? 106 | def cfs_error_convert (number): 107 | if number < 0: 108 | return number + (2**32) 109 | else: 110 | return number 111 | 112 | def sbn_load_and_init(): 113 | global sbn_client 114 | global cmd_pipe 115 | global cmd_pipe_name 116 | 117 | ctypes.cdll.LoadLibrary('./sbn_client.so') 118 | sbn_client = CDLL('sbn_client.so') 119 | print("SBN Client library loaded: '{}'".format(sbn_client)) 120 | status = sbn_client.SBN_Client_Init() 121 | print("SBN Client init: {}".format(status)) 122 | status = sbn_client.__wrap_CFE_SB_CreatePipe(byref(cmd_pipe), 10, cmd_pipe_name) 123 | print("SBN Client command pipe: {}".format(status)) 124 | 125 | def send_msg(send_msg_p): 126 | global sbn_client 127 | 128 | sbn_client.__wrap_CFE_SB_SendMsg(send_msg_p) 129 | 130 | def recv_msg(recv_msg_p): 131 | global sbn_client 132 | global cmd_pipe 133 | 134 | status = sbn_client.__wrap_CFE_SB_RcvMsg(byref(recv_msg_p), cmd_pipe, CFE_SB_PEND_FOREVER) 135 | print("status of __wrap_CFE_SB_RcvMsg = %X" % cfs_error_convert(status)) 136 | #recv_msg = recv_msg_p.contents 137 | #print("Message: {} {} {}".format(hex(recv_msg.Hdr.StreamId), hex(recv_msg.Hdr.Sequence), hex(recv_msg.Hdr.Length))) 138 | #print_header(recv_msg_p) 139 | 140 | def subscribe(msgid): 141 | global cmd_pipe 142 | 143 | status = sbn_client.__wrap_CFE_SB_Subscribe(msgid, cmd_pipe) 144 | print("SBN Client subscribe msg (id {}): {}".format(hex(msgid), status)) 145 | -------------------------------------------------------------------------------- /fsw/src/sbn_client.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include "sbn_client.h" 14 | #include "sbn_client_ingest.h" 15 | #include "sbn_client_utils.h" 16 | 17 | /* Global variables */ 18 | CFE_SBN_Client_PipeD_t PipeTbl[CFE_PLATFORM_SBN_CLIENT_MAX_PIPES]; 19 | MsgId_to_pipes_t MsgId_Subscriptions[CFE_SBN_CLIENT_MSG_ID_TO_PIPE_ID_MAP_SIZE]; 20 | int sbn_client_sockfd = 0; 21 | int sbn_client_cpuId = 0; 22 | // TODO: Our use of sockfd is not uniform. Should pass to each function XOR use as global 23 | // TODO: sbn_client_cpuId does not need to live here; perhaps it should go elsewhere 24 | 25 | 26 | void CFE_SBN_Client_InitPipeTbl(void) 27 | { 28 | uint8 i; 29 | 30 | for(i = 0; i < CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; i++){ 31 | invalidate_pipe(&PipeTbl[i]); 32 | }/* end for */ 33 | 34 | 35 | } 36 | 37 | CFE_SB_PipeId_t CFE_SBN_Client_GetAvailPipeIdx(void) 38 | { 39 | uint8 i; 40 | 41 | /* search for next available pipe entry */ 42 | for(i = 0; i < CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; i++) 43 | { 44 | if(PipeTbl[i].InUse == CFE_SBN_CLIENT_NOT_IN_USE){ 45 | return i; 46 | }/* end if */ 47 | 48 | }/* end for */ 49 | 50 | return CFE_SBN_CLIENT_INVALID_PIPE; 51 | } 52 | 53 | /** 54 | * \brief Sends a local subscription over the wire to a peer. 55 | * 56 | * @param[in] SubType Whether this is a subscription or unsubscription. 57 | * @param[in] MsgID The CCSDS message ID being (un)subscribed. 58 | * @param[in] QoS The CCSDS quality of service being (un)subscribed. 59 | * @param[in] Peer The Peer interface 60 | */ 61 | void SendSubToSbn(int SubType, CFE_SB_MsgId_t MsgID, 62 | CFE_SB_Qos_t QoS) 63 | { 64 | char Buf[SBN_PACKED_SUB_SZ] = {0}; 65 | Pack_t Pack; 66 | Pack_Init(&Pack, Buf, SBN_PACKED_SUB_SZ, 0); 67 | Pack_UInt16(&Pack, 54); 68 | Pack_UInt8(&Pack, SubType); 69 | Pack_UInt32(&Pack, 2); 70 | Pack_Data(&Pack, (void *)SBN_IDENT, (size_t)SBN_IDENT_LEN); 71 | Pack_UInt16(&Pack, 1); 72 | 73 | Pack_MsgID(&Pack, MsgID); 74 | Pack_Data(&Pack, &QoS, sizeof(QoS)); /* 2 uint8's */ 75 | 76 | size_t write_result = write_message(sbn_client_sockfd, Buf, Pack.BufUsed); 77 | 78 | if (write_result != Pack.BufUsed) 79 | { 80 | log_message("SBN_CLIENT: ERROR SendSubToSbn!!\n"); 81 | } 82 | 83 | }/* end SendLocalSubToPeer */ 84 | 85 | 86 | int32 recv_msg(int32 sockfd) 87 | { 88 | unsigned char sbn_hdr_buffer[SBN_PACKED_HDR_SZ]; 89 | unsigned char msg[CFE_SB_MAX_SB_MSG_SIZE]; 90 | SBN_MsgSz_t MsgSz; 91 | SBN_MsgType_t MsgType; 92 | uint32 CpuID; 93 | 94 | int status = CFE_SBN_CLIENT_ReadBytes(sockfd, sbn_hdr_buffer, 95 | SBN_PACKED_HDR_SZ); 96 | 97 | if (status != CFE_SUCCESS) 98 | { 99 | printf("SBN_CLIENT: recv_msg call to CFE_SBN_CLIENT_ReadBytes returned" 100 | "status = %d\n", status); 101 | } 102 | else 103 | { 104 | Unpack_t Unpack; 105 | Unpack_Init(&Unpack, sbn_hdr_buffer, SBN_PACKED_HDR_SZ); 106 | Unpack_UInt16(&Unpack, &MsgSz); 107 | Unpack_UInt8(&Unpack, &MsgType); 108 | Unpack_UInt32(&Unpack, &CpuID); 109 | 110 | //TODO: check cpuID to see if it is correct for this location? 111 | 112 | switch(MsgType) 113 | { 114 | case SBN_NO_MSG: 115 | status = CFE_SBN_CLIENT_ReadBytes(sockfd, msg, MsgSz); 116 | break; 117 | case SBN_SUB_MSG: 118 | status = CFE_SBN_CLIENT_ReadBytes(sockfd, msg, MsgSz); 119 | break; 120 | case SBN_UNSUB_MSG: 121 | status = CFE_SBN_CLIENT_ReadBytes(sockfd, msg, MsgSz); 122 | break; 123 | case SBN_APP_MSG: 124 | ingest_app_message(sockfd, MsgSz); 125 | status = CFE_SUCCESS; 126 | break; 127 | case SBN_PROTO_MSG: 128 | status = CFE_SBN_CLIENT_ReadBytes(sockfd, msg, MsgSz); 129 | break; 130 | case SBN_HEARTBEAT_MSG: 131 | status = CFE_SBN_CLIENT_ReadBytes(sockfd, msg, MsgSz); 132 | break; 133 | 134 | default: 135 | log_message("SBN_CLIENT: ERROR - recv_msg unrecognized type %d\n", MsgType); 136 | status = CFE_EVS_ERROR; //TODO: change error 137 | } 138 | 139 | } 140 | 141 | return status; 142 | } 143 | 144 | -------------------------------------------------------------------------------- /fsw/src/sbn_client.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #ifndef _sbn_client_h_ 14 | #define _sbn_client_h_ 15 | 16 | /************************************************************************ 17 | ** Includes 18 | *************************************************************************/ 19 | 20 | #include "sbn_interfaces.h" 21 | 22 | /************************************************************************ 23 | ** Constants Definitions 24 | *************************************************************************/ 25 | #define SBN_CLIENT_SUCCESS OS_SUCCESS 26 | 27 | #define CFE_SBN_CLIENT_NOT_IN_USE 0 28 | #define CFE_SBN_CLIENT_IN_USE 1 29 | #define CFE_SBN_CLIENT_UNUSED_QUEUE 0xFFFF 30 | #define CFE_SBN_CLIENT_BAD_ARGUMENT CFE_SB_BAD_ARGUMENT 31 | #define CFE_SBN_CLIENT_INVALID_PIPE 0xFF 32 | #define SBN_CLIENT_NO_STATUS_SET 0xFFFF 33 | #define SBN_CLIENT_BAD_SOCK_FD_EID 0x0100 34 | #define CFE_SBN_CLIENT_CR_PIPE_BAD_ARG_EID 1002 35 | #define CFE_SBN_CLIENT_MAX_PIPES_MET 1003 36 | #define CFE_SBN_CLIENT_MAX_PIPES_MET_EID 1004 37 | #define CFE_SBN_CLIENT_CR_PIPE_ERR_EID 1005 38 | #define CFE_SBN_CLIENT_PIPE_ADDED_EID 1006 39 | #define CFE_SBN_CLIENT_PIPE_DELETED_EID 1007 40 | #define CFE_SBN_CLIENT_MAX_MSG_IDS_MET 0xFF 41 | #define CFE_SBN_CLIENT_MAX_MSG_IDS_MET_EID 1009 42 | #define CFE_SBN_CLIENT_PIPE_BROKEN_ERR 1010 43 | #define CFE_SBN_CLIENT_PIPE_CLOSED_ERR 1011 44 | #define CFE_SBN_CLIENT_PIPE_CR_ERR ((int32)0xca001005) 45 | #define SBN_CLIENT_HEART_THREAD_CREATE_EID 1012 46 | #define SBN_CLIENT_RECEIVE_THREAD_CREATE_EID 1013 47 | 48 | #define CFE_SBN_CLIENT_INVALID_MSG_ID 0 49 | #define CFE_SBN_CLIENT_NO_PROTOCOL 0 50 | 51 | #define SERVER_SOCKET_ERROR -1 52 | #define SERVER_INET_PTON_SRC_ERROR -2 53 | #define SERVER_INET_PTON_INVALID_AF_ERROR -3 54 | #define SERVER_CONNECT_ERROR -4 55 | 56 | 57 | /************************************************************************* 58 | ** Exported Functions 59 | *************************************************************************/ 60 | 61 | void CFE_SBN_Client_InitPipeTbl(void); 62 | CFE_SB_PipeId_t CFE_SBN_Client_GetAvailPipeIdx(void); 63 | int32 recv_msg(int32); 64 | void SendSubToSbn(int, CFE_SB_MsgId_t, CFE_SB_Qos_t); 65 | 66 | #endif /* _sbn_client_h_ */ 67 | 68 | /************************/ 69 | /* End of File Comment */ 70 | /************************/ 71 | -------------------------------------------------------------------------------- /fsw/src/sbn_client_defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #ifndef _sbn_client_defs_h_ 14 | #define _sbn_client_defs_h_ 15 | 16 | /* Refer to sbn_cont_tbl.c to make sure port and ip_addr match 17 | * SBN is running here: <- Should be in the platform config */ 18 | #define SBN_CLIENT_PORT 1234 19 | #define SBN_CLIENT_IP_ADDR "127.0.0.1" 20 | 21 | #define CFE_SBN_CLIENT_MSG_ID_TO_PIPE_ID_MAP_SIZE 32 22 | #define SBN_HEARTBEAT_MSG 0xA0 23 | #define CFE_SBN_CLIENT_MAX_MESSAGE_SIZE CFE_SB_MAX_SB_MSG_SIZE 24 | #define CFE_SBN_CLIENT_MAX_MSG_IDS_PER_PIPE 4 25 | #define CFE_PLATFORM_SBN_CLIENT_MAX_PIPES 5 /* CFE_PLATFORM_SB_MAX_PIPES could be used */ 26 | #define CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH 32 27 | 28 | #endif /* _sbn_client_defs_h_ */ -------------------------------------------------------------------------------- /fsw/src/sbn_client_ingest.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | #include "sbn_client_ingest.h" 17 | 18 | pthread_mutex_t receive_mutex = PTHREAD_MUTEX_INITIALIZER; 19 | pthread_cond_t received_condition = PTHREAD_COND_INITIALIZER; 20 | 21 | /* TODO: Using memcpy to move message into pipe. What about pointer passing? 22 | * Can we only look to msgId then memcpy only that then read directly 23 | * into pipe? This could speed things up... 24 | * passing pointers will only work here if it is guaranteed that the message 25 | * will not be destroyed. SBN may not be able to provide that assurance */ 26 | 27 | void ingest_app_message(int SockFd, SBN_MsgSz_t MsgSz) 28 | { 29 | int status, i; 30 | boolean at_least_1_pipe_is_in_use = FALSE; 31 | unsigned char msg_buffer[CFE_SB_MAX_SB_MSG_SIZE]; 32 | CFE_SB_MsgId_t MsgId; 33 | 34 | status = CFE_SBN_CLIENT_ReadBytes(SockFd, msg_buffer, MsgSz); 35 | 36 | if (status != CFE_SUCCESS) 37 | { 38 | char error_message[61]; 39 | 40 | snprintf(error_message, sizeof(error_message), 41 | "CFE_SBN_CLIENT_ReadBytes returned a bad status = 0x%08X\n", status); 42 | log_message(error_message); 43 | 44 | return; 45 | } 46 | 47 | MsgId = CFE_SBN_Client_GetMsgId((CFE_SB_MsgPtr_t)msg_buffer); 48 | 49 | pthread_mutex_lock(&receive_mutex); 50 | 51 | /* Put message into pipe */ 52 | for(i = 0; i < CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; i++) 53 | { 54 | if (PipeTbl[i].InUse == CFE_SBN_CLIENT_IN_USE) 55 | { 56 | int j; 57 | 58 | at_least_1_pipe_is_in_use = TRUE; 59 | 60 | for(j = 0; j < CFE_SBN_CLIENT_MAX_MSG_IDS_PER_PIPE; j++) 61 | { 62 | if (PipeTbl[i].SubscribedMsgIds[j] == MsgId) 63 | { 64 | if (PipeTbl[i].NumberOfMessages == CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH) 65 | { 66 | /* TODO: handle error pipe overflow */ 67 | log_message("SBN_CLIENT: ERROR pipe overflow"); 68 | 69 | pthread_mutex_unlock(&receive_mutex); 70 | return; 71 | } 72 | else /* message is put into pipe */ 73 | { 74 | log_message("App message received: MsgId 0x%08X", MsgId); 75 | 76 | memcpy(PipeTbl[i].Messages[message_entry_point(PipeTbl[i])], msg_buffer, MsgSz); 77 | PipeTbl[i].NumberOfMessages++; 78 | 79 | pthread_mutex_unlock(&receive_mutex); 80 | 81 | /* only a received message should send signal */ 82 | pthread_cond_signal(&received_condition); 83 | 84 | return; 85 | } /* end if */ 86 | 87 | }/* end if */ 88 | 89 | } /* end for */ 90 | 91 | } /* end if */ 92 | 93 | } /* end for */ 94 | 95 | if (at_least_1_pipe_is_in_use) 96 | { 97 | log_message("SBN_CLIENT: ERROR no subscription for this msgid"); 98 | } 99 | else 100 | { 101 | log_message("SBN_CLIENT: No pipes are in use"); 102 | } 103 | 104 | pthread_mutex_unlock(&receive_mutex); 105 | } -------------------------------------------------------------------------------- /fsw/src/sbn_client_ingest.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #ifndef _sbn_client_ingest_h_ 14 | #define _sbn_client_ingest_h_ 15 | 16 | #include "sbn_interfaces.h" 17 | #include "sbn_client_utils.h" 18 | 19 | 20 | /** 21 | * Extern reference to sbn client pipe table. 22 | * Allows the message ingest to fill the pipe 23 | */ 24 | extern CFE_SBN_Client_PipeD_t PipeTbl[CFE_PLATFORM_SBN_CLIENT_MAX_PIPES]; 25 | 26 | /****************** Function Prototypes **********************/ 27 | 28 | /** @defgroup SBNCLIENTIngest 29 | * @{ 30 | */ 31 | 32 | /*****************************************************************************/ 33 | /** 34 | ** \brief Receive an app message and direct it into pipe. 35 | ** 36 | ** \par Description 37 | ** This routine reads the given number of bytes from the given socket, 38 | ** which becomes the message. The message is then copied into the 39 | ** correct pipe for the message's id. 40 | ** 41 | ** \par Assumptions, External Events, and Notes: 42 | ** The socket has been setup and receives app messages. 43 | ** 44 | ** \param[in] SockFd A socket file descriptor that connects to the 45 | ** that delivers app messages. 46 | ** 47 | ** \param[in] MsgSz The number of bytes to read for the message. 48 | ** 49 | **/ 50 | void ingest_app_message(int SockFd, SBN_MsgSz_t MsgSz); 51 | 52 | /**@}*/ 53 | #endif /* _sbn_client_ingest_h_ */ -------------------------------------------------------------------------------- /fsw/src/sbn_client_init.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include 14 | 15 | #include "sbn_client.h" 16 | #include "sbn_client_minders.h" 17 | #include "sbn_client_utils.h" 18 | 19 | 20 | extern int sbn_client_sockfd; 21 | extern int sbn_client_cpuId; 22 | 23 | pthread_t receive_thread_id; 24 | pthread_t heart_thread_id; 25 | 26 | 27 | int32 SBN_Client_Init(void) 28 | { 29 | int32 status = SBN_CLIENT_NO_STATUS_SET; 30 | int heart_thread_status = 0; 31 | int receive_thread_status = 0; 32 | 33 | log_message("SBN_Client Connecting to %s, %d\n", SBN_CLIENT_IP_ADDR, SBN_CLIENT_PORT); 34 | 35 | sbn_client_sockfd = connect_to_server(SBN_CLIENT_IP_ADDR, SBN_CLIENT_PORT); 36 | sbn_client_cpuId = 2; /* TODO: hardcoded, but should be set by cFS SBN ??*/ 37 | 38 | if (sbn_client_sockfd < 0) 39 | { 40 | log_message( 41 | "SBN_CLIENT: ERROR Failed to get sbn_client_sockfd, cannot continue."); 42 | status = SBN_CLIENT_BAD_SOCK_FD_EID; 43 | } 44 | else 45 | { 46 | CFE_SBN_Client_InitPipeTbl(); 47 | 48 | /* heartbeat thread establishes live connection */ 49 | heart_thread_status = pthread_create(&heart_thread_id, NULL, 50 | SBN_Client_HeartbeatMinder, NULL); 51 | 52 | status = check_pthread_create_status(heart_thread_status, 53 | SBN_CLIENT_HEART_THREAD_CREATE_EID); 54 | 55 | /* receive thread monitors for messages */ 56 | if (status == SBN_CLIENT_SUCCESS) 57 | { 58 | receive_thread_status = pthread_create(&receive_thread_id, NULL, 59 | SBN_Client_ReceiveMinder, NULL); 60 | 61 | status = check_pthread_create_status(receive_thread_status, 62 | SBN_CLIENT_RECEIVE_THREAD_CREATE_EID); 63 | }/* end if */ 64 | 65 | }/* end if */ 66 | 67 | if (status != SBN_CLIENT_SUCCESS) 68 | { 69 | log_message("SBN_Client_Init error %d\n", status); 70 | }/* end if */ 71 | 72 | return status; 73 | }/* end SBN_Client_Init */ -------------------------------------------------------------------------------- /fsw/src/sbn_client_logger.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include "sbn_client_logger.h" 14 | 15 | int32 log_message(const char * format, ...) 16 | { 17 | int32 num_char_written; 18 | va_list vl; 19 | char error_message[MAX_LOG_MESSAGE_SIZE]; 20 | 21 | va_start(vl, format); 22 | 23 | num_char_written = vsnprintf(error_message, MAX_LOG_MESSAGE_SIZE, format, vl); 24 | 25 | va_end(vl); 26 | 27 | /* TODO: puts should be changed to put messages into a file or send event in 28 | ** order to reduce spamming when multiple errors are encountered */ 29 | puts(error_message); 30 | 31 | return num_char_written; 32 | } -------------------------------------------------------------------------------- /fsw/src/sbn_client_logger.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #ifndef _sbn_client_logger_h_ 14 | #define _sbn_client_logger_h_ 15 | 16 | #include 17 | #include 18 | 19 | /* common_types.h are cFE defined types */ 20 | #include "common_types.h" 21 | 22 | 23 | 24 | #define MAX_LOG_MESSAGE_SIZE 80 25 | 26 | /****************************************************************************** 27 | ** File: sbn_client_logger.h 28 | ** 29 | ** Purpose: 30 | ** This header file contains the definition of the cFS sbn_client app's 31 | ** logging functions. The log function is called for important events 32 | ** (i.e. error output). Currently it outputs the message, but this can 33 | ** (and should!) be updated to put them in a file or something else to 34 | ** reduce output when lots of errors happen quickly. 35 | ** 36 | ** Author: A.Gibson/587 37 | ** 38 | ******************************************************************************/ 39 | /****************** Function Prototypes **********************/ 40 | 41 | /** @defgroup SBNCLIENTLogger sbn_client logger 42 | * @{ 43 | */ 44 | 45 | /*****************************************************************************/ 46 | /** 47 | ** \brief Initialized the client by connecting to SBN. 48 | ** 49 | ** \par Description 50 | ** This function takes a variable argument stream to create a message 51 | ** for output. Commonly used for important events that a user needs 52 | ** to be informed about 53 | ** 54 | ** \par Assumptions, External Events, and Notes: 55 | ** Needs updated to put messages somewhere like a file, or 56 | ** alternatively have a level of output (DEBUG, INFO, ERROR) to select 57 | ** when a message should be displayed. 58 | ** 59 | ** 60 | ** \return Number of characters successfully written to the message 61 | ** 62 | */ 63 | int32 log_message(const char * format, ...); 64 | /**@}*/ 65 | 66 | #endif /* _sbn_client_init_h_ */ -------------------------------------------------------------------------------- /fsw/src/sbn_client_minders.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include 14 | 15 | #include "sbn_client.h" 16 | #include "sbn_client_minders.h" 17 | #include "sbn_client_utils.h" 18 | 19 | #define SECONDS_BETWEEN_HEARTBEATS 3 20 | 21 | extern int sbn_client_sockfd; 22 | 23 | boolean continue_heartbeat = TRUE; 24 | boolean continue_receive_check = TRUE; 25 | 26 | 27 | void *SBN_Client_HeartbeatMinder(void *vargp) 28 | { 29 | while(continue_heartbeat) /* TODO: check run state? */ 30 | { 31 | 32 | if (sbn_client_sockfd != 0) 33 | { 34 | send_heartbeat(sbn_client_sockfd); 35 | } /* end if */ 36 | 37 | sleep(SECONDS_BETWEEN_HEARTBEATS); 38 | } /* end while */ 39 | 40 | return NULL; 41 | } /* end SBN_Client_HeartbeatMinder */ 42 | 43 | 44 | void *SBN_Client_ReceiveMinder(void *vargp) 45 | { 46 | int32 status; 47 | int32 consec_error_count = 0; 48 | 49 | while(continue_receive_check) /* TODO: check run state? */ 50 | { 51 | status = recv_msg(sbn_client_sockfd); /* TODO: pass message pointer? */ 52 | /* On heartbeats, need to update known liveness state of SBN 53 | ** On other messages, need to make available for next CFE_SB_RcvMsg call */ 54 | 55 | if (status != CFE_SUCCESS) 56 | { 57 | log_message("Receive message returned error 0x%08X\n", status); 58 | consec_error_count++; 59 | } 60 | else 61 | { 62 | consec_error_count = 0; 63 | } /* end if */ 64 | 65 | if (5 == consec_error_count) { 66 | continue_heartbeat = FALSE; 67 | continue_receive_check = FALSE; 68 | } 69 | 70 | } /* end while */ 71 | 72 | return NULL; 73 | } /* end SBN_Client_ReceiveMinder */ -------------------------------------------------------------------------------- /fsw/src/sbn_client_minders.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #ifndef _sbn_client_minders_h_ 14 | #define _sbn_client_minders_h_ 15 | 16 | void *SBN_Client_HeartbeatMinder(void *); 17 | void *SBN_Client_ReceiveMinder(void *); 18 | 19 | #endif /* _sbn_client_minders_h_ */ -------------------------------------------------------------------------------- /fsw/src/sbn_client_utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "sbn_client_utils.h" 18 | 19 | extern CFE_SBN_Client_PipeD_t PipeTbl[CFE_PLATFORM_SBN_CLIENT_MAX_PIPES]; 20 | 21 | struct sockaddr_in server_address; 22 | 23 | 24 | int32 check_pthread_create_status(int status, int32 errorId) 25 | { 26 | int32 thread_status; 27 | 28 | if (status == 0) 29 | { 30 | thread_status = SBN_CLIENT_SUCCESS; 31 | } 32 | else 33 | { 34 | switch(status) 35 | { 36 | case EAGAIN: 37 | log_message("Create thread error = EAGAIN"); 38 | break; 39 | 40 | case EINVAL: 41 | log_message("Create thread error = EINVAL"); 42 | break; 43 | 44 | case EPERM: 45 | log_message("Create thread error = EPERM"); 46 | break; 47 | 48 | default: 49 | printf("Unknown thread creation error = %d\n", status); 50 | } 51 | 52 | perror("pthread_create error"); 53 | 54 | thread_status = errorId; 55 | }/* end if */ 56 | 57 | return thread_status; 58 | } 59 | 60 | /* message_entry_point determines which slot a new message enters the pipe. 61 | * the mod allows it to go around the bend easily, i.e. 2 + 4 % 5 = 1, 62 | * slots 2,3,4,0 are taken so 1 is entry */ 63 | int message_entry_point(CFE_SBN_Client_PipeD_t pipe) 64 | { 65 | return (pipe.ReadMessage + pipe.NumberOfMessages) % 66 | CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH; 67 | } 68 | 69 | int CFE_SBN_CLIENT_ReadBytes(int sockfd, unsigned char *msg_buffer, 70 | size_t MsgSz) 71 | { 72 | int bytes_received = 0; 73 | int total_bytes_recd = 0; 74 | 75 | /* TODO:Some kind of timeout on this? */ 76 | while (total_bytes_recd != MsgSz) 77 | { 78 | bytes_received = read(sockfd, msg_buffer + total_bytes_recd, 79 | MsgSz - total_bytes_recd); 80 | 81 | if (bytes_received < 0) 82 | { 83 | /* TODO:ERROR socket is dead somehow */ 84 | log_message("SBN_CLIENT: ERROR CFE_SBN_CLIENT_PIPE_BROKEN_ERR\n"); 85 | return CFE_SBN_CLIENT_PIPE_BROKEN_ERR; 86 | } 87 | else if (bytes_received == 0) 88 | { 89 | /* TODO:ERROR closed remotely */ 90 | log_message("SBN_CLIENT: ERROR CFE_SBN_CLIENT_PIPE_CLOSED_ERR: %s\n", strerror(errno)); 91 | return CFE_SBN_CLIENT_PIPE_CLOSED_ERR; 92 | } 93 | 94 | total_bytes_recd += bytes_received; 95 | } 96 | // 97 | // log_message("CFE_SBN_CLIENT_ReadBytes THIS MESSAGE:"); 98 | // int i =0; 99 | // for (i = 0; i < MsgSz; i++) 100 | // { 101 | // printf("0x%02X ", msg_buffer[i]); 102 | // } 103 | // printf("\n"); 104 | 105 | return CFE_SUCCESS; 106 | } 107 | 108 | void invalidate_pipe(CFE_SBN_Client_PipeD_t *pipe) 109 | { 110 | int i; 111 | 112 | pipe->InUse = CFE_SBN_CLIENT_NOT_IN_USE; 113 | pipe->SysQueueId = CFE_SBN_CLIENT_UNUSED_QUEUE; 114 | pipe->PipeId = CFE_SBN_CLIENT_INVALID_PIPE; 115 | /* SB always holds one message so Number of messages should always be a minimum of 1 */ 116 | pipe->NumberOfMessages = 1; 117 | /* Message to be read will be incremented after receive is called */ 118 | /* Therefore initial next message is the last in the chain */ 119 | pipe->ReadMessage = CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH - 1; 120 | memset(&pipe->PipeName[0],0,OS_MAX_API_NAME); 121 | 122 | for(i = 0; i < CFE_SBN_CLIENT_MAX_MSG_IDS_PER_PIPE; i++) 123 | { 124 | pipe->SubscribedMsgIds[i] = CFE_SBN_CLIENT_INVALID_MSG_ID; 125 | } 126 | 127 | 128 | } 129 | 130 | size_t write_message(int sockfd, char *buffer, size_t size) 131 | { 132 | size_t result; 133 | 134 | result = write(sockfd, buffer, size); 135 | 136 | return result; 137 | } 138 | 139 | uint8 CFE_SBN_Client_GetPipeIdx(CFE_SB_PipeId_t PipeId) 140 | { 141 | /* Quick check because PipeId should match PipeIdx */ 142 | if (PipeTbl[PipeId].PipeId == PipeId && PipeTbl[PipeId].InUse == CFE_SBN_CLIENT_IN_USE) 143 | { 144 | return PipeId; 145 | } 146 | else 147 | { 148 | int i; 149 | 150 | for(i=0;iHdr); 188 | #else 189 | 190 | uint32 SubSystemId; 191 | 192 | MsgId = CCSDS_RD_APID(MsgPtr->Hdr); /* Primary header APID */ 193 | 194 | if ( CCSDS_RD_TYPE(MsgPtr->Hdr) == CCSDS_CMD) 195 | MsgId = MsgId | CFE_SB_CMD_MESSAGE_TYPE; 196 | 197 | /* Add in the SubSystem ID as needed */ 198 | SubSystemId = CCSDS_RD_SUBSYSTEM_ID(MsgPtr->SpacePacket.ApidQ); 199 | MsgId = (MsgId | (SubSystemId << 8)); 200 | #endif 201 | 202 | return MsgId; 203 | 204 | }/* end CFE_SBN_Client_GetMsgId */ 205 | 206 | // TODO: return value? 207 | int send_heartbeat(int sockfd) 208 | { 209 | int retval; 210 | char sbn_header[SBN_PACKED_HDR_SZ] = {0}; 211 | 212 | Pack_t Pack; 213 | Pack_Init(&Pack, sbn_header, 0 + SBN_PACKED_HDR_SZ, 0); 214 | 215 | Pack_UInt16(&Pack, 0); 216 | Pack_UInt8(&Pack, SBN_HEARTBEAT_MSG); 217 | Pack_UInt32(&Pack, 2); 218 | 219 | retval = write(sockfd, sbn_header, sizeof(sbn_header)); 220 | 221 | return retval; 222 | } 223 | 224 | uint16 CFE_SBN_Client_GetTotalMsgLength(CFE_SB_MsgPtr_t MsgPtr) 225 | { 226 | return CCSDS_RD_LEN(MsgPtr->Hdr); 227 | }/* end CFE_SBN_Client_GetTotalMsgLength */ 228 | 229 | int connect_to_server(const char *server_ip, uint16_t server_port) 230 | { 231 | int sockfd, address_converted, connection; 232 | 233 | sleep(5); 234 | 235 | /* Create an ipv4 TCP socket */ 236 | sockfd = socket(AF_INET, SOCK_STREAM, CFE_SBN_CLIENT_NO_PROTOCOL); 237 | 238 | /* Socket error */ 239 | if (sockfd < 0) 240 | { 241 | switch(errno) 242 | { 243 | case EACCES: 244 | case EAFNOSUPPORT: 245 | case EINVAL: 246 | case EMFILE: 247 | case ENOBUFS: 248 | case ENOMEM: 249 | case EPROTONOSUPPORT: 250 | log_message("Socket err = %s", strerror(errno)); 251 | break; 252 | 253 | default: 254 | log_message("Unknown socket error = %s", strerror(errno)); 255 | } 256 | 257 | return SERVER_SOCKET_ERROR; 258 | } 259 | 260 | memset(&server_address, '0', sizeof(server_address)); 261 | 262 | server_address.sin_family = AF_INET; 263 | server_address.sin_port = htons(server_port); 264 | 265 | address_converted = inet_pton(AF_INET, server_ip, &server_address.sin_addr); 266 | 267 | /* inet_pton can have two separate errors, a value of 1 is success. */ 268 | if (address_converted == 0) 269 | { 270 | perror("connect_to_server inet_pton 0 error"); 271 | return SERVER_INET_PTON_SRC_ERROR; 272 | } 273 | 274 | if (address_converted == -1) 275 | { 276 | perror("connect_to_server inet_pton -1 error"); 277 | return SERVER_INET_PTON_INVALID_AF_ERROR; 278 | } 279 | 280 | connection = connect(sockfd, (struct sockaddr *)&server_address, 281 | sizeof(server_address)); 282 | 283 | /* Connect error */ 284 | if (connection < 0) 285 | { 286 | switch(errno) 287 | { 288 | case EACCES: 289 | case EPERM: 290 | case EADDRINUSE: 291 | case EADDRNOTAVAIL: 292 | case EAFNOSUPPORT: 293 | case EAGAIN: 294 | case EALREADY: 295 | case EBADF: 296 | case ECONNREFUSED: 297 | case EFAULT: 298 | case EINPROGRESS: 299 | case EINTR: 300 | case EISCONN: 301 | case ENETUNREACH: 302 | case ENOTSOCK: 303 | case EPROTOTYPE: 304 | case ETIMEDOUT: 305 | log_message("connect err = %s", strerror(errno)); 306 | break; 307 | 308 | default: 309 | log_message("Unknown connect error = %s", strerror(errno)); 310 | } 311 | 312 | log_message("SERVER_CONNECT_ERROR: Connect failed error: %d\n", connection); 313 | return SERVER_CONNECT_ERROR; 314 | } 315 | 316 | return sockfd; 317 | } 318 | -------------------------------------------------------------------------------- /fsw/src/sbn_client_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #ifndef _sbn_client_utils_h_ 14 | #define _sbn_client_utils_h_ 15 | 16 | #include 17 | #include 18 | 19 | #include "sbn_pack.h" 20 | #include "sbn_client.h" 21 | #include "sbn_client_logger.h" 22 | #include "sbn_client_defs.h" 23 | 24 | /************************************************************************ 25 | ** Type Definitions 26 | *************************************************************************/ 27 | 28 | /****************************************************************************** 29 | ** Typedef: CFE_SB_BufferD_t 30 | ** 31 | ** Purpose: 32 | ** This structure defines a BUFFER DESCRIPTOR used to specify the MsgId 33 | ** and address of each packet buffer. 34 | ** 35 | ** Note: Changing the size of this structure may require the memory pool 36 | ** block sizes to change. 37 | */ 38 | typedef struct { 39 | CFE_SB_MsgId_t MsgId; 40 | uint16 UseCount; 41 | uint32 Size; 42 | void* Buffer; 43 | CFE_SB_SenderId_t Sender; 44 | } CFE_SBN_Client_BufferD_t; 45 | 46 | /* TODO: Doxygen comments */ 47 | typedef struct { 48 | uint8 InUse; 49 | CFE_SB_PipeId_t PipeId; 50 | char PipeName[OS_MAX_API_NAME]; 51 | char AppName[OS_MAX_API_NAME]; 52 | uint8 Opts; 53 | uint8 Spare; 54 | uint32 AppId; 55 | uint32 SysQueueId; 56 | uint32 LastSender; 57 | uint16 QueueDepth; 58 | uint16 SendErrors; 59 | uint32 NumberOfMessages; 60 | uint32 ReadMessage; 61 | unsigned char Messages[CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH][CFE_SBN_CLIENT_MAX_MESSAGE_SIZE]; 62 | CFE_SB_MsgId_t SubscribedMsgIds[CFE_SBN_CLIENT_MAX_MSG_IDS_PER_PIPE]; 63 | } CFE_SBN_Client_PipeD_t; 64 | 65 | /* SBN header TODO: Header is hardcoded here; what is a better way to bring this in from SB? */ 66 | typedef struct 67 | { 68 | uint16 SBN_MsgSz; 69 | uint8 SBN_MsgType; 70 | uint32 SBN_ProcessorID; 71 | } SBN_Hdr_t; 72 | 73 | /* TODO: Doxygen comments */ 74 | typedef struct { 75 | int msgId; 76 | int pipeIds[CFE_PLATFORM_SBN_CLIENT_MAX_PIPES]; 77 | } MsgId_to_pipes_t; 78 | 79 | 80 | 81 | int32 check_pthread_create_status(int, int32); 82 | int message_entry_point(CFE_SBN_Client_PipeD_t); 83 | int CFE_SBN_CLIENT_ReadBytes(int, unsigned char *, size_t); 84 | void invalidate_pipe(CFE_SBN_Client_PipeD_t *); 85 | size_t write_message(int, char *, size_t); 86 | uint8 CFE_SBN_Client_GetPipeIdx(CFE_SB_PipeId_t); 87 | uint8 CFE_SBN_Client_GetMessageSubscribeIndex(CFE_SB_PipeId_t); 88 | CFE_SB_MsgId_t CFE_SBN_Client_GetMsgId(CFE_SB_MsgPtr_t); 89 | int send_heartbeat(int); 90 | uint16 CFE_SBN_Client_GetTotalMsgLength(CFE_SB_MsgPtr_t); 91 | int connect_to_server(const char *, uint16_t); 92 | 93 | #endif /* _sbn_client_utils_h_ */ 94 | 95 | -------------------------------------------------------------------------------- /fsw/src/sbn_client_version.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #ifndef _sbn_client_version_h_ 14 | #define _sbn_client_version_h_ 15 | 16 | #define SBN_CLIENT_MAJOR_VERSION 1 17 | #define SBN_CLIENT_MINOR_VERSION 0 18 | #define SBN_CLIENT_REVISION 0 19 | #define SBN_CLIENT_MISSION_REV 0 20 | 21 | #endif /* _sbn_client_version_h_ */ 22 | 23 | /************************/ 24 | /* End of File Comment */ 25 | /************************/ 26 | -------------------------------------------------------------------------------- /fsw/src/sbn_client_wrappers.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "sbn_client.h" 19 | #include "sbn_client_utils.h" 20 | #include "sbn_client_wrappers.h" 21 | 22 | extern CFE_SBN_Client_PipeD_t PipeTbl[CFE_PLATFORM_SBN_CLIENT_MAX_PIPES]; 23 | extern int sbn_client_sockfd; 24 | extern int sbn_client_cpuId; 25 | extern pthread_mutex_t receive_mutex; 26 | extern pthread_cond_t received_condition; 27 | 28 | int32 __wrap_CFE_SB_CreatePipe(CFE_SB_PipeId_t *PipeIdPtr, uint16 Depth, const char *PipeName) 29 | { 30 | uint8 i; 31 | int32 status = CFE_SBN_CLIENT_MAX_PIPES_MET; 32 | 33 | /* TODO:AppId is static for now */ 34 | 35 | /* TODO:caller name is static for now */ 36 | /* caller name will not require NULL terminator */ 37 | 38 | /* TODO: determine if semaphore is necessary */ 39 | 40 | /* TODO: determine if taskId is necessary */ 41 | 42 | /* sets user's pipe id value to 'invalid' for error cases */ 43 | if(PipeIdPtr != NULL) 44 | { 45 | *PipeIdPtr = CFE_SBN_CLIENT_INVALID_PIPE; 46 | }/* end if */ 47 | 48 | /* verify input parameters are valid */ 49 | if((PipeIdPtr == NULL)||(Depth > CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH)||(Depth == 0)) 50 | { 51 | status = CFE_SBN_CLIENT_BAD_ARGUMENT; 52 | } 53 | else 54 | { 55 | 56 | for(i = 0; i CFE_SB_MAX_SB_MSG_SIZE) 202 | { 203 | return CFE_SB_MSG_TOO_BIG; 204 | } 205 | 206 | buffer = malloc(total_size); 207 | 208 | Pack_Init(&Pack, buffer, total_size, 0); 209 | 210 | Pack_UInt16(&Pack, msg_size); 211 | Pack_UInt8(&Pack, SBN_APP_MSG); 212 | Pack_UInt32(&Pack, sbn_client_cpuId); 213 | 214 | memcpy(buffer + SBN_PACKED_HDR_SZ, msg, msg_size); 215 | 216 | write_result = write_message(sbn_client_sockfd, buffer, total_size); 217 | 218 | if (write_result != total_size) 219 | { 220 | // TODO: This isn't an allocation error, but must return an error that CFE_SB_SendMsg would return, is there a better choice here? 221 | return CFE_SB_BUF_ALOC_ERR; 222 | } 223 | 224 | free(buffer); 225 | 226 | return CFE_SUCCESS; 227 | } /* end __wrap_CFE_SB_SendMsg */ 228 | 229 | int32 __wrap_CFE_SB_RcvMsg(CFE_SB_MsgPtr_t *BufPtr, CFE_SB_PipeId_t PipeId, 230 | int32 TimeOut) 231 | { 232 | uint8 pipe_idx; 233 | int32 status = CFE_SUCCESS; 234 | struct timespec enter_time; 235 | 236 | clock_gettime(CLOCK_MONOTONIC, &enter_time); 237 | 238 | if (BufPtr == NULL) 239 | { 240 | log_message("SBN_CLIENT: BUFFER POINTER IS NULL!"); 241 | status = CFE_SB_BAD_ARGUMENT; 242 | } 243 | else if (TimeOut < -1) 244 | { 245 | log_message("SBN_CLIENT: TIMEOUT IS LESS THAN -1!"); 246 | status = CFE_SB_BAD_ARGUMENT; 247 | } 248 | else 249 | { 250 | pipe_idx = CFE_SBN_Client_GetPipeIdx(PipeId); 251 | 252 | if (pipe_idx == CFE_SBN_CLIENT_INVALID_PIPE) 253 | { 254 | log_message("SBN_CLIENT: ERROR INVALID PIPE ERROR!"); 255 | status = CFE_SB_BAD_ARGUMENT; 256 | } 257 | 258 | } /* end if */ 259 | 260 | if (status == CFE_SUCCESS) 261 | { 262 | int lock_mutex_status = 0; 263 | int wait_mutex_status = 0; 264 | int unlock_mutex_status = 0; 265 | CFE_SBN_Client_PipeD_t *pipe = &PipeTbl[pipe_idx]; 266 | 267 | lock_mutex_status = pthread_mutex_lock(&receive_mutex); 268 | 269 | /* Number of messages must be 2 or more otherwise no new messages are 270 | * in the pipe */ 271 | if (pipe->NumberOfMessages < 2 && lock_mutex_status == 0) 272 | { 273 | 274 | if (TimeOut == CFE_SB_POLL) 275 | { 276 | status = CFE_SB_NO_MESSAGE; 277 | } 278 | else if (TimeOut == CFE_SB_PEND_FOREVER) 279 | { 280 | wait_mutex_status = pthread_cond_wait(&received_condition, 281 | &receive_mutex); 282 | } 283 | else /* Timout set to value */ 284 | { 285 | struct timespec future_timeout; 286 | 287 | /* set future time for timeout check to entry time + timeout 288 | * milliseconds */ 289 | future_timeout.tv_sec = enter_time.tv_sec; 290 | future_timeout.tv_nsec = enter_time.tv_nsec + (TimeOut * pow(10, 6)); 291 | 292 | /* when nsec greater than 1 second perform update to seconds and 293 | * nanoseconds */ 294 | if (future_timeout.tv_nsec >= pow(10, 9)) 295 | { 296 | future_timeout.tv_sec += future_timeout.tv_nsec / pow(10, 9); 297 | future_timeout.tv_nsec = future_timeout.tv_nsec % (long) pow(10, 9); 298 | } 299 | 300 | wait_mutex_status = pthread_cond_timedwait(&received_condition, 301 | &receive_mutex, 302 | &future_timeout); 303 | 304 | } /* end if */ 305 | 306 | } /* end if */ 307 | 308 | if (lock_mutex_status == 0) 309 | { 310 | 311 | if (wait_mutex_status != 0) 312 | { 313 | 314 | switch (wait_mutex_status) 315 | { 316 | case ETIMEDOUT: 317 | status = CFE_SB_TIME_OUT; 318 | break; 319 | default: 320 | status = CFE_SB_PIPE_RD_ERR; 321 | } 322 | 323 | } 324 | 325 | if (status == CFE_SUCCESS) 326 | { 327 | /* must progress to next message in pipe because currently 328 | * pointed to message is the last message that was read */ 329 | uint32 next_msg = (pipe->ReadMessage + 1) % 330 | CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH; 331 | pipe->ReadMessage = next_msg; 332 | 333 | *BufPtr = (CFE_SB_MsgPtr_t)(&(pipe->Messages[next_msg])); 334 | 335 | pipe->NumberOfMessages -= 1; 336 | status = CFE_SUCCESS; 337 | } /* end if */ 338 | 339 | unlock_mutex_status = pthread_mutex_unlock(&receive_mutex); 340 | 341 | if (unlock_mutex_status != 0) 342 | { 343 | status = CFE_SB_PIPE_RD_ERR; 344 | } /* end if */ 345 | 346 | } 347 | else 348 | { 349 | status = CFE_SB_PIPE_RD_ERR; 350 | } /* end if */ 351 | 352 | if (status != CFE_SUCCESS) 353 | { 354 | *BufPtr = NULL; 355 | } /* end if */ 356 | 357 | } /* end if */ 358 | 359 | return status; 360 | } /* end __wrap_CFE_SB_RcvMsg */ 361 | 362 | int32 __wrap_CFE_SB_ZeroCopySend(CFE_SB_Msg_t *MsgPtr, 363 | CFE_SB_ZeroCopyHandle_t BufferHandle) 364 | { 365 | printf ("SBN_CLIENT: ERROR CFE_SB_ZeroCopySend not yet implemented\n"); 366 | return -1; 367 | } /* end __wrap_CFE_SB_ZeroCopySend */ 368 | 369 | -------------------------------------------------------------------------------- /unit-test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ################################################################## 2 | # 3 | # Coverage Unit Test build recipe 4 | # 5 | # This CMake file contains the recipe for building the sample unit tests. 6 | # It is invoked from the parent directory when unit tests are enabled. 7 | # 8 | ################################################################## 9 | 10 | # 11 | # 12 | # NOTE on the subdirectory structures here: 13 | # 14 | # - "inc" provides local header files shared between the coveragetest, 15 | # wrappers, and overrides source code units 16 | # - "coveragetest" contains source code for the actual unit test cases 17 | # The primary objective is to get line/path coverage on the FSW 18 | # code units. 19 | # - "wrappers" contains wrappers for the FSW code. The wrapper adds 20 | # any UT-specific scaffolding to facilitate the coverage test, and 21 | # includes the unmodified FSW source file. 22 | # 23 | 24 | set(UT_NAME sbn_client) # UT_NAME is used in severl locations later in this file 25 | 26 | # Use the UT assert public API, and allow direct 27 | # inclusion of source files that are normally private 28 | include_directories(${osal_MISSION_DIR}/ut_assert/inc) #osal_MISSION_DIR = ${MISSION_SOURCE_DIR}/osal, UT source files for ut_assert 29 | include_directories(${PROJECT_SOURCE_DIR}/fsw/src) # PROJECT_SOURCE_DIR is set by the last call to project() command, sample_app? 30 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc) # CMAKE_CURRENT_SOURCE_DIR Path to the current source directory being processed, sample_app/unit_test? 31 | include_directories(${PROJECT_SOURCE_DIR}/unit-test/helpers) 32 | include_directories(${PROJECT_SOURCE_DIR}/unit-test/stubs) 33 | include_directories(${PROJECT_SOURCE_DIR}/unit-test) 34 | 35 | # Setting wrappers for how things are done currently. 36 | set(WRAPS -Wl) 37 | set(WRAPS "${WRAPS},-wrap,CFE_SB_CreatePipe") 38 | set(WRAPS "${WRAPS},-wrap,CFE_SB_DeletePipe") 39 | set(WRAPS "${WRAPS},-wrap,CFE_SB_Subscribe") 40 | set(WRAPS "${WRAPS},-wrap,CFE_SB_SubscribeEx") 41 | set(WRAPS "${WRAPS},-wrap,CFE_SB_SubscribeLocal") 42 | set(WRAPS "${WRAPS},-wrap,CFE_SB_Unsubscribe") 43 | set(WRAPS "${WRAPS},-wrap,CFE_SB_UnsubscribeLocal") 44 | set(WRAPS "${WRAPS},-wrap,CFE_SB_SendMsg") 45 | set(WRAPS "${WRAPS},-wrap,CFE_SB_RcvMsg") 46 | set(WRAPS "${WRAPS},-wrap,CFE_SB_ZeroCopySend") 47 | set(WRAPS "${WRAPS},-wrap,CFE_SB_CreatePipe") 48 | set(WRAPS "${WRAPS},-wrap,CFE_SB_Subscribe") 49 | set(WRAPS "${WRAPS},-wrap,CFE_SB_RcvMsg") 50 | set(WRAPS "${WRAPS},-wrap,socket") 51 | set(WRAPS "${WRAPS},-wrap,htons") 52 | set(WRAPS "${WRAPS},-wrap,inet_pton") 53 | set(WRAPS "${WRAPS},-wrap,connect") 54 | set(WRAPS "${WRAPS},-wrap,read") 55 | set(WRAPS "${WRAPS},-wrap,sleep") 56 | set(WRAPS "${WRAPS},-wrap,perror") 57 | set(WRAPS "${WRAPS},-wrap,pthread_create") 58 | set(WRAPS "${WRAPS},-wrap,connect_to_server") 59 | set(WRAPS "${WRAPS},-wrap,CFE_SBN_Client_InitPipeTbl") 60 | set(WRAPS "${WRAPS},-wrap,check_pthread_create_status") 61 | set(WRAPS "${WRAPS},-wrap,send_heartbeat") 62 | set(WRAPS "${WRAPS},-wrap,recv_msg") 63 | set(WRAPS "${WRAPS},-wrap,CFE_SBN_CLIENT_ReadBytes") 64 | set(WRAPS "${WRAPS},-wrap,pthread_mutex_lock") 65 | set(WRAPS "${WRAPS},-wrap,pthread_mutex_unlock") 66 | set(WRAPS "${WRAPS},-wrap,pthread_cond_signal") 67 | set(WRAPS "${WRAPS},-wrap,CFE_SBN_Client_GetMsgId") 68 | set(WRAPS "${WRAPS},-wrap,CFE_SBN_Client_GetPipeIdx") 69 | set(WRAPS "${WRAPS},-wrap,pthread_cond_timedwait") 70 | set(WRAPS "${WRAPS},-wrap,pthread_cond_wait") 71 | 72 | 73 | # Get the files in the source subdirectory 74 | set(source_files) 75 | aux_source_directory("${PROJECT_SOURCE_DIR}/fsw/src" source_files) 76 | 77 | set(source_file_names) 78 | foreach(SOURCE_FILE ${source_files}) 79 | get_filename_component(SOURCE_NAME "${SOURCE_FILE}" NAME_WE) 80 | add_library("${SOURCE_NAME}_object" OBJECT "${SOURCE_FILE}") 81 | list(APPEND source_file_names "${SOURCE_NAME}_object") 82 | endforeach() 83 | 84 | 85 | add_library("logger_stub" OBJECT "${PROJECT_SOURCE_DIR}/unit-test/stubs/sbn_client_logger_stubs.c") 86 | 87 | 88 | # Get the files in the applications unit-test directory 89 | set(app_ut_helper_files) 90 | aux_source_directory("${PROJECT_SOURCE_DIR}/unit-test/helpers" app_ut_helper_files) 91 | # Have a variable hold the helper library names so they can be referenced later 92 | set(app_ut_helper_names) 93 | # Build all the test helpers and save the object names 94 | 95 | foreach(HELPER_FILE ${app_ut_helper_files}) 96 | get_filename_component(HELPER_NAME "${HELPER_FILE}" NAME_WE) 97 | add_library("${HELPER_NAME}_object" OBJECT "${HELPER_FILE}") 98 | list(APPEND app_ut_helper_names "${HELPER_NAME}_object") 99 | endforeach() 100 | 101 | # Generate a dedicated "testrunner" executable that executes the tests for each FSW code unit 102 | # Cycle through all the app's source files, there will be a test file for each 103 | foreach(SRCFILE ${source_files}) 104 | # Get the base sourcfile name as a module name without path or the extension, 105 | # this will be used as the base name of the unit test file. 106 | get_filename_component(MODULENAME "${SRCFILE}" NAME_WE) 107 | 108 | set(source_file_names_copy ${source_file_names}) 109 | 110 | set(stub_names) 111 | if(NOT MODULENAME MATCHES "sbn_client_logger") 112 | # aux_source_directory("${PROJECT_SOURCE_DIR}/unit-test/stubs" stub_dir) 113 | set(stub_names "logger_stub") 114 | remove(source_file_names_copy "sbn_client_logger_object") 115 | endif() 116 | 117 | remove(source_file_names_copy "${MODULENAME}_object") 118 | 119 | # Use the module name to find the testname, adding _tests to the end 120 | set(TESTNAME "${MODULENAME}_tests") 121 | 122 | # Make the testcase sourcefile name with path and extension 123 | set(TESTCASE_SOURCE_FILE "${PROJECT_SOURCE_DIR}/unit-test/${TESTNAME}.c") 124 | 125 | set(TEST_SOURCE_OBJECT "ut_${TESTNAME}_object") 126 | 127 | # Compile the source unit under test as an OBJECT 128 | add_library(${TEST_SOURCE_OBJECT} OBJECT 129 | ${SRCFILE} 130 | ) 131 | 132 | # Apply the UT_C_FLAGS to the units under test 133 | # This should enable coverage analysis on platforms that support this 134 | set_target_properties(${TEST_SOURCE_OBJECT} PROPERTIES 135 | COMPILE_FLAGS "${UT_C_FLAGS}") 136 | 137 | # Compile a test runner application, which contains the 138 | # actual coverage test code (test cases) and the unit under test 139 | # creates sample_app-sample_app-testrunner from coveragetest/coveragetest_sample_app.c 140 | add_executable(${TESTNAME}-testrunner 141 | ${TESTCASE_SOURCE_FILE} 142 | $ 143 | ) 144 | 145 | # This also needs to be linked with WRAPS (for stubbing) and UT_C_FLAGS (for coverage) 146 | set_target_properties(${TESTNAME}-testrunner PROPERTIES 147 | LINK_FLAGS "${WRAPS} ${UT_C_FLAGS}") 148 | 149 | # This is also linked with any other stub libraries needed, 150 | # as well as the UT assert framework 151 | # sbn_client needs referenced here, not sure how to remove it, maybe when there's stubs for sbn_client files? 152 | target_link_libraries(${TESTNAME}-testrunner 153 | ${source_file_names_copy} 154 | ${app_ut_helper_names} 155 | ${stub_names} 156 | ut_cfe-core_stubs 157 | ut_assert 158 | ) 159 | 160 | # Add it to the set of tests to run as part of "make test" 161 | add_test(${TESTNAME} ${TESTNAME}-testrunner) 162 | 163 | endforeach() 164 | 165 | -------------------------------------------------------------------------------- /unit-test/helpers/sbn_client_common_test_utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include "sbn_client_tests_includes.h" 14 | 15 | /* 16 | * Globals 17 | */ 18 | 19 | char error_message[MAX_ERROR_MESSAGE_SIZE]; 20 | unsigned char message[CFE_SBN_CLIENT_MAX_MESSAGE_SIZE]; 21 | 22 | const char *log_message_expected_string = ""; 23 | boolean log_message_was_called = FALSE; 24 | void (*wrap_log_message_call_func)(void) = NULL; 25 | /* 26 | * Functions 27 | */ 28 | 29 | char *TestResultMsg(const char *format, ...) 30 | { 31 | va_list vl; 32 | va_start(vl, format); 33 | 34 | vsnprintf(error_message, MAX_ERROR_MESSAGE_SIZE, format, vl); 35 | 36 | va_end(vl); 37 | 38 | return error_message; 39 | } 40 | 41 | int Any_Negative_int(void) 42 | { 43 | int random_val = (rand() % INT_MAX) + 1; 44 | 45 | return random_val * -1; 46 | } 47 | 48 | int32 Any_Negative_int32_Except(int exception) 49 | { 50 | int32 random_val = exception; 51 | 52 | while (random_val == exception) 53 | { 54 | random_val = Any_Negative_int(); 55 | } 56 | 57 | return random_val; 58 | } 59 | 60 | int Any_Positive_int_Or_Zero(void) 61 | { 62 | int random_val = rand(); 63 | 64 | return random_val; 65 | } 66 | 67 | int32 Any_Positive_int32(void) 68 | { 69 | int32 random_val = (rand() % INT_MAX) + 1; 70 | 71 | return random_val; 72 | } 73 | 74 | int Any_Non_Zero_int(void) 75 | { 76 | return Any_int_Except(0); 77 | } 78 | 79 | int Any_int(void) 80 | { 81 | int random_val = Any_Positive_int_Or_Zero(); 82 | 83 | int coin_toss = rand() % 2; 84 | 85 | if (coin_toss == 1) 86 | { 87 | /* 0 to INT_MAX becomes -1 to INT_MIN */ 88 | random_val *= -1; /* flip sign */ 89 | random_val += -1; /* subtract 1 */ 90 | } 91 | 92 | return random_val; 93 | } 94 | 95 | int32 Any_int32(void) 96 | { 97 | return Any_int(); 98 | } 99 | 100 | CFE_SB_PipeId_t Any_CFE_SB_PipeId_t(void) 101 | { 102 | CFE_SB_PipeId_t random_val = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; 103 | 104 | return random_val; 105 | } 106 | 107 | 108 | int Any_int_Except(int exception) 109 | { 110 | int random_val = exception; 111 | 112 | while (random_val == exception) 113 | { 114 | random_val = Any_int(); 115 | } 116 | 117 | return random_val; 118 | } 119 | 120 | int32 Any_int32_Except(int32 exception) 121 | { 122 | int32 random_val = exception; 123 | 124 | while (random_val == exception) 125 | { 126 | random_val = Any_Positive_int_Or_Zero(); 127 | 128 | int coin_toss = rand() % 2; 129 | 130 | if (coin_toss == 1) 131 | { 132 | random_val *= -1; 133 | } 134 | 135 | } 136 | 137 | return random_val; 138 | } 139 | 140 | 141 | int32 Any_int32_ExceptThese(int32 * exceptions, size_t length) 142 | { 143 | int32 random_value = 0; 144 | boolean value_is_in_exceptions = TRUE; 145 | 146 | while (value_is_in_exceptions) 147 | { 148 | int index; 149 | 150 | random_value = Any_int(); 151 | 152 | value_is_in_exceptions = FALSE; 153 | 154 | for(index = 0; index < length; index++) 155 | { 156 | 157 | if (exceptions[index] == random_value) 158 | { 159 | value_is_in_exceptions = TRUE; 160 | } 161 | 162 | } 163 | 164 | } 165 | 166 | return random_value; 167 | } 168 | 169 | CFE_SB_MsgId_t Any_Message_Id_Slot(void) 170 | { 171 | return (CFE_SB_MsgId_t)(rand() % CFE_SBN_CLIENT_MAX_MSG_IDS_PER_PIPE); 172 | } 173 | 174 | uint32 Any_Pipe_Message_Location(void) 175 | { 176 | return (uint32)(rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH); 177 | } 178 | 179 | unsigned char Any_unsigned_char(void) 180 | { 181 | unsigned char random_val = rand(); 182 | 183 | return random_val; 184 | } 185 | 186 | unsigned char * Any_Pipe_Message(size_t length) 187 | { 188 | int i; 189 | 190 | for(i = 0; i < length; i++) 191 | { 192 | message[i] = Any_unsigned_char(); 193 | } 194 | 195 | return message; 196 | } 197 | 198 | size_t Any_Message_Size(void) 199 | { 200 | size_t random_val = (rand() % CFE_SBN_CLIENT_MAX_MESSAGE_SIZE - 7) + 8; 201 | 202 | return random_val; 203 | } 204 | 205 | 206 | 207 | void SBN_Client_Setup(void) 208 | { 209 | /* SBN_Client resets */ 210 | sbn_client_sockfd = 0; 211 | sbn_client_cpuId = 0; 212 | 213 | memset(PipeTbl, 0, sizeof(PipeTbl)); 214 | 215 | /* Global UT CFE resets -- 216 | * NOTE: not sure if these are required for sbn_client */ 217 | UT_ResetState(0); 218 | 219 | SBN_CLient_Wrapped_Functions_Setup(); 220 | } /* end SBN_Client_Setup */ 221 | 222 | void SBN_Client_Teardown(void) 223 | { 224 | SBN_CLient_Wrapped_Functions_Teardown(); 225 | } /* end SBN_Client_Teardown */ 226 | 227 | -------------------------------------------------------------------------------- /unit-test/helpers/sbn_client_common_test_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #ifndef _sbn_client_common_test_utils_h_ 14 | #define _sbn_client_common_test_utils_h_ 15 | 16 | #include "sbn_client_tests_includes.h" 17 | 18 | /* 19 | * Defines 20 | */ 21 | 22 | #define MAX_ERROR_MESSAGE_SIZE 120 23 | #define CONNECT_ERROR_VALUE -1 24 | 25 | #define FIRST_CALL 1 26 | #define SECOND_CALL 2 27 | 28 | char *TestResultMsg(const char *, ...); 29 | int Any_Negative_int(void); 30 | int32 Any_Negative_int32_Except(int); 31 | int Any_Positive_int_Or_Zero(void); 32 | int32 Any_Positive_int32(void); 33 | int Any_int_Except(int); 34 | int Any_int(void); 35 | int32 Any_int32(void); 36 | int Any_Non_Zero_int(void); 37 | int32 Any_int32_Except(int32); 38 | int32 Any_int32_ExceptThese(int32 *, size_t); 39 | CFE_SB_PipeId_t Any_CFE_SB_PipeId_t(void); 40 | CFE_SB_MsgId_t Any_Message_Id_Slot(void); 41 | uint32 Any_Pipe_Message_Location(void); 42 | unsigned char Any_unsigned_char(void); 43 | unsigned char * Any_Pipe_Message(size_t length); 44 | size_t Any_Message_Size(void); 45 | 46 | 47 | 48 | void SBN_Client_Setup(void); 49 | void SBN_Client_Teardown(void); 50 | 51 | #endif /* _sbn_client_common_test_utils_h_ */ -------------------------------------------------------------------------------- /unit-test/helpers/sbn_client_wrapped_functions.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include "sbn_client_wrapped_functions.h" 14 | 15 | #define PTHREAD_MUTEX_UNLOCK_SUCCESS 0 16 | #define PTHREAD_MUTEX_UNLOCK_FAILURE EPERM 17 | 18 | 19 | boolean use_wrap_CFE_SBN_CLIENT_ReadBytes = FALSE; 20 | unsigned char *wrap_CFE_SBN_CLIENT_ReadBytes_msg_buffer = NULL; 21 | int wrap_CFE_SBN_CLIENT_ReadBytes_return_value = INT_MIN; 22 | boolean wrap_pthread_mutex_lock_should_be_called = FALSE; 23 | boolean wrap_pthread_mutex_lock_was_called = FALSE; 24 | int wrap_pthread_mutex_lock_return_value = 0; 25 | boolean wrap_pthread_mutex_unlock_should_be_called = FALSE; 26 | boolean wrap_pthread_mutex_unlock_was_called = FALSE; 27 | int wrap_pthread_mutex_unlock_return_value = 0; 28 | boolean wrap_pthread_cond_wait_should_be_called = FALSE; 29 | boolean wrap_pthread_cond_wait_was_called = FALSE; 30 | boolean use_wrap_pthread_cond_wait = FALSE; 31 | int wrap_pthread_cond_wait_return_value = INT_MIN; 32 | boolean wrap_pthread_cond_signal_should_be_called = FALSE; 33 | boolean wrap_pthread_cond_signal_was_called = FALSE; 34 | boolean use_wrap_CFE_SBN_Client_GetMsgId = FALSE; 35 | CFE_SB_MsgId_t wrap_CFE_SBN_Client_GetMsgId_return_value = 0xFFFF; 36 | boolean wrap_pthread_cond_timedwait_should_be_called = FALSE; 37 | boolean use_wrap_pthread_cond_timedwait = FALSE; 38 | boolean wrap_pthread_cond_timedwait_was_called = FALSE; 39 | int wrap_pthread_cond_timedwait_return_value = 0; 40 | boolean use_wrap_CFE_SBN_Client_GetPipeIdx = FALSE; 41 | uint8 wrap_CFE_SBN_Client_GetPipeIdx_return_value = UCHAR_MAX; 42 | boolean use_wrap_connect_to_server = FALSE; 43 | int wrap_connect_to_server_return_value = INT_MIN; 44 | int wrap_exit_expected_status = INT_MIN; 45 | boolean use_wrap_CFE_SBN_Client_InitPipeTbl = FALSE; 46 | int pthread_create_errors_on_call_number = INT_MIN; 47 | uint8 pthread_create_call_number = 0; 48 | int pthread_create_error_value = INT_MIN; 49 | boolean use_wrap_check_pthread_create_status = FALSE; 50 | boolean wrap_check_pthread_create_status_fail_call = FALSE; 51 | uint8 check_pthread_create_status_call_number = 0; 52 | int check_pthread_create_status_errors_on_call_number = INT_MIN; 53 | boolean use_wrap_send_heartbeat = FALSE; 54 | int wrap_send_heartbeat_return_value = SBN_CLIENT_SUCCESS; 55 | uint8 send_hearbeat_call_number = 0; 56 | uint8 send_heartbeat_discontinue_on_call_number = 0; 57 | boolean use_wrap_recv_msg = FALSE; 58 | int wrap_recv_msg_return_value = SBN_CLIENT_SUCCESS; 59 | uint8 recv_msg_call_number = 0; 60 | uint8 recv_msg_discontiue_on_call_number = 0; 61 | const char *perror_expected_string = ""; 62 | int wrap_socket_return_value; 63 | uint16_t wrap_htons_return_value; 64 | int wrap_inet_pton_return_value; 65 | int wrap_connect_return_value; 66 | size_t wrap_read_return_value; 67 | 68 | 69 | /* function pointers */ 70 | void (*wrap_sleep_call_func)(void) = NULL; 71 | 72 | /* Functions called by function pointer */ 73 | void wrap_sleep_set_continue_heartbeat_false(void) 74 | { 75 | continue_heartbeat = FALSE; 76 | } 77 | 78 | 79 | int __wrap_CFE_SBN_CLIENT_ReadBytes(int sockfd, unsigned char *msg_buffer, 80 | size_t MsgSz) 81 | { 82 | int result; 83 | 84 | if (use_wrap_CFE_SBN_CLIENT_ReadBytes) 85 | { 86 | if (wrap_CFE_SBN_CLIENT_ReadBytes_msg_buffer != NULL) 87 | { 88 | memcpy(msg_buffer, wrap_CFE_SBN_CLIENT_ReadBytes_msg_buffer, MsgSz); 89 | } 90 | result = wrap_CFE_SBN_CLIENT_ReadBytes_return_value; 91 | } 92 | else 93 | { 94 | result = __real_CFE_SBN_CLIENT_ReadBytes(sockfd, msg_buffer, MsgSz); 95 | } 96 | 97 | return result; 98 | } 99 | 100 | int __wrap_pthread_mutex_lock(pthread_mutex_t *mutex) 101 | { 102 | wrap_pthread_mutex_lock_was_called = TRUE; 103 | 104 | if (!wrap_pthread_mutex_lock_should_be_called) 105 | { 106 | UtAssert_Failed("pthread_mutex_lock called, but should not have been"); 107 | } 108 | 109 | return wrap_pthread_mutex_lock_return_value; 110 | } 111 | 112 | int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex) 113 | { 114 | wrap_pthread_mutex_unlock_was_called = TRUE; 115 | 116 | if (!wrap_pthread_mutex_unlock_should_be_called) 117 | { 118 | UtAssert_Failed( 119 | "pthread_mutex_unlock called, but should not have been"); 120 | 121 | if (wrap_pthread_mutex_lock_was_called == TRUE) 122 | { 123 | UtAssert_Failed( 124 | "pthread_mutex_unlock called before calling pthread_mutex_lock"); 125 | } 126 | 127 | } 128 | 129 | return wrap_pthread_mutex_unlock_return_value; 130 | } 131 | 132 | int __wrap_pthread_cond_signal(pthread_cond_t *cond) 133 | { 134 | wrap_pthread_cond_signal_was_called = TRUE; 135 | 136 | if (!wrap_pthread_cond_signal_should_be_called) 137 | { 138 | UtAssert_Failed( 139 | "pthread_cond_signal called, but should not have been"); 140 | } 141 | 142 | return 0; 143 | } 144 | 145 | int __wrap_pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex) 146 | { 147 | int result; 148 | 149 | wrap_pthread_cond_wait_was_called = TRUE; 150 | 151 | if (!wrap_pthread_cond_wait_should_be_called) 152 | { 153 | UtAssert_Failed( 154 | "pthread_cond_wait was called, but should not have been"); 155 | } 156 | 157 | if (use_wrap_pthread_cond_wait) 158 | { 159 | result = wrap_pthread_cond_wait_return_value; 160 | } 161 | else 162 | { 163 | result = __real_pthread_cond_wait(cond, mutex); 164 | } 165 | 166 | return result; 167 | } 168 | 169 | int __wrap_pthread_cond_timedwait(pthread_cond_t * cond, 170 | pthread_mutex_t * mutex, const struct timespec * abstime) 171 | { 172 | int result; 173 | 174 | wrap_pthread_cond_timedwait_was_called = TRUE; 175 | 176 | if (!wrap_pthread_cond_timedwait_should_be_called) 177 | { 178 | UtAssert_Failed( 179 | "pthread_cond_timedwait was called, but should not have been"); 180 | } 181 | 182 | if (use_wrap_pthread_cond_timedwait) 183 | { 184 | result = wrap_pthread_cond_timedwait_return_value; 185 | } 186 | else 187 | { 188 | result = __real_pthread_cond_timedwait(cond, mutex, abstime); 189 | } 190 | 191 | return result; 192 | } 193 | 194 | CFE_SB_MsgId_t __wrap_CFE_SBN_Client_GetMsgId(CFE_SB_MsgPtr_t MsgPtr) 195 | { 196 | CFE_SB_MsgId_t result; 197 | 198 | if (use_wrap_CFE_SBN_Client_GetMsgId) 199 | { 200 | result = wrap_CFE_SBN_Client_GetMsgId_return_value; 201 | } 202 | else 203 | { 204 | result = __real_CFE_SBN_Client_GetMsgId(MsgPtr); 205 | } 206 | 207 | return result; 208 | } 209 | 210 | uint8 __wrap_CFE_SBN_Client_GetPipeIdx(CFE_SB_PipeId_t PipeId) 211 | { 212 | if (use_wrap_CFE_SBN_Client_GetPipeIdx) 213 | { 214 | return wrap_CFE_SBN_Client_GetPipeIdx_return_value; 215 | } 216 | else 217 | { 218 | return __real_CFE_SBN_Client_GetPipeIdx(PipeId); 219 | } 220 | } 221 | 222 | int __wrap_connect_to_server(const char *server_ip, uint16_t server_port) 223 | { 224 | int result = INT_MIN; 225 | 226 | if (use_wrap_connect_to_server) 227 | { 228 | result = wrap_connect_to_server_return_value; 229 | } 230 | else 231 | { 232 | result = __real_connect_to_server(server_ip, server_port); 233 | } /* end if */ 234 | 235 | return result; 236 | } 237 | 238 | void __wrap_exit(int status) 239 | { 240 | UtAssert_True(status == wrap_exit_expected_status, 241 | TestResultMsg("exit() status should be %d, and was %d", 242 | wrap_exit_expected_status, status)); 243 | } 244 | 245 | void __wrap_CFE_SBN_Client_InitPipeTbl(void) 246 | { 247 | if (use_wrap_CFE_SBN_Client_InitPipeTbl) 248 | { 249 | ; /* CFE_SBN_Client_InitPipeTbl is a void so do nothing */ 250 | } 251 | else 252 | { 253 | __real_CFE_SBN_Client_InitPipeTbl(); 254 | } 255 | } 256 | 257 | int __wrap_pthread_create(pthread_t *thread, const pthread_attr_t *attr, 258 | void *(*start_routine) (void *), void *arg) 259 | { 260 | pthread_create_call_number += 1; 261 | int result; 262 | 263 | if (pthread_create_errors_on_call_number == pthread_create_call_number) 264 | { 265 | result = pthread_create_error_value; 266 | } 267 | else 268 | { 269 | result = 0; 270 | } 271 | 272 | return result; 273 | } 274 | 275 | int32 __wrap_check_pthread_create_status(int status, int32 errorId) 276 | { 277 | int32 result = INT_MIN; 278 | 279 | check_pthread_create_status_call_number += 1; 280 | 281 | if (use_wrap_check_pthread_create_status) 282 | { 283 | if (wrap_check_pthread_create_status_fail_call && 284 | check_pthread_create_status_call_number == 285 | check_pthread_create_status_errors_on_call_number) 286 | { 287 | UtAssert_True(status == pthread_create_error_value, 288 | "check_pthread_create_status received expected error value " 289 | "returned by pthread_create"); 290 | result = errorId; 291 | } 292 | else 293 | { 294 | result = SBN_CLIENT_SUCCESS; 295 | } 296 | } 297 | else 298 | { 299 | result = __real_check_pthread_create_status(status, errorId); 300 | } 301 | 302 | return result; 303 | }/* NOTE: wrapper will auto discontinue after send_hearbeat_call_number 304 | * rolls over from 255, this is by design so any test using the wrapper cannot 305 | * run in an infinite loop */ 306 | int __wrap_send_heartbeat(int sockfd) 307 | { 308 | int result; 309 | 310 | send_hearbeat_call_number += 1; 311 | 312 | if (use_wrap_send_heartbeat) 313 | { 314 | if (send_hearbeat_call_number == 315 | send_heartbeat_discontinue_on_call_number) 316 | { 317 | continue_heartbeat = FALSE; 318 | } 319 | 320 | return wrap_send_heartbeat_return_value; 321 | } 322 | else 323 | { 324 | result = __real_send_heartbeat(sockfd); 325 | } 326 | 327 | return result; 328 | } 329 | 330 | /* NOTE: wrapper will auto discontinue after recv_msg_call_number 331 | * rolls over from 255, this is by design so any test using the wrapper cannot 332 | * run in an infinite loop */ 333 | int32 __wrap_recv_msg(int sockfd) 334 | { 335 | int32 result; 336 | 337 | recv_msg_call_number += 1; 338 | 339 | if (use_wrap_recv_msg) 340 | { 341 | if (recv_msg_call_number == recv_msg_discontiue_on_call_number) 342 | { 343 | continue_receive_check = FALSE; 344 | } 345 | 346 | return wrap_recv_msg_return_value; 347 | } 348 | else 349 | { 350 | result = __real_recv_msg(sockfd); 351 | } 352 | 353 | return result; 354 | } 355 | 356 | void __wrap_perror(const char *str) 357 | { 358 | if (strlen(perror_expected_string) > 0) 359 | { 360 | UtAssert_StrCmp(str, perror_expected_string, 361 | TestResultMsg("perror expected string '%s' == '%s' string received", 362 | perror_expected_string, str)); 363 | } 364 | 365 | __real_perror(str); 366 | } 367 | 368 | int __wrap_socket(int domain, int type, int protocol) 369 | { 370 | return wrap_socket_return_value; 371 | } 372 | 373 | uint16_t __wrap_htons(uint16_t hostshort) 374 | { 375 | return wrap_htons_return_value; 376 | } 377 | 378 | int __wrap_inet_pton(int af, const char *src, void *dst) 379 | { 380 | return wrap_inet_pton_return_value; 381 | } 382 | 383 | int __wrap_connect(int sbn_client_sockfd, const struct sockaddr *addr, socklen_t addrlen) 384 | { 385 | return wrap_connect_return_value; 386 | } 387 | 388 | size_t __wrap_read(int fd, void* buf, size_t cnt) 389 | { 390 | if (wrap_read_return_value != INT_MIN) 391 | { 392 | return wrap_read_return_value; 393 | } 394 | else 395 | { 396 | return __real_read(fd, buf, cnt); 397 | } 398 | } 399 | 400 | unsigned int __wrap_sleep(unsigned int seconds) 401 | { 402 | if (wrap_sleep_call_func != NULL) 403 | { 404 | (*wrap_sleep_call_func)(); 405 | } 406 | 407 | return 0; 408 | } 409 | 410 | 411 | 412 | 413 | 414 | void SBN_CLient_Wrapped_Functions_Setup(void) 415 | { 416 | ; /* SBN_CLient_Wrapped_Functions_Setup currently does nothing */ 417 | } 418 | 419 | void SBN_CLient_Wrapped_Functions_Teardown(void) 420 | { 421 | /* SBN_CLient_Wrapped_Functions_Teardown resets all variables */ 422 | use_wrap_CFE_SBN_CLIENT_ReadBytes = FALSE; 423 | wrap_CFE_SBN_CLIENT_ReadBytes_msg_buffer = NULL; 424 | wrap_CFE_SBN_CLIENT_ReadBytes_return_value = INT_MIN; 425 | wrap_pthread_mutex_lock_should_be_called = FALSE; 426 | wrap_pthread_mutex_lock_was_called = FALSE; 427 | wrap_pthread_mutex_lock_return_value = 0; 428 | wrap_pthread_mutex_unlock_should_be_called = FALSE; 429 | wrap_pthread_mutex_unlock_was_called = FALSE; 430 | wrap_pthread_mutex_unlock_return_value = 0; 431 | wrap_pthread_cond_wait_should_be_called = FALSE; 432 | wrap_pthread_cond_wait_was_called = FALSE; 433 | use_wrap_pthread_cond_wait = FALSE; 434 | wrap_pthread_cond_wait_return_value = INT_MIN; 435 | wrap_pthread_cond_signal_should_be_called = FALSE; 436 | wrap_pthread_cond_signal_was_called = FALSE; 437 | use_wrap_CFE_SBN_Client_GetMsgId = FALSE; 438 | wrap_CFE_SBN_Client_GetMsgId_return_value = 0xFFFF; 439 | wrap_pthread_cond_timedwait_should_be_called = FALSE; 440 | use_wrap_pthread_cond_timedwait = FALSE; 441 | wrap_pthread_cond_timedwait_was_called = FALSE; 442 | wrap_pthread_cond_timedwait_return_value = 0; 443 | use_wrap_CFE_SBN_Client_GetPipeIdx = FALSE; 444 | wrap_CFE_SBN_Client_GetPipeIdx_return_value = UCHAR_MAX; 445 | use_wrap_connect_to_server = FALSE; 446 | wrap_connect_to_server_return_value = INT_MIN; 447 | wrap_exit_expected_status = INT_MIN; 448 | use_wrap_CFE_SBN_Client_InitPipeTbl = FALSE; 449 | pthread_create_errors_on_call_number = INT_MIN; 450 | pthread_create_call_number = 0; 451 | pthread_create_error_value = INT_MIN; 452 | use_wrap_check_pthread_create_status = FALSE; 453 | wrap_check_pthread_create_status_fail_call = FALSE; 454 | check_pthread_create_status_call_number = 0; 455 | check_pthread_create_status_errors_on_call_number = INT_MIN; 456 | use_wrap_send_heartbeat = FALSE; 457 | wrap_send_heartbeat_return_value = SBN_CLIENT_SUCCESS; 458 | send_hearbeat_call_number = 0; 459 | send_heartbeat_discontinue_on_call_number = 0; 460 | use_wrap_recv_msg = FALSE; 461 | wrap_recv_msg_return_value = SBN_CLIENT_SUCCESS; 462 | recv_msg_call_number = 0; 463 | recv_msg_discontiue_on_call_number = 0; 464 | perror_expected_string = ""; 465 | 466 | 467 | /* function pointers */ 468 | wrap_sleep_call_func = NULL; 469 | 470 | /* external resets */ 471 | continue_heartbeat = TRUE; 472 | continue_receive_check = TRUE; 473 | } 474 | 475 | -------------------------------------------------------------------------------- /unit-test/helpers/sbn_client_wrapped_functions.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #ifndef _sbn_client_wrapped_functions_h_ 14 | #define _sbn_client_wrapped_functions_h_ 15 | 16 | #include "sbn_client_tests_includes.h" 17 | 18 | int __real_CFE_SBN_CLIENT_ReadBytes(int, unsigned char *, size_t); 19 | int __real_pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *); 20 | int __real_pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *, 21 | const struct timespec *); 22 | CFE_SB_MsgId_t __real_CFE_SBN_Client_GetMsgId(CFE_SB_MsgPtr_t); 23 | uint8 __real_CFE_SBN_Client_GetPipeIdx(CFE_SB_PipeId_t); 24 | int __real_connect_to_server(const char *, uint16_t); 25 | void __real_CFE_SBN_Client_InitPipeTbl(void); 26 | int __real_pthread_create(pthread_t *, const pthread_attr_t *, 27 | void *(*) (void *), void *); 28 | int32 __real_check_pthread_create_status(int, int32); 29 | int __real_send_heartbeat(int); 30 | int32 __real_recv_msg(int32); 31 | void __real_perror(const char *s); 32 | size_t __real_read(int fd, void* buf, size_t cnt); 33 | 34 | int __wrap_CFE_SBN_CLIENT_ReadBytes(int, unsigned char *, size_t); 35 | int __wrap_pthread_mutex_lock(pthread_mutex_t *); 36 | int __wrap_pthread_mutex_unlock(pthread_mutex_t *); 37 | int __wrap_pthread_cond_signal(pthread_cond_t *); 38 | int __wrap_pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *); 39 | int __wrap_pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *, 40 | const struct timespec *); 41 | CFE_SB_MsgId_t __wrap_CFE_SBN_Client_GetMsgId(CFE_SB_MsgPtr_t); 42 | uint8 __wrap_CFE_SBN_Client_GetPipeIdx(CFE_SB_PipeId_t); 43 | int __wrap_connect_to_server(const char *, uint16_t); 44 | void __wrap_exit(int); 45 | int __wrap_pthread_create(pthread_t *, const pthread_attr_t *, 46 | void *(*) (void *), void *); 47 | int __wrap_send_heartbeat(int); 48 | int32 __wrap_recv_msg(int32); 49 | void __wrap_perror(const char *s); 50 | int __wrap_socket(int, int, int); 51 | uint16_t __wrap_htons(uint16_t); 52 | int __wrap_inet_pton(int, const char *, void*); 53 | int __wrap_connect(int, const struct sockaddr *, socklen_t); 54 | int __wrap_connect_to_server(const char *, uint16_t); 55 | size_t __wrap_read(int fd, void* buf, size_t cnt); 56 | unsigned int __wrap_sleep(unsigned int seconds); 57 | 58 | /* functions called by function pointer */ 59 | void wrap_sleep_set_continue_heartbeat_false(void); 60 | void wrap_log_message_set_continue_recv_check_false(void); 61 | 62 | extern boolean use_wrap_CFE_SBN_CLIENT_ReadBytes; 63 | extern unsigned char *wrap_CFE_SBN_CLIENT_ReadBytes_msg_buffer; 64 | extern int wrap_CFE_SBN_CLIENT_ReadBytes_return_value; 65 | extern boolean wrap_pthread_mutex_lock_should_be_called; 66 | extern boolean wrap_pthread_mutex_lock_was_called; 67 | extern int wrap_pthread_mutex_lock_return_value; 68 | extern boolean wrap_pthread_mutex_unlock_should_be_called; 69 | extern boolean wrap_pthread_mutex_unlock_was_called; 70 | extern int wrap_pthread_mutex_unlock_return_value; 71 | extern boolean wrap_pthread_cond_signal_should_be_called; 72 | extern boolean wrap_pthread_cond_signal_was_called; 73 | extern boolean wrap_pthread_cond_wait_should_be_called; 74 | extern boolean wrap_pthread_cond_wait_was_called; 75 | extern boolean use_wrap_pthread_cond_wait; 76 | extern int wrap_pthread_cond_wait_return_value; 77 | extern boolean use_wrap_CFE_SBN_Client_GetMsgId; 78 | extern CFE_SB_MsgId_t wrap_CFE_SBN_Client_GetMsgId_return_value; 79 | extern boolean wrap_pthread_cond_timedwait_should_be_called; 80 | extern boolean use_wrap_pthread_cond_timedwait; 81 | extern boolean wrap_pthread_cond_timedwait_was_called; 82 | extern int wrap_pthread_cond_timedwait_return_value; 83 | extern boolean use_wrap_CFE_SBN_Client_GetPipeIdx; 84 | extern uint8 wrap_CFE_SBN_Client_GetPipeIdx_return_value; 85 | extern boolean use_wrap_connect_to_server; 86 | extern int wrap_connect_to_server_return_value; 87 | extern int wrap_exit_expected_status; 88 | extern boolean use_wrap_CFE_SBN_Client_InitPipeTbl; 89 | extern int pthread_create_errors_on_call_number; 90 | extern uint8 pthread_create_call_number; 91 | extern int pthread_create_error_value; 92 | extern boolean use_wrap_check_pthread_create_status; 93 | extern boolean wrap_check_pthread_create_status_fail_call; 94 | extern uint8 check_pthread_create_status_call_number; 95 | extern int check_pthread_create_status_errors_on_call_number; 96 | extern boolean use_wrap_send_heartbeat; 97 | extern int wrap_send_heartbeat_return_value; 98 | extern uint8 send_hearbeat_call_number; 99 | extern uint8 send_heartbeat_discontinue_on_call_number; 100 | extern boolean use_wrap_recv_msg; 101 | extern int wrap_recv_msg_return_value; 102 | extern uint8 recv_msg_call_number; 103 | extern uint8 recv_msg_discontiue_on_call_number; 104 | extern const char *log_message_expected_string; 105 | extern boolean log_message_was_called; 106 | extern const char *perror_expected_string; 107 | extern int wrap_socket_return_value; 108 | extern uint16_t wrap_htons_return_value; 109 | extern int wrap_inet_pton_return_value; 110 | extern int wrap_connect_return_value; 111 | extern size_t wrap_read_return_value; 112 | 113 | /* function pointers */ 114 | 115 | extern void (*wrap_log_message_call_func)(void); 116 | extern void (*wrap_sleep_call_func)(void); 117 | 118 | void SBN_CLient_Wrapped_Functions_Setup(void); 119 | void SBN_CLient_Wrapped_Functions_Teardown(void); 120 | #endif /* _sbn_client_wrapped_functions_h_ */ -------------------------------------------------------------------------------- /unit-test/sbn_client_ingest_tests.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include "sbn_client_tests_includes.h" 14 | 15 | /******************************************************************************* 16 | ** 17 | ** SBN_Client_Ingest_Tests Setup and Teardown 18 | ** 19 | *******************************************************************************/ 20 | 21 | void SBN_Client_Ingest_Setup(void) 22 | { 23 | SBN_Client_Setup(); 24 | } 25 | 26 | void SBN_Client_Ingest_Teardown(void) 27 | { 28 | SBN_Client_Teardown(); 29 | } 30 | 31 | 32 | /******************************************************************************* 33 | ** 34 | ** ingest_app_message Tests 35 | ** 36 | *******************************************************************************/ 37 | 38 | void Test_ingest_app_message_ReadBytesFails(void) 39 | { 40 | /* Arrange */ 41 | char err_msg[60]; 42 | int sockfd = Any_int(); 43 | int msgSize = rand() % CFE_SB_MAX_SB_MSG_SIZE; 44 | 45 | use_wrap_CFE_SBN_CLIENT_ReadBytes = TRUE; 46 | wrap_CFE_SBN_CLIENT_ReadBytes_return_value = Any_int32_Except(CFE_SUCCESS); 47 | 48 | snprintf(err_msg, 60, 49 | "CFE_SBN_CLIENT_ReadBytes returned a bad status = 0x%08X\n", 50 | wrap_CFE_SBN_CLIENT_ReadBytes_return_value); 51 | 52 | log_message_expected_string = err_msg; 53 | 54 | /* Act */ 55 | ingest_app_message(sockfd, msgSize); 56 | 57 | /* Assert */ 58 | UtAssert_True(wrap_pthread_mutex_lock_was_called == FALSE, 59 | "pthread_mutex_lock should not have been called"); 60 | UtAssert_True(wrap_pthread_mutex_unlock_was_called == FALSE, 61 | "pthread_mutex_unlock should not have been called"); 62 | UtAssert_True(wrap_pthread_cond_signal_was_called == FALSE, 63 | "pthread_cond_signal should not have been called"); 64 | } 65 | 66 | void Test_ingest_app_message_FailsWhenNoPipesInUse(void) 67 | { 68 | /* Arrange */ 69 | char err_msg[60] = "SBN_CLIENT: No pipes are in use"; 70 | unsigned char msg[8] = {0x18, 0x81, 0xC0, 0x00, 0x00, 0x01, 0x00, 0x00}; 71 | int msgSize = sizeof(msg); 72 | int sockfd = Any_int(); 73 | 74 | wrap_pthread_mutex_lock_should_be_called = TRUE; 75 | wrap_pthread_mutex_unlock_should_be_called = TRUE; 76 | wrap_pthread_cond_signal_should_be_called = FALSE; 77 | use_wrap_CFE_SBN_Client_GetMsgId = TRUE; 78 | wrap_CFE_SBN_Client_GetMsgId_return_value = msg[0] << 8 | msg[1]; 79 | use_wrap_CFE_SBN_CLIENT_ReadBytes = TRUE; 80 | wrap_CFE_SBN_CLIENT_ReadBytes_return_value = CFE_SUCCESS; 81 | wrap_CFE_SBN_CLIENT_ReadBytes_msg_buffer = msg; 82 | 83 | log_message_expected_string = err_msg; 84 | 85 | /* Act */ 86 | ingest_app_message(sockfd, msgSize); 87 | 88 | /* Assert */ 89 | UtAssert_True(wrap_pthread_mutex_lock_was_called == TRUE, 90 | "pthread_mutex_lock should not have been called"); 91 | UtAssert_True(wrap_pthread_mutex_unlock_was_called == TRUE, 92 | "pthread_mutex_unlock should not have been called"); 93 | UtAssert_True(wrap_pthread_cond_signal_was_called == FALSE, 94 | "pthread_cond_signal should not have been called"); 95 | } 96 | 97 | void Test_ingest_app_message_FailsOverflowWhenNumberOfMessagesIsFull(void) 98 | { 99 | /* Arrange */ 100 | unsigned char msg[8] = {0x18, 0x81, 0xC0, 0x00, 0x00, 0x01, 0x00, 0x00}; 101 | int msgSize = sizeof(msg); 102 | int pipe_assigned = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; 103 | int msg_id_slot = rand() % CFE_SBN_CLIENT_MAX_MSG_IDS_PER_PIPE; 104 | int read_msg = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH; 105 | int num_msg = CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH; 106 | int msg_slot = read_msg + num_msg; 107 | int sockfd = Any_int(); 108 | 109 | wrap_pthread_mutex_lock_should_be_called = TRUE; 110 | wrap_pthread_mutex_unlock_should_be_called = TRUE; 111 | wrap_pthread_cond_signal_should_be_called = FALSE; 112 | use_wrap_CFE_SBN_Client_GetMsgId = TRUE; 113 | wrap_CFE_SBN_Client_GetMsgId_return_value = msg[0] << 8 | msg[1]; 114 | use_wrap_CFE_SBN_CLIENT_ReadBytes = TRUE; 115 | wrap_CFE_SBN_CLIENT_ReadBytes_return_value = CFE_SUCCESS; 116 | wrap_CFE_SBN_CLIENT_ReadBytes_msg_buffer = msg; 117 | 118 | PipeTbl[pipe_assigned].InUse = CFE_SBN_CLIENT_IN_USE; 119 | PipeTbl[pipe_assigned].PipeId = pipe_assigned; 120 | PipeTbl[pipe_assigned].SubscribedMsgIds[msg_id_slot] = msg[0] << 8 | msg[1]; 121 | PipeTbl[pipe_assigned].NumberOfMessages = num_msg; 122 | PipeTbl[pipe_assigned].ReadMessage = read_msg; 123 | 124 | if (msg_slot >= CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH) 125 | { 126 | msg_slot = msg_slot - CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH; 127 | } 128 | 129 | /* Act */ 130 | ingest_app_message(sockfd, msgSize); 131 | 132 | /* Assert */ 133 | UtAssert_True(PipeTbl[pipe_assigned].NumberOfMessages == num_msg, 134 | "PipeTbl[%d].NumberOfMessages %d should not increase and was %d", 135 | pipe_assigned, num_msg, PipeTbl[pipe_assigned].NumberOfMessages); 136 | UtAssert_True(PipeTbl[pipe_assigned].ReadMessage == read_msg, 137 | "PipeTbl[%d].ReadMessage should not have changed from %d and was %d", 138 | pipe_assigned, read_msg, PipeTbl[pipe_assigned].ReadMessage); 139 | UtAssert_True(wrap_pthread_mutex_lock_was_called == TRUE, 140 | "pthread_mutex_lock was called"); 141 | UtAssert_True(wrap_pthread_mutex_unlock_was_called == TRUE, 142 | "pthread_mutex_unlock was called"); 143 | UtAssert_True(wrap_pthread_cond_signal_was_called == FALSE, 144 | "pthread_cond_signal should not have been called"); 145 | } 146 | 147 | void Test_ingest_app_message_FailsWhenNoPipeLookingForMessageId(void) 148 | { 149 | /* Arrange */ 150 | unsigned char msg[8] = {0x18, 0x81, 0xC0, 0x00, 0x00, 0x01, 0x00, 0x00}; 151 | int msgSize = sizeof(msg); 152 | int pipe_assigned = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; 153 | int msg_id_slot = rand() % CFE_SBN_CLIENT_MAX_MSG_IDS_PER_PIPE; 154 | int read_msg = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH; 155 | int num_msg = 0; 156 | int msg_slot= read_msg + num_msg; 157 | int sockfd = Any_int(); 158 | char err_msg[60] = "SBN_CLIENT: ERROR no subscription for this msgid"; 159 | 160 | use_wrap_CFE_SBN_CLIENT_ReadBytes = TRUE; 161 | wrap_CFE_SBN_CLIENT_ReadBytes_return_value = Any_int32_Except(CFE_SUCCESS); 162 | 163 | log_message_expected_string = err_msg; 164 | 165 | wrap_pthread_mutex_lock_should_be_called = TRUE; 166 | wrap_pthread_mutex_unlock_should_be_called = TRUE; 167 | wrap_pthread_cond_signal_should_be_called = FALSE; 168 | use_wrap_CFE_SBN_Client_GetMsgId = TRUE; 169 | wrap_CFE_SBN_Client_GetMsgId_return_value = msg[0] << 8 | msg[1]; 170 | use_wrap_CFE_SBN_CLIENT_ReadBytes = TRUE; 171 | wrap_CFE_SBN_CLIENT_ReadBytes_return_value = CFE_SUCCESS; 172 | wrap_CFE_SBN_CLIENT_ReadBytes_msg_buffer = msg; 173 | 174 | PipeTbl[pipe_assigned].InUse = CFE_SBN_CLIENT_IN_USE; 175 | PipeTbl[pipe_assigned].PipeId = pipe_assigned; 176 | PipeTbl[pipe_assigned].SubscribedMsgIds[msg_id_slot] = 0x0000; 177 | PipeTbl[pipe_assigned].NumberOfMessages = num_msg; 178 | PipeTbl[pipe_assigned].ReadMessage = read_msg; 179 | 180 | if (msg_slot >= CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH) 181 | { 182 | msg_slot = msg_slot - CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH; 183 | } 184 | 185 | /* Act */ 186 | ingest_app_message(sockfd, msgSize); 187 | 188 | /* Assert */ 189 | UtAssert_True(PipeTbl[pipe_assigned].NumberOfMessages == 0, 190 | "PipeTbl[%d].NumberOfMessages should = %d and was %d ", pipe_assigned, 191 | CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH, 192 | PipeTbl[pipe_assigned].NumberOfMessages); 193 | UtAssert_True(PipeTbl[pipe_assigned].ReadMessage == read_msg, 194 | "PipeTbl[%d].ReadMessage should not have changed from %d and was %d", 195 | pipe_assigned, read_msg, PipeTbl[pipe_assigned].ReadMessage); 196 | UtAssert_True(wrap_pthread_mutex_lock_was_called == TRUE, 197 | "pthread_mutex_lock was called"); 198 | UtAssert_True(wrap_pthread_mutex_unlock_was_called == TRUE, 199 | "pthread_mutex_unlock was called"); 200 | UtAssert_True(wrap_pthread_cond_signal_was_called == FALSE, 201 | "pthread_cond_signal should not have been called"); 202 | } 203 | 204 | void Test_ingest_app_message_SuccessAllSlotsAvailable(void) 205 | { 206 | /* Arrange */ 207 | unsigned char msg[8] = {0x18, 0x81, 0xC0, 0x00, 0x00, 0x01, 0x00, 0x00}; 208 | int msgSize = sizeof(msg); 209 | int pipe_assigned = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; 210 | int msg_id_slot = rand() % CFE_SBN_CLIENT_MAX_MSG_IDS_PER_PIPE; 211 | int read_msg = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH; 212 | int num_msg = 0; 213 | int msg_slot = read_msg + num_msg; 214 | int sockfd = Any_int(); 215 | 216 | wrap_pthread_mutex_lock_should_be_called = TRUE; 217 | wrap_pthread_mutex_unlock_should_be_called = TRUE; 218 | wrap_pthread_cond_signal_should_be_called = TRUE; 219 | use_wrap_CFE_SBN_Client_GetMsgId = TRUE; 220 | wrap_CFE_SBN_Client_GetMsgId_return_value = msg[0] << 8 | msg[1]; 221 | use_wrap_CFE_SBN_CLIENT_ReadBytes = TRUE; 222 | wrap_CFE_SBN_CLIENT_ReadBytes_return_value = CFE_SUCCESS; 223 | wrap_CFE_SBN_CLIENT_ReadBytes_msg_buffer = msg; 224 | 225 | PipeTbl[pipe_assigned].InUse = CFE_SBN_CLIENT_IN_USE; 226 | PipeTbl[pipe_assigned].PipeId = pipe_assigned; 227 | PipeTbl[pipe_assigned].SubscribedMsgIds[msg_id_slot] = msg[0] << 8 | msg[1]; 228 | PipeTbl[pipe_assigned].NumberOfMessages = num_msg; 229 | PipeTbl[pipe_assigned].ReadMessage = read_msg; 230 | 231 | if (msg_slot >= CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH) 232 | { 233 | msg_slot = msg_slot - CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH; 234 | } 235 | 236 | /* Act */ 237 | ingest_app_message(sockfd, msgSize); 238 | 239 | /* Assert */ 240 | int i; 241 | 242 | for(i = 0; i < msgSize; i++) 243 | { 244 | UtAssert_True(PipeTbl[pipe_assigned].Messages[msg_slot][i] == msg[i], 245 | "PipeTbl[%d].Messages[%d][%d] should = %d and was %d", 246 | pipe_assigned, msg_slot, i, msg[i], 247 | PipeTbl[pipe_assigned].Messages[msg_slot][i]); 248 | } 249 | UtAssert_True(PipeTbl[pipe_assigned].NumberOfMessages == num_msg + 1, 250 | "PipeTbl[%d].NumberOfMessages should increase by 1 to %d and was %d", 251 | pipe_assigned, num_msg + 1, PipeTbl[pipe_assigned].NumberOfMessages); 252 | UtAssert_True(PipeTbl[pipe_assigned].ReadMessage == read_msg, 253 | "PipeTbl[%d].ReadMessage should not have changed from %d and was %d", 254 | pipe_assigned, read_msg, PipeTbl[pipe_assigned].ReadMessage); 255 | UtAssert_True(wrap_pthread_mutex_lock_was_called == TRUE, 256 | "pthread_mutex_lock was called"); 257 | UtAssert_True(wrap_pthread_mutex_unlock_was_called == TRUE, 258 | "pthread_mutex_unlock was called"); 259 | UtAssert_True(wrap_pthread_cond_signal_was_called == TRUE, 260 | "pthread_cond_signal was called"); 261 | } 262 | 263 | void Test_ingest_app_message_SuccessAnyNumberOfSlotsAvailable(void) 264 | { 265 | /* Arrange */ 266 | unsigned char msg[8] = {0x18, 0x81, 0xC0, 0x00, 0x00, 0x01, 0x00, 0x00}; 267 | int msgSize = sizeof(msg); 268 | int pipe_assigned = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; 269 | int msg_id_slot = rand() % CFE_SBN_CLIENT_MAX_MSG_IDS_PER_PIPE; 270 | int read_msg = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH; 271 | /* from 1 to CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH */ 272 | int num_msg = (rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH - 1) + 1; 273 | int msg_slot = read_msg + num_msg; 274 | int sockfd = Any_int(); 275 | 276 | wrap_pthread_mutex_lock_should_be_called = TRUE; 277 | wrap_pthread_mutex_unlock_should_be_called = TRUE; 278 | wrap_pthread_cond_signal_should_be_called = TRUE; 279 | use_wrap_CFE_SBN_Client_GetMsgId = TRUE; 280 | wrap_CFE_SBN_Client_GetMsgId_return_value = msg[0] << 8 | msg[1]; 281 | use_wrap_CFE_SBN_CLIENT_ReadBytes = TRUE; 282 | wrap_CFE_SBN_CLIENT_ReadBytes_return_value = CFE_SUCCESS; 283 | wrap_CFE_SBN_CLIENT_ReadBytes_msg_buffer = msg; 284 | 285 | PipeTbl[pipe_assigned].InUse = CFE_SBN_CLIENT_IN_USE; 286 | PipeTbl[pipe_assigned].PipeId = pipe_assigned; 287 | PipeTbl[pipe_assigned].SubscribedMsgIds[msg_id_slot] = msg[0] << 8 | msg[1]; 288 | PipeTbl[pipe_assigned].NumberOfMessages = num_msg; 289 | PipeTbl[pipe_assigned].ReadMessage = read_msg; 290 | 291 | if (msg_slot >= CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH) 292 | { 293 | msg_slot = msg_slot - CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH; 294 | } 295 | 296 | /* Act */ 297 | ingest_app_message(sockfd, msgSize); 298 | 299 | /* Assert */ 300 | int i; 301 | 302 | for(i = 0; i < msgSize; i++) 303 | { 304 | UtAssert_True(PipeTbl[pipe_assigned].Messages[msg_slot][i] == msg[i], 305 | "PipeTbl[%d].Messages[%d][%d] should = %d and was %d", 306 | pipe_assigned, msg_slot, i, msg[i], 307 | PipeTbl[pipe_assigned].Messages[msg_slot][i]); 308 | } 309 | UtAssert_True(PipeTbl[pipe_assigned].NumberOfMessages == num_msg + 1, 310 | "PipeTbl[%d].NumberOfMessages should increase by 1 to %d and was %d", 311 | pipe_assigned, num_msg + 1, PipeTbl[pipe_assigned].NumberOfMessages); 312 | UtAssert_True(PipeTbl[pipe_assigned].ReadMessage == read_msg, 313 | "PipeTbl[%d].ReadMessage should not have changed from %d and was %d", 314 | pipe_assigned, read_msg, PipeTbl[pipe_assigned].ReadMessage); 315 | UtAssert_True(wrap_pthread_mutex_lock_was_called == TRUE, 316 | "pthread_mutex_lock was called"); 317 | UtAssert_True(wrap_pthread_mutex_unlock_was_called == TRUE, 318 | "pthread_mutex_unlock was called"); 319 | UtAssert_True(wrap_pthread_cond_signal_was_called == TRUE, 320 | "pthread_cond_signal was called"); 321 | } 322 | 323 | void Test_ingest_app_message_SuccessWhenOnlyOneSlotLeft(void) 324 | { 325 | /* Arrange */ 326 | unsigned char msg[8] = {0x18, 0x81, 0xC0, 0x00, 0x00, 0x01, 0x00, 0x00}; 327 | int msgSize = sizeof(msg); 328 | int pipe_assigned = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; 329 | int msg_id_slot = rand() % CFE_SBN_CLIENT_MAX_MSG_IDS_PER_PIPE; 330 | int read_msg = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH; 331 | int num_msg = CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH - 1; /* 1 slot left */ 332 | int msg_slot= read_msg + num_msg; 333 | int sockfd = Any_int(); 334 | 335 | wrap_pthread_mutex_lock_should_be_called = TRUE; 336 | wrap_pthread_mutex_unlock_should_be_called = TRUE; 337 | wrap_pthread_cond_signal_should_be_called = TRUE; 338 | use_wrap_CFE_SBN_Client_GetMsgId = TRUE; 339 | wrap_CFE_SBN_Client_GetMsgId_return_value = msg[0] << 8 | msg[1]; 340 | use_wrap_CFE_SBN_CLIENT_ReadBytes = TRUE; 341 | wrap_CFE_SBN_CLIENT_ReadBytes_return_value = CFE_SUCCESS; 342 | wrap_CFE_SBN_CLIENT_ReadBytes_msg_buffer = msg; 343 | 344 | PipeTbl[pipe_assigned].InUse = CFE_SBN_CLIENT_IN_USE; 345 | PipeTbl[pipe_assigned].PipeId = pipe_assigned; 346 | PipeTbl[pipe_assigned].SubscribedMsgIds[msg_id_slot] = msg[0] << 8 | msg[1]; 347 | PipeTbl[pipe_assigned].NumberOfMessages = num_msg; 348 | PipeTbl[pipe_assigned].ReadMessage = read_msg; 349 | 350 | if (msg_slot >= CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH) 351 | { 352 | msg_slot = msg_slot - CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH; 353 | } 354 | 355 | /* Act */ 356 | ingest_app_message(sockfd, msgSize); 357 | 358 | /* Assert */ 359 | int i; 360 | 361 | for(i = 0; i < msgSize; i++) 362 | { 363 | UtAssert_True(PipeTbl[pipe_assigned].Messages[msg_slot][i] == msg[i], 364 | "PipeTbl[%d].Messages[%d][%d] should = %d and was %d ", 365 | pipe_assigned, msg_slot, i, msg[i], 366 | PipeTbl[pipe_assigned].Messages[msg_slot][i]); 367 | } 368 | UtAssert_True(PipeTbl[pipe_assigned].NumberOfMessages == 369 | CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH, 370 | "PipeTbl[%d].NumberOfMessages should = %d and was %d ", pipe_assigned, 371 | CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH, 372 | PipeTbl[pipe_assigned].NumberOfMessages); 373 | UtAssert_True(PipeTbl[pipe_assigned].ReadMessage == read_msg, 374 | "PipeTbl[%d].ReadMessage should not have changed from %d and was %d", 375 | pipe_assigned, read_msg, PipeTbl[pipe_assigned].ReadMessage); 376 | UtAssert_True(wrap_pthread_mutex_lock_was_called == TRUE, 377 | "pthread_mutex_lock was called"); 378 | UtAssert_True(wrap_pthread_mutex_unlock_was_called == TRUE, 379 | "pthread_mutex_unlock was called"); 380 | UtAssert_True(wrap_pthread_cond_signal_was_called == TRUE, 381 | "pthread_cond_signal was called"); 382 | } 383 | 384 | //void Test_ingest_app_message_SuccessCausesPipeNumberOfMessagesToIncreaseBy1 385 | //void Test_ingest_app_message_FailsWhenNoPipesInUse 386 | /* end ingest_app_message Tests */ 387 | 388 | 389 | 390 | void UtTest_Setup(void) 391 | { 392 | /* ingest_app_message Tests */ 393 | UtTest_Add( 394 | Test_ingest_app_message_ReadBytesFails, 395 | SBN_Client_Ingest_Setup, SBN_Client_Ingest_Teardown, 396 | "Test_ingest_app_message_ReadBytesFails"); 397 | UtTest_Add( 398 | Test_ingest_app_message_FailsWhenNoPipesInUse, 399 | SBN_Client_Ingest_Setup, SBN_Client_Ingest_Teardown, 400 | "Test_ingest_app_message_FailsWhenNoPipesInUse"); 401 | UtTest_Add( 402 | Test_ingest_app_message_FailsOverflowWhenNumberOfMessagesIsFull, 403 | SBN_Client_Ingest_Setup, SBN_Client_Ingest_Teardown, 404 | "Test_ingest_app_message_FailsOverflowWhenNumberOfMessagesIsFull"); 405 | UtTest_Add( 406 | Test_ingest_app_message_FailsWhenNoPipeLookingForMessageId, 407 | SBN_Client_Ingest_Setup, SBN_Client_Ingest_Teardown, 408 | "Test_ingest_app_message_FailsWhenNoPipeLookingForMessageId"); 409 | UtTest_Add( 410 | Test_ingest_app_message_SuccessAllSlotsAvailable, 411 | SBN_Client_Ingest_Setup, SBN_Client_Ingest_Teardown, 412 | "Test_ingest_app_message_SuccessAllSlotsAvailable"); 413 | UtTest_Add( 414 | Test_ingest_app_message_SuccessAnyNumberOfSlotsAvailable, 415 | SBN_Client_Ingest_Setup, SBN_Client_Ingest_Teardown, 416 | "Test_ingest_app_message_SuccessAnyNumberOfSlotsAvailable"); 417 | UtTest_Add( 418 | Test_ingest_app_message_SuccessWhenOnlyOneSlotLeft, 419 | SBN_Client_Ingest_Setup, SBN_Client_Ingest_Teardown, 420 | "Test_ingest_app_message_SuccessWhenOnlyOneSlotLeft"); 421 | } -------------------------------------------------------------------------------- /unit-test/sbn_client_init_tests.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include "sbn_client_tests_includes.h" 14 | 15 | /******************************************************************************* 16 | ** 17 | ** SBN_Client_Init_Tests Setup and Teardown 18 | ** 19 | *******************************************************************************/ 20 | 21 | void SBN_Client_Init_Setup(void) 22 | { 23 | SBN_Client_Setup(); 24 | } 25 | 26 | void SBN_Client_Init_Teardown(void) 27 | { 28 | SBN_Client_Teardown(); 29 | } 30 | 31 | /******************************************************************************* 32 | ** 33 | ** SBN_Client_Init Tests 34 | ** 35 | *******************************************************************************/ 36 | 37 | void Test_SBN_Client_Init_FailsBecause_connect_to_server_Fails(void) 38 | { 39 | /* Arrange */ 40 | int32 result; 41 | int32 expected_result = SBN_CLIENT_BAD_SOCK_FD_EID; 42 | /* connect_to_server call control */ 43 | use_wrap_connect_to_server = TRUE; 44 | wrap_connect_to_server_return_value = Any_Negative_int(); 45 | 46 | /* Act */ 47 | result = SBN_Client_Init(); 48 | 49 | /* Assert */ 50 | UtAssert_True(result == expected_result, 51 | "SBN_Client_Init result should be %d, but was %d", 52 | SBN_CLIENT_BAD_SOCK_FD_EID, result); 53 | } 54 | 55 | void Test_SBN_Client_Init_FailsBecauseCreateHeartThreadFails(void) 56 | { 57 | /* Arrange */ 58 | int32 result; 59 | int32 expected_result = SBN_CLIENT_HEART_THREAD_CREATE_EID; 60 | /* connect_to_server call control */ 61 | use_wrap_connect_to_server = TRUE; 62 | wrap_connect_to_server_return_value = Any_Positive_int_Or_Zero(); 63 | 64 | use_wrap_CFE_SBN_Client_InitPipeTbl = TRUE; 65 | 66 | /* set pthread_create error */ 67 | pthread_create_errors_on_call_number = FIRST_CALL; 68 | pthread_create_error_value = Any_int_Except(0); 69 | 70 | /* set check_pthread_create_status return given error id */ 71 | use_wrap_check_pthread_create_status = TRUE; 72 | wrap_check_pthread_create_status_fail_call = TRUE; 73 | check_pthread_create_status_errors_on_call_number = FIRST_CALL; 74 | 75 | /* Act */ 76 | result = SBN_Client_Init(); 77 | 78 | /* Assert */ 79 | UtAssert_True(result == expected_result, 80 | "SBN_Client_Init result should be %d, but was %d", 81 | SBN_CLIENT_HEART_THREAD_CREATE_EID, result); 82 | UtAssert_True(sbn_client_sockfd == wrap_connect_to_server_return_value, 83 | "SBN_Client_Init successful call to connect_to_server set " 84 | "sbn_client_sockfd to the returned value"); 85 | UtAssert_True(sbn_client_cpuId == 2, "SBN_Client_Init set the " 86 | "sbn_client_cpuId to 2"); 87 | } 88 | 89 | void Test_SBN_Client_Init_FailsBecauseCreateReceiveThreadFails(void) 90 | { 91 | /* Arrange */ 92 | int32 result; 93 | int32 expected_result = SBN_CLIENT_RECEIVE_THREAD_CREATE_EID; 94 | /* connect_to_server call control */ 95 | use_wrap_connect_to_server = TRUE; 96 | wrap_connect_to_server_return_value = Any_Positive_int_Or_Zero(); 97 | 98 | use_wrap_CFE_SBN_Client_InitPipeTbl = TRUE; 99 | 100 | /* set pthread_create error */ 101 | pthread_create_errors_on_call_number = SECOND_CALL; 102 | pthread_create_error_value = Any_int_Except(0); 103 | 104 | /* set check_pthread_create_status return given error id */ 105 | use_wrap_check_pthread_create_status = TRUE; 106 | wrap_check_pthread_create_status_fail_call = TRUE; 107 | check_pthread_create_status_errors_on_call_number = SECOND_CALL; 108 | 109 | /* Act */ 110 | result = SBN_Client_Init(); 111 | 112 | /* Assert */ 113 | UtAssert_True(result == expected_result, 114 | "SBN_Client_Init result should be %d, but was %d", 115 | SBN_CLIENT_RECEIVE_THREAD_CREATE_EID, result); 116 | UtAssert_True(sbn_client_sockfd == wrap_connect_to_server_return_value, 117 | "SBN_Client_Init successful call to connect_to_server set " 118 | "sbn_client_sockfd to the returned value"); 119 | UtAssert_True(sbn_client_cpuId == 2, "SBN_Client_Init set the " 120 | "sbn_client_cpuId to 2"); 121 | } 122 | 123 | void Test_SBN_Client_Init_Success(void) 124 | { 125 | /* Arrange */ 126 | /* connect_to_server call control */ 127 | use_wrap_connect_to_server = TRUE; 128 | wrap_connect_to_server_return_value = Any_Positive_int_Or_Zero(); 129 | 130 | use_wrap_CFE_SBN_Client_InitPipeTbl = TRUE; 131 | 132 | /* set pthread_create to NOT error */ 133 | pthread_create_errors_on_call_number = 0; 134 | 135 | /* set check_pthread_create_status return given error id */ 136 | use_wrap_check_pthread_create_status = TRUE; 137 | wrap_check_pthread_create_status_fail_call = FALSE; 138 | 139 | /* Act */ 140 | int32 result = SBN_Client_Init(); 141 | 142 | /* Assert */ 143 | UtAssert_True(result == SBN_CLIENT_SUCCESS, 144 | "SBN_Client_Init result should be %d, but was %d", 145 | SBN_CLIENT_SUCCESS, result); 146 | UtAssert_True(sbn_client_sockfd == wrap_connect_to_server_return_value, 147 | "SBN_Client_Init successful call to connect_to_server set " 148 | "sbn_client_sockfd to the returned value"); 149 | UtAssert_True(sbn_client_cpuId == 2, "SBN_Client_Init set the " 150 | "sbn_client_cpuId to 2"); 151 | } 152 | /* end SBN_Client_Init Tests */ 153 | 154 | 155 | /*************************************************/ 156 | 157 | void UtTest_Setup(void) 158 | { 159 | /* SBN_Client_Init Tests */ 160 | UtTest_Add( 161 | Test_SBN_Client_Init_FailsBecause_connect_to_server_Fails, 162 | SBN_Client_Init_Setup, SBN_Client_Init_Teardown, 163 | "Test_SBN_Client_Init_FailsBecause_connect_to_server_Fails"); 164 | UtTest_Add( 165 | Test_SBN_Client_Init_FailsBecauseCreateHeartThreadFails, 166 | SBN_Client_Init_Setup, SBN_Client_Init_Teardown, 167 | "Test_SBN_Client_Init_FailsBecauseCreateHeartThreadFails"); 168 | UtTest_Add( 169 | Test_SBN_Client_Init_FailsBecauseCreateReceiveThreadFails, 170 | SBN_Client_Init_Setup, SBN_Client_Init_Teardown, 171 | "Test_SBN_Client_Init_FailsBecauseCreateReceiveThreadFails"); 172 | UtTest_Add( 173 | Test_SBN_Client_Init_Success, 174 | SBN_Client_Init_Setup, SBN_Client_Init_Teardown, 175 | "Test_SBN_Client_Init_Success"); 176 | } -------------------------------------------------------------------------------- /unit-test/sbn_client_logger_tests.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include "sbn_client_tests_includes.h" 14 | 15 | extern const char *log_message_expected_string; 16 | extern boolean log_message_was_called; 17 | extern const char *perror_expected_string; 18 | 19 | extern void (*wrap_log_message_call_func)(void); 20 | /******************************************************************************* 21 | ** 22 | ** SBN_Client_Logger_Tests Setup and Teardown 23 | ** 24 | *******************************************************************************/ 25 | 26 | void SBN_Client_Logger_Tests_Setup(void) 27 | { 28 | SBN_Client_Setup(); 29 | } 30 | 31 | void SBN_Client_Logger_Tests_Teardown(void) 32 | { 33 | SBN_Client_Teardown(); 34 | 35 | 36 | log_message_expected_string = ""; 37 | log_message_was_called = FALSE; 38 | perror_expected_string = ""; 39 | 40 | 41 | /* function pointers */ 42 | wrap_log_message_call_func = NULL; 43 | } 44 | 45 | /******************************************************************************* 46 | ** 47 | ** log_message Tests 48 | ** 49 | *******************************************************************************/ 50 | 51 | void Test_log_message_WritesExpectedNumberOfCharacters(void) 52 | { 53 | /* Arrange */ 54 | const char *test_message = "This is a test, %s %d %03f"; 55 | const char *test_string = "two numbers:"; 56 | int test_int = 5; 57 | float test_float = 5.515000; 58 | int32 result; 59 | int32 expectedResult = 39; 60 | 61 | /* Act */ 62 | result = log_message(test_message, test_string, test_int, test_float); 63 | 64 | /* Assert */ 65 | UtAssert_True(result == expectedResult, 66 | "log_message wrote %d characters and should be %d", 67 | result, expectedResult); 68 | 69 | } 70 | 71 | /* end log_message Tests */ 72 | 73 | void UtTest_Setup(void) 74 | { 75 | UtTest_Add(Test_log_message_WritesExpectedNumberOfCharacters, 76 | SBN_Client_Logger_Tests_Setup, SBN_Client_Logger_Tests_Teardown, 77 | "Test_log_message_WritesExpectedNumberOfCharacters"); 78 | } 79 | -------------------------------------------------------------------------------- /unit-test/sbn_client_minders_tests.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include "sbn_client_tests_includes.h" 14 | 15 | 16 | 17 | /******************************************************************************* 18 | ** 19 | ** SBN_Client_Minders_Tests Setup and Teardown 20 | ** 21 | *******************************************************************************/ 22 | 23 | void SBN_Client_Minders_Tests_Setup(void) 24 | { 25 | SBN_Client_Setup(); 26 | } 27 | 28 | void SBN_Client_Minders_Tests_Teardown(void) 29 | { 30 | SBN_Client_Teardown(); 31 | } 32 | 33 | void wrap_log_message_set_continue_recv_check_false(void) 34 | { 35 | continue_receive_check = FALSE; 36 | } 37 | 38 | void Test_SBN_Client_HeartbeatMinder_NoLoopContinueHeartbeatFalse(void) 39 | { 40 | /* Arrange */ 41 | void * result; 42 | 43 | continue_heartbeat = FALSE; 44 | 45 | /* Act */ 46 | result = SBN_Client_HeartbeatMinder(NULL); 47 | 48 | /* Assert */ 49 | UtAssert_True(result == NULL, "SBN_Client_HeartbeatMinder returned NULL"); 50 | } 51 | 52 | void Test_SBN_Client_HeartbeatMinder_HeartbeatWithSockfdZero(void) 53 | { 54 | /* Arrange */ 55 | void * result; 56 | sbn_client_sockfd = 0; 57 | 58 | wrap_sleep_call_func = &wrap_sleep_set_continue_heartbeat_false; 59 | 60 | /* Act */ 61 | result = SBN_Client_HeartbeatMinder(NULL); 62 | 63 | /* Assert */ 64 | UtAssert_True(result == NULL, "SBN_Client_HeartbeatMinder returned NULL"); 65 | } 66 | 67 | void Test_SBN_Client_HeartbeatMinder_RunsUntilContinueHeartbeatIsFalse(void) 68 | { 69 | /* Arrange */ 70 | void * result; 71 | sbn_client_sockfd = Any_Non_Zero_int(); 72 | 73 | /* call number becomes from 1 to 255 */ 74 | send_heartbeat_discontinue_on_call_number = (rand() % UCHAR_MAX) + 1; 75 | 76 | use_wrap_send_heartbeat = TRUE; 77 | wrap_send_heartbeat_return_value = Any_int(); 78 | 79 | /* Act */ 80 | result = SBN_Client_HeartbeatMinder(NULL); 81 | 82 | /* Assert */ 83 | UtAssert_True(result == NULL, "SBN_Client_HeartbeatMinder returned NULL"); 84 | UtAssert_True(send_hearbeat_call_number == 85 | send_heartbeat_discontinue_on_call_number, 86 | "send_heartbeat was called the expected number of times"); 87 | } 88 | 89 | void Test_SBN_Client_ReceiveMinder_NoLoopContinueReceiveCheckFalse(void) 90 | { 91 | /* Arrange */ 92 | void * result; 93 | 94 | continue_receive_check = FALSE; 95 | 96 | /* Act */ 97 | result = SBN_Client_ReceiveMinder(NULL); 98 | 99 | /* Assert */ 100 | UtAssert_True(result == NULL, "SBN_Client_HeartbeatMinder returned NULL"); 101 | 102 | } 103 | 104 | void Test_SBN_Client_ReceiveMinder_Outlog_messageError(void) 105 | { 106 | /* Arrange */ 107 | char err_msg[50]; 108 | void * result; 109 | 110 | use_wrap_recv_msg = TRUE; 111 | 112 | wrap_recv_msg_return_value = Any_int32_Except(CFE_SUCCESS); 113 | snprintf(err_msg, 50, "Receive message returned error 0x%08X\n", 114 | wrap_recv_msg_return_value); 115 | 116 | log_message_expected_string = err_msg; 117 | wrap_log_message_call_func = 118 | &wrap_log_message_set_continue_recv_check_false; 119 | 120 | /* Act */ 121 | result = SBN_Client_ReceiveMinder(NULL); 122 | 123 | /* Assert */ 124 | UtAssert_True(result == NULL, "SBN_Client_HeartbeatMinder returned NULL"); 125 | } 126 | 127 | void Test_SBN_Client_ReceiveMinder_RunsUntilContinueReceiveCheckIsFalse(void) 128 | { 129 | /* Arrange */ 130 | void * result; 131 | 132 | /* call number becomes from 1 to 255 */ 133 | recv_msg_discontiue_on_call_number = (rand() % UCHAR_MAX) + 1; 134 | 135 | use_wrap_recv_msg = TRUE; 136 | wrap_recv_msg_return_value = CFE_SUCCESS; 137 | 138 | /* Act */ 139 | result = SBN_Client_ReceiveMinder(NULL); 140 | 141 | /* Assert */ 142 | UtAssert_True(result == NULL, "SBN_Client_HeartbeatMinder returned NULL"); 143 | UtAssert_True(recv_msg_call_number == recv_msg_discontiue_on_call_number, 144 | "recv_msg was called the expected number of times"); 145 | } 146 | 147 | void UtTest_Setup(void) 148 | { 149 | UtTest_Add( 150 | Test_SBN_Client_HeartbeatMinder_NoLoopContinueHeartbeatFalse, 151 | SBN_Client_Minders_Tests_Setup, SBN_Client_Minders_Tests_Teardown, 152 | "Test_SBN_Client_HeartbeatMinder_NoLoopContinueHeartbeatFalse"); 153 | UtTest_Add( 154 | Test_SBN_Client_HeartbeatMinder_HeartbeatWithSockfdZero, 155 | SBN_Client_Minders_Tests_Setup, SBN_Client_Minders_Tests_Teardown, 156 | "Test_SBN_Client_HeartbeatMinder_HeartbeatWithSockfdZero"); 157 | UtTest_Add( 158 | Test_SBN_Client_HeartbeatMinder_RunsUntilContinueHeartbeatIsFalse, 159 | SBN_Client_Minders_Tests_Setup, SBN_Client_Minders_Tests_Teardown, 160 | "Test_SBN_Client_HeartbeatMinder_RunsUntilContinueHeartbeatIsFalse"); 161 | 162 | 163 | 164 | 165 | UtTest_Add( 166 | Test_SBN_Client_ReceiveMinder_NoLoopContinueReceiveCheckFalse, 167 | SBN_Client_Minders_Tests_Setup, SBN_Client_Minders_Tests_Teardown, 168 | "Test_SBN_Client_ReceiveMinder_NoLoopContinueReceiveCheckFalse"); 169 | UtTest_Add( 170 | Test_SBN_Client_ReceiveMinder_Outlog_messageError, 171 | SBN_Client_Minders_Tests_Setup, SBN_Client_Minders_Tests_Teardown, 172 | "Test_SBN_Client_ReceiveMinder_Outlog_messageError"); 173 | UtTest_Add( 174 | Test_SBN_Client_ReceiveMinder_RunsUntilContinueReceiveCheckIsFalse, 175 | SBN_Client_Minders_Tests_Setup, SBN_Client_Minders_Tests_Teardown, 176 | "Test_SBN_Client_ReceiveMinder_RunsUntilContinueReceiveCheckIsFalse"); 177 | } 178 | -------------------------------------------------------------------------------- /unit-test/sbn_client_tests.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include "sbn_client_tests_includes.h" 14 | 15 | /******************************************************************************* 16 | ** 17 | ** SBN_Client_Tests Setup and Teardown 18 | ** 19 | *******************************************************************************/ 20 | 21 | void SBN_Client_Tests_Setup(void) 22 | { 23 | SBN_Client_Setup(); 24 | } /* end SBN_Client_Tests_Setup */ 25 | 26 | void SBN_Client_Tests_Teardown(void) 27 | { 28 | SBN_Client_Teardown(); 29 | } /* end SBN_Client_Tests_Setup */ 30 | 31 | /******************************************************************************* 32 | ** 33 | ** CFE_SBN_Client_InitPipeTbl Tests 34 | ** 35 | *******************************************************************************/ 36 | 37 | void Test_CFE_SBN_Client_InitPipeTblFullyInitializesPipes(void) 38 | { 39 | /* Arrange */ 40 | int i, j; 41 | 42 | /* Act */ 43 | CFE_SBN_Client_InitPipeTbl(); 44 | 45 | /* Assert */ 46 | for(i = 0; i < CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; i++) 47 | { 48 | CFE_SBN_Client_PipeD_t test_pipe = PipeTbl[i]; 49 | 50 | UtAssert_True(test_pipe.InUse == CFE_SBN_CLIENT_NOT_IN_USE, 51 | "PipeTbl[%d].InUse should equal %d and was %d", i, 52 | CFE_SBN_CLIENT_NOT_IN_USE, test_pipe.InUse); 53 | UtAssert_True(test_pipe.SysQueueId == CFE_SBN_CLIENT_UNUSED_QUEUE, 54 | "PipeTbl[%d].SysQueueId should equal %d and was %d", i, 55 | CFE_SBN_CLIENT_UNUSED_QUEUE, test_pipe.SysQueueId); 56 | UtAssert_True(test_pipe.PipeId == CFE_SBN_CLIENT_INVALID_PIPE, 57 | "PipeTbl[%d].PipeId should equal %d and was %d", i, 58 | CFE_SBN_CLIENT_INVALID_PIPE, test_pipe.PipeId); 59 | UtAssert_True(test_pipe.NumberOfMessages == 1, 60 | "PipeTbl[%d].NumberOfMessages should equal %d and was %d", i, 1, 61 | test_pipe.NumberOfMessages); 62 | UtAssert_True(test_pipe.ReadMessage == 63 | (CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH - 1), 64 | "PipeTbl[%d].ReadMessage should equal %d and was %d", i, 65 | CFE_PLATFORM_SBN_CLIENT_MAX_PIPE_DEPTH - 1, 66 | test_pipe.ReadMessage); 67 | UtAssert_True(strcmp(test_pipe.PipeName, "") == 0, 68 | "PipeTbl[%d].PipeId should equal '' and was '%s'", i, 69 | test_pipe.PipeName); 70 | 71 | for(j = 0; j < CFE_SBN_CLIENT_MAX_MSG_IDS_PER_PIPE; j++) 72 | { 73 | UtAssert_True(test_pipe.SubscribedMsgIds[j] == 74 | CFE_SBN_CLIENT_INVALID_MSG_ID, 75 | "PipeTbl[%d].SubscribedMsgIds[%d] should be %d and was %d", i, j, 76 | CFE_SBN_CLIENT_INVALID_MSG_ID, test_pipe.SubscribedMsgIds[j]); 77 | } 78 | 79 | } 80 | 81 | } /* end Test_CFE_SBN_Client_InitPipeTblFullyInitializesPipes */ 82 | 83 | /* end CFE_SBN_Client_InitPipeTbl Tests */ 84 | 85 | /******************************************************************************* 86 | ** 87 | ** CFE_SBN_Client_GetAvailPipeIdx Tests 88 | ** 89 | *******************************************************************************/ 90 | 91 | void Test_CFE_SBN_Client_GetAvailPipeIdx_ReturnsErrorWhenAllPipesUsed(void) 92 | { 93 | /* Arrange */ 94 | int i; 95 | CFE_SB_PipeId_t result; 96 | for(i = 0; i < CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; i++) 97 | { 98 | PipeTbl[i].InUse = CFE_SBN_CLIENT_IN_USE; 99 | } 100 | 101 | /* Act */ 102 | result = CFE_SBN_Client_GetAvailPipeIdx(); 103 | 104 | /* Assert */ 105 | UtAssert_True(result == CFE_SBN_CLIENT_INVALID_PIPE, 106 | "CFE_SBN_Client_GetAvailPipeIdx returned CFE_SBN_CLIENT_INVALID_PIPE"); 107 | } /* end Test_CFE_SBN_Client_GetAvailPipeIdx_ReturnsErrorWhenAllPipesUsed */ 108 | 109 | void Test_CFE_SBN_Client_GetAvailPipeIdx_ReturnsIndexForFirstOpenPipe(void) 110 | { 111 | /* Arrange */ 112 | int i; 113 | /* 0 to CFE_PLATFORM_SBN_CLIENT_MAX_PIPES */ 114 | int available_index = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; 115 | CFE_SB_PipeId_t result; 116 | for(i = 0; i < available_index; i++) 117 | { 118 | PipeTbl[i].InUse = CFE_SBN_CLIENT_IN_USE; 119 | } 120 | 121 | /* Act */ 122 | result = CFE_SBN_Client_GetAvailPipeIdx(); 123 | 124 | /* Assert */ 125 | UtAssert_True(result == available_index, 126 | "CFE_SBN_Client_GetAvailPipeIdx should have returned %d and returned %d", 127 | available_index, result); 128 | } /* end Test_CFE_SBN_Client_GetAvailPipeIdx_ReturnsIndexForFirstOpenPipe */ 129 | 130 | /* end CFE_SBN_Client_GetAvailPipeIdx Tests */ 131 | 132 | /******************************************************************************* 133 | ** 134 | ** add test group functions 135 | ** 136 | *******************************************************************************/ 137 | 138 | void add_CFE_SBN_Client_InitPipeTbl_tests(void) 139 | { 140 | UtTest_Add(Test_CFE_SBN_Client_InitPipeTblFullyInitializesPipes, 141 | SBN_Client_Tests_Setup, SBN_Client_Tests_Teardown, 142 | "Test_CFE_SBN_Client_InitPipeTblFullyInitializesPipes"); 143 | } /* end add_CFE_SBN_Client_InitPipeTbl_tests */ 144 | 145 | void add_CFE_SBN_Client_GetAvailPipeIdx(void) 146 | { 147 | UtTest_Add(Test_CFE_SBN_Client_GetAvailPipeIdx_ReturnsErrorWhenAllPipesUsed, 148 | SBN_Client_Tests_Setup, SBN_Client_Tests_Teardown, 149 | "Test_CFE_SBN_Client_GetAvailPipeIdx_ReturnsErrorWhenAllPipesUsed"); 150 | UtTest_Add(Test_CFE_SBN_Client_GetAvailPipeIdx_ReturnsIndexForFirstOpenPipe, 151 | SBN_Client_Tests_Setup, SBN_Client_Tests_Teardown, 152 | "Test_CFE_SBN_Client_GetAvailPipeIdx_ReturnsIndexForFirstOpenPipe"); 153 | } /* end add_CFE_SBN_Client_GetAvailPipeIdx */ 154 | 155 | /* end add test group functions */ 156 | 157 | /******************************************************************************* 158 | ** 159 | ** Required UtTest_Setup function for ut-assert framework 160 | ** 161 | *******************************************************************************/ 162 | 163 | void UtTest_Setup(void) 164 | { 165 | add_CFE_SBN_Client_InitPipeTbl_tests(); 166 | 167 | add_CFE_SBN_Client_GetAvailPipeIdx(); 168 | } /* end UtTest_Setup */ 169 | 170 | /* end Required UtTest_Setup function for ut-assert framework */ 171 | -------------------------------------------------------------------------------- /unit-test/sbn_client_tests_includes.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #ifndef _sbn_client_tests_includes_h_ 14 | #define _sbn_client_tests_includes_h_ 15 | 16 | /* Library includes */ 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | /* UT includes */ 28 | #include "uttest.h" 29 | #include "utassert.h" 30 | #include "utstubs.h" 31 | 32 | /* SBN_Client includes */ 33 | #include "sbn_client_ingest.h" 34 | #include "sbn_client_init.h" 35 | #include "sbn_client_logger.h" 36 | #include "sbn_client_minders.h" 37 | #include "sbn_client_utils.h" 38 | #include "sbn_client_version.h" 39 | #include "sbn_client.h" 40 | 41 | /* SBN_Client test includes */ 42 | #include "sbn_client_common_test_utils.h" 43 | #include "sbn_client_wrapped_functions.h" 44 | #include "sbn_client_logger_stubs.h" 45 | 46 | /* SBN_Client variable access */ 47 | extern int sbn_client_sockfd; 48 | extern int sbn_client_cpuId; 49 | extern boolean continue_heartbeat; 50 | extern boolean continue_receive_check; 51 | extern CFE_SBN_Client_PipeD_t PipeTbl[CFE_PLATFORM_SBN_CLIENT_MAX_PIPES]; 52 | extern const char *log_message_expected_string; 53 | extern boolean log_message_was_called; 54 | 55 | #endif /* _sbn_client_tests_includes_h_ */ -------------------------------------------------------------------------------- /unit-test/sbn_client_utils_tests.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include "sbn_client_tests_includes.h" 14 | 15 | void add_connect_to_server_tests(void); 16 | 17 | /******************************************************************************* 18 | ** 19 | ** SBN_Client_Utils_Tests Setup and Teardown 20 | ** 21 | *******************************************************************************/ 22 | 23 | void SBN_Client_Utils_Tests_Setup(void) 24 | { 25 | SBN_Client_Setup(); 26 | 27 | wrap_socket_return_value = (rand() % INT_MIN) * -1; 28 | wrap_htons_return_value = 0; 29 | wrap_inet_pton_return_value = 1; 30 | wrap_connect_return_value = -1; 31 | wrap_read_return_value = INT_MIN; 32 | } 33 | 34 | void SBN_Client_Utils_Tests_Teardown(void) 35 | { 36 | SBN_Client_Teardown(); 37 | } 38 | 39 | /******************************************************************************* 40 | ** 41 | ** Helper Functions for check_pthread_create_status Tests 42 | ** 43 | *******************************************************************************/ 44 | 45 | void check_pthread_create_status_Outlog_messageCorrectError(int error, 46 | const char *error_name) 47 | { 48 | /* Arrange */ 49 | char p_e_s[50]; 50 | int status = error; 51 | int32 errorId = rand() % INT_MIN; 52 | 53 | sprintf(p_e_s, "Create thread error = %s", error_name); 54 | log_message_expected_string = p_e_s; 55 | perror_expected_string = "pthread_create error"; 56 | 57 | /* Act */ 58 | int32 result = check_pthread_create_status(status, errorId); 59 | 60 | /* Assert */ 61 | UtAssert_True(result == errorId, 62 | "check_pthread_create_status returned the errorId argument"); 63 | } 64 | 65 | 66 | /******************************************************************************* 67 | ** 68 | ** check_pthread_create_status Tests 69 | ** 70 | *******************************************************************************/ 71 | 72 | void Test_check_pthread_create_status_Outlog_messageErrorWhenStatusIs_EAGAIN(void) 73 | { 74 | check_pthread_create_status_Outlog_messageCorrectError(EAGAIN, "EAGAIN"); 75 | } 76 | 77 | void Test_check_pthread_create_status_Outlog_messageErrorWhenStatusIs_EINVAL(void) 78 | { 79 | check_pthread_create_status_Outlog_messageCorrectError(EINVAL, "EINVAL"); 80 | } 81 | 82 | void Test_check_pthread_create_status_Outlog_messageErrorWhenStatusIs_EPERM(void) 83 | { 84 | check_pthread_create_status_Outlog_messageCorrectError(EPERM, "EPERM"); 85 | } 86 | 87 | void Test_check_pthread_create_status_Is_errorId_WhenStatusIsNonZero(void) 88 | { 89 | /* Arrange */ 90 | int status = rand() % INT_MIN; 91 | int32 errorId = rand() % INT_MIN; 92 | perror_expected_string = "pthread_create error"; 93 | 94 | /* Act */ 95 | int32 result = check_pthread_create_status(status, errorId); 96 | 97 | /* Assert */ 98 | UtAssert_True(result == errorId, 99 | "check_pthread_create_status returned the errorId argument"); 100 | } 101 | 102 | void Test_check_pthread_create_status_Is_SBN_CLIENT_SUCCESS_When0(void) 103 | { 104 | /* Arrange */ 105 | int status = 0; 106 | int32 errorId = rand() % INT_MIN; 107 | 108 | /* Act */ 109 | int32 result = check_pthread_create_status(status, errorId); 110 | 111 | /* Assert */ 112 | UtAssert_True(result == SBN_CLIENT_SUCCESS, 113 | "check_pthread_create_status returned SBN_CLIENT_SUCCESS"); 114 | } 115 | 116 | /******************************************************************************* 117 | ** 118 | ** Helper Functions for connect_to_server Tests 119 | ** 120 | *******************************************************************************/ 121 | 122 | void connect_to_server_socket_fail_check(int32 expected_error, 123 | const char *error_name) 124 | { 125 | /* Arrange */ 126 | char p_e_s[50]; 127 | 128 | wrap_socket_return_value = -1; 129 | errno = expected_error; 130 | sprintf(p_e_s, "socket err = %s", error_name); 131 | log_message_expected_string = p_e_s; 132 | perror_expected_string = "connect_to_server socket error"; 133 | const char * dummyIp = NULL; 134 | uint16_t dummyPort = 0; 135 | 136 | /* Act */ 137 | int result = connect_to_server(dummyIp, dummyPort); 138 | 139 | /* Assert */ 140 | UtAssert_True(result == SERVER_SOCKET_ERROR, 141 | "Error returned should have been %d and was %d", 142 | SERVER_SOCKET_ERROR, result); 143 | } 144 | 145 | void connect_to_server_connect_fail_check(int32 expected_error, 146 | const char *error_name) 147 | { 148 | /* Arrange */ 149 | char p_e_s[50]; 150 | 151 | wrap_socket_return_value = rand() % INT_MAX; 152 | wrap_htons_return_value = 0; 153 | wrap_inet_pton_return_value = 1; 154 | wrap_connect_return_value = CONNECT_ERROR_VALUE; 155 | errno = expected_error; 156 | sprintf(p_e_s, "connect err = %s", error_name); 157 | log_message_expected_string = p_e_s; 158 | perror_expected_string = "connect_to_server connect error"; 159 | const char * dummyIp = NULL; 160 | uint16_t dummyPort = 0; 161 | 162 | /* Act */ 163 | int result = connect_to_server(dummyIp, dummyPort); 164 | 165 | /* Assert */ 166 | UtAssert_True(result == SERVER_CONNECT_ERROR, 167 | "error returned should have been %d and was %d", 168 | SERVER_CONNECT_ERROR, result); 169 | } 170 | 171 | /******************************************************************************* 172 | ** 173 | ** connect_to_server Tests 174 | ** 175 | *******************************************************************************/ 176 | 177 | void Test_connect_to_server_returns_sbn_client_sockfd_when_successful(void) 178 | { 179 | /* Arrange */ 180 | wrap_socket_return_value = rand() % INT_MAX; 181 | wrap_htons_return_value = 0; 182 | wrap_inet_pton_return_value = 1; 183 | wrap_connect_return_value = 0; 184 | const char * dummyIp = NULL; 185 | uint16_t dummyPort = 0; 186 | 187 | /* Act */ 188 | int result = connect_to_server(dummyIp, dummyPort); 189 | 190 | /* Assert */ 191 | UtAssert_True(result == wrap_socket_return_value, 192 | "Sockfd returned should have been %d and was %d", 193 | wrap_socket_return_value, result); 194 | } 195 | 196 | void Test_connect_to_server_Outlog_message_EACCES_WhenSocketFails(void) 197 | { 198 | connect_to_server_socket_fail_check(EACCES, "EACCES"); 199 | } 200 | 201 | void Test_connect_to_server_Outlog_message_EAFNOSUPPORT_WhenSocketFails(void) 202 | { 203 | connect_to_server_socket_fail_check(EAFNOSUPPORT, "EAFNOSUPPORT"); 204 | } 205 | 206 | void Test_connect_to_server_Outlog_message_EINVAL_WhenSocketFails(void) 207 | { 208 | connect_to_server_socket_fail_check(EINVAL, "EINVAL"); 209 | } 210 | 211 | void Test_connect_to_server_Outlog_message_EMFILE_WhenSocketFails(void) 212 | { 213 | connect_to_server_socket_fail_check(EMFILE, "EMFILE"); 214 | } 215 | 216 | void Test_connect_to_server_Outlog_message_ENOBUFS_WhenSocketFails(void) 217 | { 218 | connect_to_server_socket_fail_check(ENOBUFS, "ENOBUFS"); 219 | } 220 | 221 | void Test_connect_to_server_Outlog_message_ENOMEM_WhenSocketFails(void) 222 | { 223 | connect_to_server_socket_fail_check(ENOMEM, "ENOMEM"); 224 | } 225 | 226 | void Test_connect_to_server_Outlog_message_EPROTONOSUPPORT_WhenSocketFails(void) 227 | { 228 | connect_to_server_socket_fail_check(EPROTONOSUPPORT, "EPROTONOSUPPORT"); 229 | } 230 | 231 | void Test_connect_to_server_Outlog_messageUnknownErrorWhenNoCaseMatches(void) 232 | { 233 | /* Arrange */ 234 | wrap_socket_return_value = -1; 235 | errno = 0xFFFF; 236 | /* TODO: printf is being used not log_message, need a better way to check */ 237 | /* log_message_expected_string = "Unknown socket error = 65535"; */ 238 | perror_expected_string = "connect_to_server socket error"; 239 | const char * dummyIp = NULL; 240 | uint16_t dummyPort = 0; 241 | 242 | /* Act */ 243 | int result = connect_to_server(dummyIp, dummyPort); 244 | 245 | /* Assert */ 246 | UtAssert_True(result == SERVER_SOCKET_ERROR, 247 | "Error returned should have been %d and was %d", 248 | SERVER_SOCKET_ERROR, result); 249 | } 250 | 251 | void Test_connect_to_server_returns_error_when_inet_pton_src_is_invalid(void) 252 | { 253 | /* Arrange */ 254 | /* once inet_pton fails CUT returns error */ 255 | wrap_socket_return_value = rand() % INT_MAX; 256 | wrap_htons_return_value = 0; 257 | wrap_inet_pton_return_value = 0; 258 | errno = SERVER_INET_PTON_SRC_ERROR; 259 | const char * dummyIp = NULL; 260 | uint16_t dummyPort = 0; 261 | 262 | /* Act */ 263 | int result = connect_to_server(dummyIp, dummyPort); 264 | 265 | /* Assert */ 266 | UtAssert_True(result == SERVER_INET_PTON_SRC_ERROR, 267 | "Error returned should have been %d and was %d", 268 | SERVER_INET_PTON_SRC_ERROR, result); 269 | } 270 | 271 | void Test_connect_to_server_returns_error_when_inet_pton_af_is_invalid(void) 272 | { 273 | /* Arrange */ 274 | /* once inet_pton fails CUT returns error */ 275 | wrap_socket_return_value = rand() % INT_MAX; 276 | wrap_htons_return_value = 0; 277 | wrap_inet_pton_return_value = -1; 278 | errno = SERVER_INET_PTON_INVALID_AF_ERROR; 279 | const char * dummyIp = NULL; 280 | uint16_t dummyPort = 0; 281 | 282 | /* Act */ 283 | int result = connect_to_server(dummyIp, dummyPort); 284 | 285 | /* Assert */ 286 | UtAssert_True(result == SERVER_INET_PTON_INVALID_AF_ERROR, 287 | "Error returned should have been %d and was %d", 288 | SERVER_INET_PTON_INVALID_AF_ERROR, result); 289 | } 290 | 291 | void Test_connect_to_server_returns_error_WhenConnectFails(void) 292 | { 293 | /* Arrange */ 294 | wrap_socket_return_value = rand() % INT_MAX; 295 | wrap_htons_return_value = 0; 296 | wrap_inet_pton_return_value = 1; 297 | wrap_connect_return_value = CONNECT_ERROR_VALUE; 298 | errno = -4; 299 | const char * dummyIp = NULL; 300 | uint16_t dummyPort = 0; 301 | 302 | /* Act */ 303 | int result = connect_to_server(dummyIp, dummyPort); 304 | 305 | /* Assert */ 306 | UtAssert_True(result == errno, 307 | "error returned should have been %d and was %d", 308 | errno, result); 309 | } 310 | 311 | void Test_connect_to_server_Outlog_message_EACCES_errorFromConnectCall(void) 312 | { 313 | connect_to_server_connect_fail_check(EACCES, "EACCES"); 314 | } 315 | 316 | void Test_connect_to_server_Outlog_message_EPERM_errorFromConnectCall(void) 317 | { 318 | connect_to_server_connect_fail_check(EPERM, "EPERM"); 319 | } 320 | 321 | void Test_connect_to_server_Outlog_message_EADDRINUSE_errorFromConnectCall(void) 322 | { 323 | connect_to_server_connect_fail_check(EADDRINUSE, "EADDRINUSE"); 324 | } 325 | 326 | void Test_connect_to_server_Outlog_message_EADDRNOTAVAIL_errorFromConnectCall(void) 327 | { 328 | connect_to_server_connect_fail_check(EADDRNOTAVAIL, "EADDRNOTAVAIL"); 329 | } 330 | 331 | void Test_connect_to_server_Outlog_message_EAFNOSUPPORT_errorFromConnectCall(void) 332 | { 333 | connect_to_server_connect_fail_check(EAFNOSUPPORT, "EAFNOSUPPORT"); 334 | } 335 | 336 | void Test_connect_to_server_Outlog_message_EAGAIN_errorFromConnectCall(void) 337 | { 338 | connect_to_server_connect_fail_check(EAGAIN, "EAGAIN"); 339 | } 340 | 341 | void Test_connect_to_server_Outlog_message_EALREADY_errorFromConnectCall(void) 342 | { 343 | connect_to_server_connect_fail_check(EALREADY, "EALREADY"); 344 | } 345 | 346 | void Test_connect_to_server_Outlog_message_EBADF_errorFromConnectCall(void) 347 | { 348 | connect_to_server_connect_fail_check(EBADF, "EBADF"); 349 | } 350 | 351 | void Test_connect_to_server_Outlog_message_ECONNREFUSED_errorFromConnectCall(void) 352 | { 353 | connect_to_server_connect_fail_check(ECONNREFUSED, "ECONNREFUSED"); 354 | } 355 | 356 | void Test_connect_to_server_Outlog_message_EFAULT_errorFromConnectCall(void) 357 | { 358 | connect_to_server_connect_fail_check(EFAULT, "EFAULT"); 359 | } 360 | 361 | void Test_connect_to_server_Outlog_message_EINPROGRESS_errorFromConnectCall(void) 362 | { 363 | connect_to_server_connect_fail_check(EINPROGRESS, "EINPROGRESS"); 364 | } 365 | 366 | void Test_connect_to_server_Outlog_message_EINTR_errorFromConnectCall(void) 367 | { 368 | connect_to_server_connect_fail_check(EINTR, "EINTR"); 369 | } 370 | 371 | void Test_connect_to_server_Outlog_message_EISCONN_errorFromConnectCall(void) 372 | { 373 | connect_to_server_connect_fail_check(EISCONN, "EISCONN"); 374 | } 375 | 376 | void Test_connect_to_server_Outlog_message_ENETUNREACH_errorFromConnectCall(void) 377 | { 378 | connect_to_server_connect_fail_check(ENETUNREACH, "ENETUNREACH"); 379 | } 380 | 381 | void Test_connect_to_server_Outlog_message_ENOTSOCK_errorFromConnectCall(void) 382 | { 383 | connect_to_server_connect_fail_check(ENOTSOCK, "ENOTSOCK"); 384 | } 385 | 386 | void Test_connect_to_server_Outlog_message_EPROTOTYPE_errorFromConnectCall(void) 387 | { 388 | connect_to_server_connect_fail_check(EPROTOTYPE, "EPROTOTYPE"); 389 | } 390 | 391 | void Test_connect_to_server_Outlog_message_ETIMEDOUT_errorFromConnectCall(void) 392 | { 393 | connect_to_server_connect_fail_check(ETIMEDOUT, "ETIMEDOUT"); 394 | } 395 | /* end connect_to_server Tests */ 396 | 397 | /******************************************************************************* 398 | ** 399 | ** CFE_SBN_Client_GetPipeIdx Tests 400 | ** 401 | *******************************************************************************/ 402 | 403 | void Test_CFE_SBN_Client_GetPipeIdxSuccessPipeIdEqualsPipeIdx(void) 404 | { 405 | /* Arrange */ 406 | CFE_SB_PipeId_t pipe = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; 407 | PipeTbl[pipe].InUse = CFE_SBN_CLIENT_IN_USE; 408 | PipeTbl[pipe].PipeId = pipe; 409 | 410 | /* Act */ 411 | uint8 result = CFE_SBN_Client_GetPipeIdx(pipe); 412 | 413 | /* Assert */ 414 | UtAssert_True(result == pipe, 415 | "CFE_SBN_Client_GetPipeIdx should have returned %d and was %d", 416 | pipe, result); 417 | } 418 | 419 | /* NOTE:not sure if what happens in 420 | * Test_CFE_SBN_Client_GetPipeIdxSuccessPipeIdDoesNotEqualPipeIdx can really 421 | * ever occur during runtime */ 422 | void Test_CFE_SBN_Client_GetPipeIdxSuccessPipeIdDoesNotEqualPipeIdx(void) 423 | { 424 | /* Arrange */ 425 | CFE_SB_PipeId_t pipe = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; 426 | PipeTbl[pipe].InUse = CFE_SBN_CLIENT_NOT_IN_USE; 427 | PipeTbl[pipe].PipeId = CFE_SBN_CLIENT_INVALID_PIPE; 428 | uint8 tblIdx = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; 429 | 430 | while (tblIdx == pipe) // get a pipe that is not the same as index 431 | { 432 | tblIdx = rand() % CFE_PLATFORM_SBN_CLIENT_MAX_PIPES; 433 | } 434 | 435 | PipeTbl[tblIdx].InUse = CFE_SBN_CLIENT_IN_USE; 436 | PipeTbl[tblIdx].PipeId = pipe; 437 | 438 | /* Act */ 439 | uint8 result = CFE_SBN_Client_GetPipeIdx(pipe); 440 | 441 | /* Assert */ 442 | UtAssert_True(result == tblIdx, 443 | "CFE_SBN_Client_GetPipeIdx for pipeId %d should have been %d and was %d", 444 | pipe, tblIdx, result); 445 | } 446 | /* end CFE_SBN_Client_GetPipeIdx Tests */ 447 | 448 | 449 | 450 | /* CFE_SBN_CLIENT_ReadBytes Tests*/ 451 | void Test_CFE_SBN_CLIENT_ReadBytes_ReturnsErrorWhenPipeBroken(void) 452 | { 453 | /* Arrange */ 454 | int sock_fd = (rand() % 10) + 1; /* 1 to 10 */ 455 | size_t MsgSz = 8; /* TODO: random size generation? */ 456 | unsigned char msg_buffer[MsgSz]; 457 | wrap_read_return_value = -1; 458 | int result; 459 | 460 | /* Act */ 461 | result = CFE_SBN_CLIENT_ReadBytes(sock_fd, msg_buffer, MsgSz); 462 | 463 | /* Assert */ 464 | UtAssert_True(result == CFE_SBN_CLIENT_PIPE_BROKEN_ERR, 465 | "CFE_SBN_CLIENT_ReadBytes should return CFE_SBN_CLIENT_PIPE_BROKEN_ERR"); 466 | } /* end Test_CFE_SBN_CLIENT_ReadBytes_ReturnsErrorWhenPipeBroken */ 467 | 468 | void Test_CFE_SBN_CLIENT_ReadBytes_ReturnsErrorWhenPipeClosed(void) 469 | { 470 | /* Arrange */ 471 | int sock_fd = (rand() % 10) + 1; /* 1 to 10 */ 472 | size_t MsgSz = 8; /* TODO: random size generation? */ 473 | unsigned char msg_buffer[MsgSz]; 474 | wrap_read_return_value = 0; 475 | int result; 476 | 477 | /* Act */ 478 | result = CFE_SBN_CLIENT_ReadBytes(sock_fd, msg_buffer, MsgSz); 479 | 480 | /* Assert */ 481 | UtAssert_True(result == CFE_SBN_CLIENT_PIPE_CLOSED_ERR, 482 | "CFE_SBN_CLIENT_ReadBytes returned CFE_SBN_CLIENT_PIPE_CLOSED_ERR"); 483 | } 484 | 485 | void Test_CFE_SBN_CLIENT_ReadBytes_ReturnsCfeSuccessWhenAllBytesReceived(void) 486 | { 487 | /* Arrange */ 488 | int sock_fd = (rand() % 10) + 1; /* 1 to 10 */ 489 | size_t MsgSz = 8; /* TODO: random size generation? */ 490 | unsigned char msg_buffer[MsgSz]; 491 | wrap_read_return_value = 8; 492 | int result; 493 | 494 | /* Act */ 495 | result = CFE_SBN_CLIENT_ReadBytes(sock_fd, msg_buffer, MsgSz); 496 | 497 | /* Assert */ 498 | UtAssert_True(result == CFE_SUCCESS, 499 | "CFE_SBN_CLIENT_ReadBytes returned CFE_SUCCESS"); 500 | } 501 | /* end CFE_SBN_CLIENT_ReadBytes Tests*/ 502 | 503 | /*************************************************/ 504 | 505 | void Test_CFE_SBN_Client_GetMessageSubscribeIndex_FailsMaxMessagesHit(CFE_SB_PipeId_t PipeId) 506 | { 507 | /* Arrange */ 508 | CFE_SB_PipeId_t testPipeId = 0; 509 | int32 expectedResult = CFE_SBN_CLIENT_MAX_MSG_IDS_MET; 510 | int32 result; 511 | int i=0; 512 | 513 | for (i = 0; i < CFE_SBN_CLIENT_MAX_MSG_IDS_PER_PIPE; ++i) 514 | { 515 | PipeTbl[testPipeId].SubscribedMsgIds[i] = i + 1; 516 | } 517 | 518 | /* Act */ 519 | result = CFE_SBN_Client_GetMessageSubscribeIndex(testPipeId); 520 | 521 | /* Assert */ 522 | UtAssert_True(result == expectedResult, "Expected 0x%08X got 0x%08X", expectedResult, result); 523 | 524 | } 525 | 526 | void UtTest_Setup(void) 527 | { 528 | // UtGroupSetup_Add(Test_Group_Setup); 529 | // UtGroupTeardown_Add(Test_Group_Teardown); 530 | // 531 | /* check_pthread_create_status Tests */ 532 | UtTest_Add( 533 | Test_CFE_SBN_Client_GetMessageSubscribeIndex_FailsMaxMessagesHit, 534 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 535 | "Test_CFE_SBN_Client_GetMessageSubscribeIndex_FailsMaxMessagesHit"); 536 | 537 | UtTest_Add( 538 | Test_check_pthread_create_status_Outlog_messageErrorWhenStatusIs_EAGAIN, 539 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 540 | "Test_check_pthread_create_status_Outlog_messageErrorWhenStatusIs_EAGAIN"); 541 | UtTest_Add( 542 | Test_check_pthread_create_status_Outlog_messageErrorWhenStatusIs_EINVAL, 543 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 544 | "Test_check_pthread_create_status_Outlog_messageErrorWhenStatusIs_EINVAL"); 545 | UtTest_Add( 546 | Test_check_pthread_create_status_Outlog_messageErrorWhenStatusIs_EPERM, 547 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 548 | "Test_check_pthread_create_status_Outlog_messageErrorWhenStatusIs_EPERM"); 549 | UtTest_Add( 550 | Test_check_pthread_create_status_Is_errorId_WhenStatusIsNonZero, 551 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 552 | "Test_check_pthread_create_status_Is_errorId_WhenStatusIsNonZero"); 553 | UtTest_Add( 554 | Test_check_pthread_create_status_Is_SBN_CLIENT_SUCCESS_When0, 555 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 556 | "Test_check_pthread_create_status_Is_SBN_CLIENT_SUCCESS_When0"); 557 | 558 | /* connect_to_server Tests */ 559 | add_connect_to_server_tests(); 560 | 561 | /* CFE_SBN_Client_GetPipeIdx Tests */ 562 | UtTest_Add( 563 | Test_CFE_SBN_Client_GetPipeIdxSuccessPipeIdEqualsPipeIdx, 564 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 565 | "Test_CFE_SBN_Client_GetPipeIdxSuccessPipeIdEqualsPipeIdx"); 566 | UtTest_Add( 567 | Test_CFE_SBN_Client_GetPipeIdxSuccessPipeIdDoesNotEqualPipeIdx, 568 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 569 | "Test_CFE_SBN_Client_GetPipeIdxSuccessPipeIdDoesNotEqualPipeIdx"); 570 | 571 | /* CFE_SBN_CLIENT_ReadBytes Tests*/ 572 | UtTest_Add( 573 | Test_CFE_SBN_CLIENT_ReadBytes_ReturnsErrorWhenPipeBroken, 574 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 575 | "Test_CFE_SBN_CLIENT_ReadBytes_ReturnsErrorWhenPipeBroken"); 576 | UtTest_Add( 577 | Test_CFE_SBN_CLIENT_ReadBytes_ReturnsErrorWhenPipeClosed, 578 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 579 | "Test_CFE_SBN_CLIENT_ReadBytes_ReturnsErrorWhenPipeClosed"); 580 | UtTest_Add( 581 | Test_CFE_SBN_CLIENT_ReadBytes_ReturnsCfeSuccessWhenAllBytesReceived, 582 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 583 | "Test_CFE_SBN_CLIENT_ReadBytes_ReturnsCfeSuccessWhenAllBytesReceived"); 584 | 585 | } 586 | 587 | /* Helper Functions */ 588 | 589 | void add_connect_to_server_tests(void) 590 | { 591 | UtTest_Add( 592 | Test_connect_to_server_returns_sbn_client_sockfd_when_successful, 593 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 594 | "Test_connect_to_server_returns_sbn_client_sockfd_when_successful"); 595 | UtTest_Add( 596 | Test_connect_to_server_Outlog_message_EACCES_WhenSocketFails, 597 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 598 | "Test_connect_to_server_Outlog_message_EACCES_WhenSocketFails"); 599 | UtTest_Add( 600 | Test_connect_to_server_Outlog_message_EAFNOSUPPORT_WhenSocketFails, 601 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 602 | "Test_connect_to_server_Outlog_message_EAFNOSUPPORT_WhenSocketFails"); 603 | UtTest_Add( 604 | Test_connect_to_server_Outlog_message_EINVAL_WhenSocketFails, 605 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 606 | "Test_connect_to_server_Outlog_message_EINVAL_WhenSocketFails"); 607 | UtTest_Add( 608 | Test_connect_to_server_Outlog_message_EMFILE_WhenSocketFails, 609 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 610 | "Test_connect_to_server_Outlog_message_EMFILE_WhenSocketFails"); 611 | UtTest_Add( 612 | Test_connect_to_server_Outlog_message_ENOBUFS_WhenSocketFails, 613 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 614 | "Test_connect_to_server_Outlog_message_ENOBUFS_WhenSocketFails"); 615 | UtTest_Add( 616 | Test_connect_to_server_Outlog_message_ENOMEM_WhenSocketFails, 617 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 618 | "Test_connect_to_server_Outlog_message_ENOMEM_WhenSocketFails"); 619 | UtTest_Add( 620 | Test_connect_to_server_Outlog_message_EPROTONOSUPPORT_WhenSocketFails, 621 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 622 | "Test_connect_to_server_Outlog_message_EPROTONOSUPPORT_WhenSocketFails"); 623 | UtTest_Add( 624 | Test_connect_to_server_Outlog_messageUnknownErrorWhenNoCaseMatches, 625 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 626 | "Test_connect_to_server_Outlog_messageUnknownErrorWhenNoCaseMatches"); 627 | UtTest_Add( 628 | Test_connect_to_server_returns_error_when_inet_pton_src_is_invalid, 629 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 630 | "Test_connect_to_server_returns_error_when_inet_pton_src_is_invalid"); 631 | UtTest_Add( 632 | Test_connect_to_server_returns_error_when_inet_pton_af_is_invalid, 633 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 634 | "Test_connect_to_server_returns_error_when_inet_pton_af_is_invalid"); 635 | UtTest_Add( 636 | Test_connect_to_server_returns_error_WhenConnectFails, 637 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 638 | "Test_connect_to_server_returns_error_WhenConnectFails"); 639 | UtTest_Add( 640 | Test_connect_to_server_Outlog_message_EACCES_errorFromConnectCall, 641 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 642 | "Test_connect_to_server_Outlog_message_EACCES_errorFromConnectCall"); 643 | UtTest_Add( 644 | Test_connect_to_server_Outlog_message_EPERM_errorFromConnectCall, 645 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 646 | "Test_connect_to_server_Outlog_message_EPERM_errorFromConnectCall"); 647 | UtTest_Add( 648 | Test_connect_to_server_Outlog_message_EADDRINUSE_errorFromConnectCall, 649 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 650 | "Test_connect_to_server_Outlog_message_EADDRINUSE_errorFromConnectCall"); 651 | UtTest_Add( 652 | Test_connect_to_server_Outlog_message_EADDRNOTAVAIL_errorFromConnectCall, 653 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 654 | "Test_connect_to_server_Outlog_message_EADDRNOTAVAIL_errorFromConnectCall"); 655 | UtTest_Add( 656 | Test_connect_to_server_Outlog_message_EAFNOSUPPORT_errorFromConnectCall, 657 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 658 | "Test_connect_to_server_Outlog_message_EAFNOSUPPORT_errorFromConnectCall"); 659 | UtTest_Add( 660 | Test_connect_to_server_Outlog_message_EAGAIN_errorFromConnectCall, 661 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 662 | "Test_connect_to_server_Outlog_message_EAGAIN_errorFromConnectCall"); 663 | UtTest_Add( 664 | Test_connect_to_server_Outlog_message_EALREADY_errorFromConnectCall, 665 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 666 | "Test_connect_to_server_Outlog_message_EALREADY_errorFromConnectCall"); 667 | UtTest_Add( 668 | Test_connect_to_server_Outlog_message_EBADF_errorFromConnectCall, 669 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 670 | "Test_connect_to_server_Outlog_message_EBADF_errorFromConnectCall"); 671 | UtTest_Add( 672 | Test_connect_to_server_Outlog_message_ECONNREFUSED_errorFromConnectCall, 673 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 674 | "Test_connect_to_server_Outlog_message_ECONNREFUSED_errorFromConnectCall"); 675 | UtTest_Add( 676 | Test_connect_to_server_Outlog_message_EFAULT_errorFromConnectCall, 677 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 678 | "Test_connect_to_server_Outlog_message_EFAULT_errorFromConnectCall"); 679 | UtTest_Add( 680 | Test_connect_to_server_Outlog_message_EINPROGRESS_errorFromConnectCall, 681 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 682 | "Test_connect_to_server_Outlog_message_EINPROGRESS_errorFromConnectCall"); 683 | UtTest_Add( 684 | Test_connect_to_server_Outlog_message_EINTR_errorFromConnectCall, 685 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 686 | "Test_connect_to_server_Outlog_message_EINTR_errorFromConnectCall"); 687 | UtTest_Add( 688 | Test_connect_to_server_Outlog_message_EISCONN_errorFromConnectCall, 689 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 690 | "Test_connect_to_server_Outlog_message_EISCONN_errorFromConnectCall"); 691 | UtTest_Add( 692 | Test_connect_to_server_Outlog_message_ENETUNREACH_errorFromConnectCall, 693 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 694 | "Test_connect_to_server_Outlog_message_ENETUNREACH_errorFromConnectCall"); 695 | UtTest_Add( 696 | Test_connect_to_server_Outlog_message_ENOTSOCK_errorFromConnectCall, 697 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 698 | "Test_connect_to_server_Outlog_message_ENOTSOCK_errorFromConnectCall"); 699 | UtTest_Add( 700 | Test_connect_to_server_Outlog_message_EPROTOTYPE_errorFromConnectCall, 701 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 702 | "Test_connect_to_server_Outlog_message_EPROTOTYPE_errorFromConnectCall"); 703 | UtTest_Add( 704 | Test_connect_to_server_Outlog_message_ETIMEDOUT_errorFromConnectCall, 705 | SBN_Client_Utils_Tests_Setup, SBN_Client_Utils_Tests_Teardown, 706 | "Test_connect_to_server_Outlog_message_ETIMEDOUT_errorFromConnectCall"); 707 | } -------------------------------------------------------------------------------- /unit-test/stubs/sbn_client_logger_stubs.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include "sbn_client_logger_stubs.h" 14 | 15 | extern boolean continue_receive_check; 16 | extern const char *log_message_expected_string; 17 | extern boolean log_message_was_called; 18 | extern const char *perror_expected_string; 19 | 20 | extern void (*wrap_log_message_call_func)(void); 21 | 22 | int32 log_message(const char *format, ...) 23 | { 24 | 25 | log_message_was_called = TRUE; 26 | // 27 | // if (strlen(log_message_expected_string) > 0) 28 | // { 29 | // UtAssert_StrCmp(str, log_message_expected_string, 30 | // TestResultMsg("log_message expected string '%s' == '%s' string received", 31 | // log_message_expected_string, str)); 32 | // } 33 | // 34 | // if (wrap_log_message_call_func != NULL) 35 | // { 36 | // (*wrap_log_message_call_func)(); 37 | // } 38 | int result; 39 | int i = 0; 40 | int num_vars = 0; 41 | va_list vl; 42 | 43 | UT_Stub_CopyToLocal(UT_KEY(log_message), format, sizeof(format)); 44 | 45 | va_start(vl, format); 46 | while (format[i] && format[i+1]) 47 | { 48 | 49 | if (format[i] == '%') 50 | { 51 | num_vars++; 52 | UT_Stub_CopyToLocal(UT_KEY(log_message), va_arg(vl, int), sizeof(int)); 53 | } 54 | 55 | i++; 56 | } 57 | 58 | va_end(vl); 59 | 60 | // 61 | // 62 | // printf("PreCheck NUM_VARS = %d\n", num_vars); 63 | // 64 | // for(i = 0;format[i] != '\0';i++) 65 | // { 66 | // 67 | // if (format[i] == '%') 68 | // { 69 | // num_vars++; 70 | // } 71 | // 72 | // } 73 | // printf("PostCheck NUM_VARS = %d\n", num_vars); 74 | 75 | //result = __real_log_message(format, vl); 76 | 77 | return result; 78 | } 79 | 80 | 81 | -------------------------------------------------------------------------------- /unit-test/stubs/sbn_client_logger_stubs.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** GSC-18396-1, “Software Bus Network Client for External Process” 3 | ** 4 | ** Copyright © 2019 United States Government as represented by 5 | ** the Administrator of the National Aeronautics and Space Administration. 6 | ** No copyright is claimed in the United States under Title 17, U.S. Code. 7 | ** All Other Rights Reserved. 8 | ** 9 | ** Licensed under the NASA Open Source Agreement version 1.3 10 | ** See "NOSA GSC-18396-1.pdf" 11 | */ 12 | 13 | #include "sbn_client_logger.h" 14 | /* UT includes */ 15 | #include "uttest.h" 16 | #include "utassert.h" 17 | #include "utstubs.h" -------------------------------------------------------------------------------- /unwrap_symbols.txt: -------------------------------------------------------------------------------- 1 | __wrap_CFE_SB_DeletePipe CFE_SB_DeletePipe 2 | __wrap_CFE_SB_RcvMsg CFE_SB_RcvMsg 3 | __wrap_CFE_SB_SendMsg CFE_SB_SendMsg 4 | __wrap_CFE_SB_SubscribeEx CFE_SB_SubscribeEx 5 | __wrap_CFE_SB_Subscribe CFE_SB_Subscribe 6 | __wrap_CFE_SB_SubscribeLocal CFE_SB_SubscribeLocal 7 | __wrap_CFE_SB_Unsubscribe CFE_SB_Unsubscribe 8 | __wrap_CFE_SB_ZeroCopySend CFE_SB_ZeroCopySend 9 | __wrap_CFE_SB_CreatePipe CFE_SB_CreatePipe 10 | __wrap_CFE_SB_UnsubscribeLocal CFE_SB_UnsubscribeLocal 11 | --------------------------------------------------------------------------------