diff --git a/c/include/libsbp/cpp/message_traits.h b/c/include/libsbp/cpp/message_traits.h index d1f78a7009..23d5f72813 100644 --- a/c/include/libsbp/cpp/message_traits.h +++ b/c/include/libsbp/cpp/message_traits.h @@ -5357,6 +5357,118 @@ struct MessageTraits { } }; +template <> +struct MessageTraits { + static constexpr sbp_msg_type_t id = SbpMsgProfilingResourceCounter; + static constexpr const char *name = "MSG_PROFILING_RESOURCE_COUNTER"; + static const sbp_msg_profiling_resource_counter_t &get(const sbp_msg_t &msg) { + return msg.profiling_resource_counter; + } + static sbp_msg_profiling_resource_counter_t &get(sbp_msg_t &msg) { + return msg.profiling_resource_counter; + } + static void to_sbp_msg(const sbp_msg_profiling_resource_counter_t &msg, + sbp_msg_t *sbp_msg) { + sbp_msg->profiling_resource_counter = msg; + } + static sbp_msg_t to_sbp_msg(const sbp_msg_profiling_resource_counter_t &msg) { + sbp_msg_t sbp_msg; + sbp_msg.profiling_resource_counter = msg; + return sbp_msg; + } + static s8 send(sbp_state_t *state, u16 sender_id, + const sbp_msg_profiling_resource_counter_t &msg, + sbp_write_fn_t write) { + return sbp_msg_profiling_resource_counter_send(state, sender_id, &msg, + write); + } + static s8 encode(uint8_t *buf, uint8_t len, uint8_t *n_written, + const sbp_msg_profiling_resource_counter_t &msg) { + return sbp_msg_profiling_resource_counter_encode(buf, len, n_written, &msg); + } + static s8 decode(const uint8_t *buf, uint8_t len, uint8_t *n_read, + sbp_msg_profiling_resource_counter_t *msg) { + return sbp_msg_profiling_resource_counter_decode(buf, len, n_read, msg); + } + static size_t encoded_len(const sbp_msg_profiling_resource_counter_t &msg) { + return sbp_msg_profiling_resource_counter_encoded_len(&msg); + } +}; + +template <> +struct MessageTraits { + static constexpr sbp_msg_type_t id = SbpMsgProfilingSystemInfo; + static constexpr const char *name = "MSG_PROFILING_SYSTEM_INFO"; + static const sbp_msg_profiling_system_info_t &get(const sbp_msg_t &msg) { + return msg.profiling_system_info; + } + static sbp_msg_profiling_system_info_t &get(sbp_msg_t &msg) { + return msg.profiling_system_info; + } + static void to_sbp_msg(const sbp_msg_profiling_system_info_t &msg, + sbp_msg_t *sbp_msg) { + sbp_msg->profiling_system_info = msg; + } + static sbp_msg_t to_sbp_msg(const sbp_msg_profiling_system_info_t &msg) { + sbp_msg_t sbp_msg; + sbp_msg.profiling_system_info = msg; + return sbp_msg; + } + static s8 send(sbp_state_t *state, u16 sender_id, + const sbp_msg_profiling_system_info_t &msg, + sbp_write_fn_t write) { + return sbp_msg_profiling_system_info_send(state, sender_id, &msg, write); + } + static s8 encode(uint8_t *buf, uint8_t len, uint8_t *n_written, + const sbp_msg_profiling_system_info_t &msg) { + return sbp_msg_profiling_system_info_encode(buf, len, n_written, &msg); + } + static s8 decode(const uint8_t *buf, uint8_t len, uint8_t *n_read, + sbp_msg_profiling_system_info_t *msg) { + return sbp_msg_profiling_system_info_decode(buf, len, n_read, msg); + } + static size_t encoded_len(const sbp_msg_profiling_system_info_t &msg) { + return sbp_msg_profiling_system_info_encoded_len(&msg); + } +}; + +template <> +struct MessageTraits { + static constexpr sbp_msg_type_t id = SbpMsgProfilingThreadInfo; + static constexpr const char *name = "MSG_PROFILING_THREAD_INFO"; + static const sbp_msg_profiling_thread_info_t &get(const sbp_msg_t &msg) { + return msg.profiling_thread_info; + } + static sbp_msg_profiling_thread_info_t &get(sbp_msg_t &msg) { + return msg.profiling_thread_info; + } + static void to_sbp_msg(const sbp_msg_profiling_thread_info_t &msg, + sbp_msg_t *sbp_msg) { + sbp_msg->profiling_thread_info = msg; + } + static sbp_msg_t to_sbp_msg(const sbp_msg_profiling_thread_info_t &msg) { + sbp_msg_t sbp_msg; + sbp_msg.profiling_thread_info = msg; + return sbp_msg; + } + static s8 send(sbp_state_t *state, u16 sender_id, + const sbp_msg_profiling_thread_info_t &msg, + sbp_write_fn_t write) { + return sbp_msg_profiling_thread_info_send(state, sender_id, &msg, write); + } + static s8 encode(uint8_t *buf, uint8_t len, uint8_t *n_written, + const sbp_msg_profiling_thread_info_t &msg) { + return sbp_msg_profiling_thread_info_encode(buf, len, n_written, &msg); + } + static s8 decode(const uint8_t *buf, uint8_t len, uint8_t *n_read, + sbp_msg_profiling_thread_info_t *msg) { + return sbp_msg_profiling_thread_info_decode(buf, len, n_read, msg); + } + static size_t encoded_len(const sbp_msg_profiling_thread_info_t &msg) { + return sbp_msg_profiling_thread_info_encoded_len(&msg); + } +}; + template <> struct MessageTraits { static constexpr sbp_msg_type_t id = SbpMsgProtectionLevelDepA; diff --git a/c/include/libsbp/profiling.h b/c/include/libsbp/profiling.h index 22c913acf7..3062c2c633 100644 --- a/c/include/libsbp/profiling.h +++ b/c/include/libsbp/profiling.h @@ -18,5 +18,9 @@ #ifndef LIBSBP_PROFILING_MESSAGES_H #define LIBSBP_PROFILING_MESSAGES_H #include +#include +#include +#include +#include #endif /* LIBSBP_PROFILING_MESSAGES_H */ diff --git a/c/include/libsbp/profiling/MSG_PROFILING_RESOURCE_COUNTER.h b/c/include/libsbp/profiling/MSG_PROFILING_RESOURCE_COUNTER.h new file mode 100644 index 0000000000..b6912588df --- /dev/null +++ b/c/include/libsbp/profiling/MSG_PROFILING_RESOURCE_COUNTER.h @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2015-2021 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +/***************************************************************************** + * Automatically generated from yaml/swiftnav/sbp/profiling.yaml + * with generate.py. Please do not hand edit! + *****************************************************************************/ + +#ifndef LIBSBP_PROFILING_MSG_PROFILING_RESOURCE_COUNTER_H +#define LIBSBP_PROFILING_MSG_PROFILING_RESOURCE_COUNTER_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * + * SBP_MSG_PROFILING_RESOURCE_COUNTER + * + *****************************************************************************/ +/** Information about resource buckets + * + * Information about resource buckets. Refer to product documentation to + * understand the meaning and values in this message. + */ +typedef struct { + /** + * Message number in complete sequence + */ + u8 seq_no; + + /** + * Length of message sequence + */ + u8 seq_len; + + /** + * List of resource buckets + */ + sbp_resource_bucket_t buckets[SBP_MSG_PROFILING_RESOURCE_COUNTER_BUCKETS_MAX]; + /** + * Number of elements in buckets + * + * When sending a message fill in this field with the number elements set in + * buckets before calling an appropriate libsbp send function + * + * When receiving a message query this field for the number of elements in + * buckets. The value of any elements beyond the index specified in this field + * is undefined + */ + u8 n_buckets; +} sbp_msg_profiling_resource_counter_t; + +/** + * Get encoded size of an instance of sbp_msg_profiling_resource_counter_t + * + * @param msg sbp_msg_profiling_resource_counter_t instance + * @return Length of on-wire representation + */ +static inline size_t sbp_msg_profiling_resource_counter_encoded_len( + const sbp_msg_profiling_resource_counter_t *msg) { + return SBP_MSG_PROFILING_RESOURCE_COUNTER_ENCODED_OVERHEAD + + (msg->n_buckets * SBP_RESOURCE_BUCKET_ENCODED_LEN); +} + +/** + * Encode an instance of sbp_msg_profiling_resource_counter_t to wire + * representation + * + * This function encodes the given instance in to the user provided buffer. The + * buffer provided to this function must be large enough to store the encoded + * message otherwise it will return SBP_ENCODE_ERROR without writing anything to + * the buffer. + * + * Specify the length of the destination buffer in the \p len parameter. If + * non-null the number of bytes written to the buffer will be returned in \p + * n_written. + * + * @param buf Destination buffer + * @param len Length of \p buf + * @param n_written If not null, on success will be set to the number of bytes + * written to \p buf + * @param msg Instance of sbp_msg_profiling_resource_counter_t to encode + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 sbp_msg_profiling_resource_counter_encode( + uint8_t *buf, uint8_t len, uint8_t *n_written, + const sbp_msg_profiling_resource_counter_t *msg); + +/** + * Decode an instance of sbp_msg_profiling_resource_counter_t from wire + * representation + * + * This function decodes the wire representation of a + * sbp_msg_profiling_resource_counter_t message to the given instance. The + * caller must specify the length of the buffer in the \p len parameter. If + * non-null the number of bytes read from the buffer will be returned in \p + * n_read. + * + * @param buf Wire representation of the sbp_msg_profiling_resource_counter_t + * instance + * @param len Length of \p buf + * @param n_read If not null, on success will be set to the number of bytes read + * from \p buf + * @param msg Destination + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 sbp_msg_profiling_resource_counter_decode( + const uint8_t *buf, uint8_t len, uint8_t *n_read, + sbp_msg_profiling_resource_counter_t *msg); +/** + * Send an instance of sbp_msg_profiling_resource_counter_t with the given write + * function + * + * An equivalent of #sbp_message_send which operates specifically on + * sbp_msg_profiling_resource_counter_t + * + * The given message will be encoded to wire representation and passed in to the + * given write function callback. The write callback will be called several + * times for each invocation of this function. + * + * @param s SBP state + * @param sender_id SBP sender id + * @param msg Message to send + * @param write Write function + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 sbp_msg_profiling_resource_counter_send( + sbp_state_t *s, u16 sender_id, + const sbp_msg_profiling_resource_counter_t *msg, sbp_write_fn_t write); + +/** + * Compare two instances of sbp_msg_profiling_resource_counter_t + * + * The two instances will be compared and a value returned consistent with the + * return codes of comparison functions from the C standard library + * + * 0 will be returned if \p a and \p b are considered equal + * A value less than 0 will be returned if \p a is considered to be less than \p + * b A value greater than 0 will be returned if \p b is considered to be greater + * than \p b + * + * @param a sbp_msg_profiling_resource_counter_t instance + * @param b sbp_msg_profiling_resource_counter_t instance + * @return 0, <0, >0 + */ +SBP_EXPORT int sbp_msg_profiling_resource_counter_cmp( + const sbp_msg_profiling_resource_counter_t *a, + const sbp_msg_profiling_resource_counter_t *b); + +#ifdef __cplusplus +} + +static inline bool operator==(const sbp_msg_profiling_resource_counter_t &lhs, + const sbp_msg_profiling_resource_counter_t &rhs) { + return sbp_msg_profiling_resource_counter_cmp(&lhs, &rhs) == 0; +} + +static inline bool operator!=(const sbp_msg_profiling_resource_counter_t &lhs, + const sbp_msg_profiling_resource_counter_t &rhs) { + return sbp_msg_profiling_resource_counter_cmp(&lhs, &rhs) != 0; +} + +static inline bool operator<(const sbp_msg_profiling_resource_counter_t &lhs, + const sbp_msg_profiling_resource_counter_t &rhs) { + return sbp_msg_profiling_resource_counter_cmp(&lhs, &rhs) < 0; +} + +static inline bool operator<=(const sbp_msg_profiling_resource_counter_t &lhs, + const sbp_msg_profiling_resource_counter_t &rhs) { + return sbp_msg_profiling_resource_counter_cmp(&lhs, &rhs) <= 0; +} + +static inline bool operator>(const sbp_msg_profiling_resource_counter_t &lhs, + const sbp_msg_profiling_resource_counter_t &rhs) { + return sbp_msg_profiling_resource_counter_cmp(&lhs, &rhs) > 0; +} + +static inline bool operator>=(const sbp_msg_profiling_resource_counter_t &lhs, + const sbp_msg_profiling_resource_counter_t &rhs) { + return sbp_msg_profiling_resource_counter_cmp(&lhs, &rhs) >= 0; +} + +#endif // ifdef __cplusplus + +#endif /* LIBSBP_PROFILING_MSG_PROFILING_RESOURCE_COUNTER_H */ diff --git a/c/include/libsbp/profiling/MSG_PROFILING_SYSTEM_INFO.h b/c/include/libsbp/profiling/MSG_PROFILING_SYSTEM_INFO.h new file mode 100644 index 0000000000..bf44cbe8b2 --- /dev/null +++ b/c/include/libsbp/profiling/MSG_PROFILING_SYSTEM_INFO.h @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2015-2021 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +/***************************************************************************** + * Automatically generated from yaml/swiftnav/sbp/profiling.yaml + * with generate.py. Please do not hand edit! + *****************************************************************************/ + +#ifndef LIBSBP_PROFILING_MSG_PROFILING_SYSTEM_INFO_H +#define LIBSBP_PROFILING_MSG_PROFILING_SYSTEM_INFO_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * + * SBP_MSG_PROFILING_SYSTEM_INFO + * + *****************************************************************************/ +/** System Profiling Information + * + * Contains basic information about system resource usage. System is defined in + * terms of the source of this message and may vary from sender to sender. + * Refer to product documentation to understand the exact scope and meaning of + * this message. + */ +typedef struct { + /** + * Total cpu time in microseconds consumed by this system + */ + u64 total_cpu_time; + + /** + * Age of the producing system in microseconds + */ + u64 age; + + /** + * Number of threads being tracked by this system + */ + u8 n_threads; + + /** + * Number of bytes allocated on the heap + */ + u32 heap_usage; +} sbp_msg_profiling_system_info_t; + +/** + * Get encoded size of an instance of sbp_msg_profiling_system_info_t + * + * @param msg sbp_msg_profiling_system_info_t instance + * @return Length of on-wire representation + */ +static inline size_t sbp_msg_profiling_system_info_encoded_len( + const sbp_msg_profiling_system_info_t *msg) { + (void)msg; + return SBP_MSG_PROFILING_SYSTEM_INFO_ENCODED_LEN; +} + +/** + * Encode an instance of sbp_msg_profiling_system_info_t to wire representation + * + * This function encodes the given instance in to the user provided buffer. The + * buffer provided to this function must be large enough to store the encoded + * message otherwise it will return SBP_ENCODE_ERROR without writing anything to + * the buffer. + * + * Specify the length of the destination buffer in the \p len parameter. If + * non-null the number of bytes written to the buffer will be returned in \p + * n_written. + * + * @param buf Destination buffer + * @param len Length of \p buf + * @param n_written If not null, on success will be set to the number of bytes + * written to \p buf + * @param msg Instance of sbp_msg_profiling_system_info_t to encode + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 sbp_msg_profiling_system_info_encode( + uint8_t *buf, uint8_t len, uint8_t *n_written, + const sbp_msg_profiling_system_info_t *msg); + +/** + * Decode an instance of sbp_msg_profiling_system_info_t from wire + * representation + * + * This function decodes the wire representation of a + * sbp_msg_profiling_system_info_t message to the given instance. The caller + * must specify the length of the buffer in the \p len parameter. If non-null + * the number of bytes read from the buffer will be returned in \p n_read. + * + * @param buf Wire representation of the sbp_msg_profiling_system_info_t + * instance + * @param len Length of \p buf + * @param n_read If not null, on success will be set to the number of bytes read + * from \p buf + * @param msg Destination + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 sbp_msg_profiling_system_info_decode( + const uint8_t *buf, uint8_t len, uint8_t *n_read, + sbp_msg_profiling_system_info_t *msg); +/** + * Send an instance of sbp_msg_profiling_system_info_t with the given write + * function + * + * An equivalent of #sbp_message_send which operates specifically on + * sbp_msg_profiling_system_info_t + * + * The given message will be encoded to wire representation and passed in to the + * given write function callback. The write callback will be called several + * times for each invocation of this function. + * + * @param s SBP state + * @param sender_id SBP sender id + * @param msg Message to send + * @param write Write function + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 sbp_msg_profiling_system_info_send( + sbp_state_t *s, u16 sender_id, const sbp_msg_profiling_system_info_t *msg, + sbp_write_fn_t write); + +/** + * Compare two instances of sbp_msg_profiling_system_info_t + * + * The two instances will be compared and a value returned consistent with the + * return codes of comparison functions from the C standard library + * + * 0 will be returned if \p a and \p b are considered equal + * A value less than 0 will be returned if \p a is considered to be less than \p + * b A value greater than 0 will be returned if \p b is considered to be greater + * than \p b + * + * @param a sbp_msg_profiling_system_info_t instance + * @param b sbp_msg_profiling_system_info_t instance + * @return 0, <0, >0 + */ +SBP_EXPORT int sbp_msg_profiling_system_info_cmp( + const sbp_msg_profiling_system_info_t *a, + const sbp_msg_profiling_system_info_t *b); + +#ifdef __cplusplus +} + +static inline bool operator==(const sbp_msg_profiling_system_info_t &lhs, + const sbp_msg_profiling_system_info_t &rhs) { + return sbp_msg_profiling_system_info_cmp(&lhs, &rhs) == 0; +} + +static inline bool operator!=(const sbp_msg_profiling_system_info_t &lhs, + const sbp_msg_profiling_system_info_t &rhs) { + return sbp_msg_profiling_system_info_cmp(&lhs, &rhs) != 0; +} + +static inline bool operator<(const sbp_msg_profiling_system_info_t &lhs, + const sbp_msg_profiling_system_info_t &rhs) { + return sbp_msg_profiling_system_info_cmp(&lhs, &rhs) < 0; +} + +static inline bool operator<=(const sbp_msg_profiling_system_info_t &lhs, + const sbp_msg_profiling_system_info_t &rhs) { + return sbp_msg_profiling_system_info_cmp(&lhs, &rhs) <= 0; +} + +static inline bool operator>(const sbp_msg_profiling_system_info_t &lhs, + const sbp_msg_profiling_system_info_t &rhs) { + return sbp_msg_profiling_system_info_cmp(&lhs, &rhs) > 0; +} + +static inline bool operator>=(const sbp_msg_profiling_system_info_t &lhs, + const sbp_msg_profiling_system_info_t &rhs) { + return sbp_msg_profiling_system_info_cmp(&lhs, &rhs) >= 0; +} + +#endif // ifdef __cplusplus + +#endif /* LIBSBP_PROFILING_MSG_PROFILING_SYSTEM_INFO_H */ diff --git a/c/include/libsbp/profiling/MSG_PROFILING_THREAD_INFO.h b/c/include/libsbp/profiling/MSG_PROFILING_THREAD_INFO.h new file mode 100644 index 0000000000..451601ef3e --- /dev/null +++ b/c/include/libsbp/profiling/MSG_PROFILING_THREAD_INFO.h @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2015-2021 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +/***************************************************************************** + * Automatically generated from yaml/swiftnav/sbp/profiling.yaml + * with generate.py. Please do not hand edit! + *****************************************************************************/ + +#ifndef LIBSBP_PROFILING_MSG_PROFILING_THREAD_INFO_H +#define LIBSBP_PROFILING_MSG_PROFILING_THREAD_INFO_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * + * SBP_MSG_PROFILING_THREAD_INFO + * + *****************************************************************************/ +/** Thread Profiling Information + * + * Contains profiling information related to a single thread being tracked by + * the producing system. Refer to product documentation to understand the exact + * scope and meaning of this message. + */ +typedef struct { + /** + * Total cpu time in microseconds consumed by this thread + */ + u64 total_cpu_time; + + /** + * Age of the thread in microseconds + */ + u64 age; + + /** + * Thread state + */ + u8 state; + + /** + * Stack size in bytes + */ + u32 stack_size; + + /** + * Stack highwater usage in bytes + */ + u32 stack_usage; + + /** + * Thread name + */ + sbp_string_t name; +} sbp_msg_profiling_thread_info_t; + +/** + * Initialise sbp_msg_profiling_thread_info_t::name to empty + * + * @param msg sbp_msg_profiling_thread_info_t instance + */ +SBP_EXPORT void sbp_msg_profiling_thread_info_name_init( + sbp_msg_profiling_thread_info_t *msg); + +/** + * Test sbp_msg_profiling_thread_info_t::name for validity + * + * @param msg sbp_msg_profiling_thread_info_t instance + * @return true is sbp_msg_profiling_thread_info_t::name is valid for encoding + * purposes, false otherwise + */ +SBP_EXPORT bool sbp_msg_profiling_thread_info_name_valid( + const sbp_msg_profiling_thread_info_t *msg); + +/** + * Tests 2 instances of sbp_msg_profiling_thread_info_t::name for equality + * + * Returns a value with the same definitions as strcmp from the C standard + * library + * + * @param a sbp_msg_profiling_thread_info_t instance + * @param b sbp_msg_profiling_thread_info_t instance + * @return 0 if equal, <0 if a0 if a>b + */ +SBP_EXPORT int sbp_msg_profiling_thread_info_name_strcmp( + const sbp_msg_profiling_thread_info_t *a, + const sbp_msg_profiling_thread_info_t *b); + +/** + * Get the encoded size of sbp_msg_profiling_thread_info_t::name + * + * @param msg sbp_msg_profiling_thread_info_t instance + * @return Size of sbp_msg_profiling_thread_info_t::name in wire representation + */ +SBP_EXPORT size_t sbp_msg_profiling_thread_info_name_encoded_len( + const sbp_msg_profiling_thread_info_t *msg); + +/** + * Query sbp_msg_profiling_thread_info_t::name for remaining space + * + * Returns the number of bytes (not including NULL terminator) which can be + * added to sbp_msg_profiling_thread_info_t::name before it exceeds the maximum + * size of the field in wire representation + * + * @param msg sbp_msg_profiling_thread_info_t instance + * @return Maximum number of bytes that can be appended to the existing string + */ +SBP_EXPORT size_t sbp_msg_profiling_thread_info_name_space_remaining( + const sbp_msg_profiling_thread_info_t *msg); +/** + * Set sbp_msg_profiling_thread_info_t::name + * + * Erase any existing content and replace with the specified string + * + * If the should_trunc parameter is set to false and the specified string is + * longer than can be represented in wire encoding, this function will return + * false. Otherwise, if should_trunc is set to true, then as much as possible + * will be read from the new_str as can fit in the msg. + * + * @param msg sbp_msg_profiling_thread_info_t instance + * @param new_str New string + * @param should_trunc Whether the new_str can be truncated to fit in msg + * @param n_written If not null, on success will be set to the number of bytes + * written to msg + * @return true on success, false otherwise + */ +SBP_EXPORT bool sbp_msg_profiling_thread_info_name_set( + sbp_msg_profiling_thread_info_t *msg, const char *new_str, + bool should_trunc, size_t *n_written); + +/** + * Set sbp_msg_profiling_thread_info_t::name from a raw buffer + * + * Erase any existing content and replace with the specified raw buffer + * + * If the should_trunc parameter is set to false and the specified string is + * longer than can be represented in wire encoding, this function will return + * false. Otherwise, if should_trunc is set to true, then as much as possible + * will be read from the new_str as can fit in the msg. + * + * @param msg sbp_msg_profiling_thread_info_t instance + * @param new_buf New buffer + * @param new_buf_len New buffer length + * @param should_trunc Whether the new_str can be truncated to fit in msg + * @param n_written If not null, on success will be set to the number of bytes + * written to msg + * @return true on success, false otherwise + */ +SBP_EXPORT bool sbp_msg_profiling_thread_info_name_set_raw( + sbp_msg_profiling_thread_info_t *msg, const char *new_buf, + size_t new_buf_len, bool should_trunc, size_t *n_written); + +/** + * Set sbp_msg_profiling_thread_info_t::name with printf style formatting + * + * Erase any existing content and replace with the formatted string + * + * This function will return true if the new string was successfully applied. + * If should_trunc is set false, and the operation would end up overflowing the + * maximum size of this field in wire encoding the existing contents will be + * erased and this function will return false. Otherwise, if should_trunc is + * set true, the input formatted string will be truncated to fit. + * + * @param msg sbp_msg_profiling_thread_info_t instance + * @param should_trunc Whether the input string should be truncated to fit + * @param n_written If not null, on success will be set to the number of bytes + * written to msg + * @param fmt printf style format string + * @return true on success, false otherwise + */ +SBP_EXPORT bool sbp_msg_profiling_thread_info_name_printf( + sbp_msg_profiling_thread_info_t *msg, bool should_trunc, size_t *n_written, + const char *fmt, ...) SBP_ATTR_FORMAT(4, 5); + +/** + * Set sbp_msg_profiling_thread_info_t::name with printf style formatting + * + * Identical to #sbp_msg_profiling_thread_info_name_printf except it takes a + * va_list argument + * + * @param msg sbp_msg_profiling_thread_info_t instance + * @param should_trunc Whether the input string should be truncated to fit + * @param n_written If not null, on success will be set to the number of bytes + * written to msg + * @param fmt printf style format string + * @param ap Argument list + * @return true on success, false otherwise + */ +SBP_EXPORT bool sbp_msg_profiling_thread_info_name_vprintf( + sbp_msg_profiling_thread_info_t *msg, bool should_trunc, size_t *n_written, + const char *fmt, va_list ap) SBP_ATTR_VFORMAT(4); + +/** + * Append sbp_msg_profiling_thread_info_t::name with printf style formatting + * + * The new string will be appended to the existing contents of the string (if + * any). If should_trunc is false and the operation would end up overflowing + * the maximum size of this field in wire encoding, the existing contents will + * be unmodified and this function will return false. Otherwise, if + * should_trunc is true, the input string will be truncated to fit. + * + * @param msg sbp_msg_profiling_thread_info_t instance + * @param should_trunc Whether the input string should be truncated to fit + * @param n_written If not null, on success will be set to the number of bytes + * written to msg + * @param fmt printf style format string + * @return true on success, false otherwise + */ +SBP_EXPORT bool sbp_msg_profiling_thread_info_name_append_printf( + sbp_msg_profiling_thread_info_t *msg, bool should_trunc, size_t *n_written, + const char *fmt, ...) SBP_ATTR_FORMAT(4, 5); + +/** + * Append sbp_msg_profiling_thread_info_t::name with printf style formatting + * + * Identical to #sbp_msg_profiling_thread_info_name_append_printf except it + * takes a va_list argument + * + * @param msg sbp_msg_profiling_thread_info_t instance + * @param should_trunc Whether the input string should be truncated to fit + * @param n_written If not null, on success will be set to the number of bytes + * written to msg + * @param fmt printf style format string + * @param ap Argument list + * @return true on success, false otherwise + */ +SBP_EXPORT bool sbp_msg_profiling_thread_info_name_append_vprintf( + sbp_msg_profiling_thread_info_t *msg, bool should_trunc, size_t *n_written, + const char *fmt, va_list ap) SBP_ATTR_VFORMAT(4); + +/** + * Obtain the string value from sbp_msg_profiling_thread_info_t::name + * + * @param msg sbp_msg_profiling_thread_info_t instance + * @return String contents + */ +SBP_EXPORT const char *sbp_msg_profiling_thread_info_name_get( + const sbp_msg_profiling_thread_info_t *msg); + +/** + * Obtain the length of sbp_msg_profiling_thread_info_t::name + * + * The returned value does not include the NULL terminator. + * + * @param msg sbp_msg_profiling_thread_info_t instance + * @return Length of string + */ +SBP_EXPORT size_t sbp_msg_profiling_thread_info_name_strlen( + const sbp_msg_profiling_thread_info_t *msg); + +/** + * Get encoded size of an instance of sbp_msg_profiling_thread_info_t + * + * @param msg sbp_msg_profiling_thread_info_t instance + * @return Length of on-wire representation + */ +static inline size_t sbp_msg_profiling_thread_info_encoded_len( + const sbp_msg_profiling_thread_info_t *msg) { + return SBP_MSG_PROFILING_THREAD_INFO_ENCODED_OVERHEAD + + sbp_msg_profiling_thread_info_name_encoded_len(msg); +} + +/** + * Encode an instance of sbp_msg_profiling_thread_info_t to wire representation + * + * This function encodes the given instance in to the user provided buffer. The + * buffer provided to this function must be large enough to store the encoded + * message otherwise it will return SBP_ENCODE_ERROR without writing anything to + * the buffer. + * + * Specify the length of the destination buffer in the \p len parameter. If + * non-null the number of bytes written to the buffer will be returned in \p + * n_written. + * + * @param buf Destination buffer + * @param len Length of \p buf + * @param n_written If not null, on success will be set to the number of bytes + * written to \p buf + * @param msg Instance of sbp_msg_profiling_thread_info_t to encode + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 sbp_msg_profiling_thread_info_encode( + uint8_t *buf, uint8_t len, uint8_t *n_written, + const sbp_msg_profiling_thread_info_t *msg); + +/** + * Decode an instance of sbp_msg_profiling_thread_info_t from wire + * representation + * + * This function decodes the wire representation of a + * sbp_msg_profiling_thread_info_t message to the given instance. The caller + * must specify the length of the buffer in the \p len parameter. If non-null + * the number of bytes read from the buffer will be returned in \p n_read. + * + * @param buf Wire representation of the sbp_msg_profiling_thread_info_t + * instance + * @param len Length of \p buf + * @param n_read If not null, on success will be set to the number of bytes read + * from \p buf + * @param msg Destination + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 sbp_msg_profiling_thread_info_decode( + const uint8_t *buf, uint8_t len, uint8_t *n_read, + sbp_msg_profiling_thread_info_t *msg); +/** + * Send an instance of sbp_msg_profiling_thread_info_t with the given write + * function + * + * An equivalent of #sbp_message_send which operates specifically on + * sbp_msg_profiling_thread_info_t + * + * The given message will be encoded to wire representation and passed in to the + * given write function callback. The write callback will be called several + * times for each invocation of this function. + * + * @param s SBP state + * @param sender_id SBP sender id + * @param msg Message to send + * @param write Write function + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 sbp_msg_profiling_thread_info_send( + sbp_state_t *s, u16 sender_id, const sbp_msg_profiling_thread_info_t *msg, + sbp_write_fn_t write); + +/** + * Compare two instances of sbp_msg_profiling_thread_info_t + * + * The two instances will be compared and a value returned consistent with the + * return codes of comparison functions from the C standard library + * + * 0 will be returned if \p a and \p b are considered equal + * A value less than 0 will be returned if \p a is considered to be less than \p + * b A value greater than 0 will be returned if \p b is considered to be greater + * than \p b + * + * @param a sbp_msg_profiling_thread_info_t instance + * @param b sbp_msg_profiling_thread_info_t instance + * @return 0, <0, >0 + */ +SBP_EXPORT int sbp_msg_profiling_thread_info_cmp( + const sbp_msg_profiling_thread_info_t *a, + const sbp_msg_profiling_thread_info_t *b); + +#ifdef __cplusplus +} + +static inline bool operator==(const sbp_msg_profiling_thread_info_t &lhs, + const sbp_msg_profiling_thread_info_t &rhs) { + return sbp_msg_profiling_thread_info_cmp(&lhs, &rhs) == 0; +} + +static inline bool operator!=(const sbp_msg_profiling_thread_info_t &lhs, + const sbp_msg_profiling_thread_info_t &rhs) { + return sbp_msg_profiling_thread_info_cmp(&lhs, &rhs) != 0; +} + +static inline bool operator<(const sbp_msg_profiling_thread_info_t &lhs, + const sbp_msg_profiling_thread_info_t &rhs) { + return sbp_msg_profiling_thread_info_cmp(&lhs, &rhs) < 0; +} + +static inline bool operator<=(const sbp_msg_profiling_thread_info_t &lhs, + const sbp_msg_profiling_thread_info_t &rhs) { + return sbp_msg_profiling_thread_info_cmp(&lhs, &rhs) <= 0; +} + +static inline bool operator>(const sbp_msg_profiling_thread_info_t &lhs, + const sbp_msg_profiling_thread_info_t &rhs) { + return sbp_msg_profiling_thread_info_cmp(&lhs, &rhs) > 0; +} + +static inline bool operator>=(const sbp_msg_profiling_thread_info_t &lhs, + const sbp_msg_profiling_thread_info_t &rhs) { + return sbp_msg_profiling_thread_info_cmp(&lhs, &rhs) >= 0; +} + +#endif // ifdef __cplusplus + +#endif /* LIBSBP_PROFILING_MSG_PROFILING_THREAD_INFO_H */ diff --git a/c/include/libsbp/profiling/ResourceBucket.h b/c/include/libsbp/profiling/ResourceBucket.h new file mode 100644 index 0000000000..bb7c802d01 --- /dev/null +++ b/c/include/libsbp/profiling/ResourceBucket.h @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2015-2021 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +/***************************************************************************** + * Automatically generated from yaml/swiftnav/sbp/profiling.yaml + * with generate.py. Please do not hand edit! + *****************************************************************************/ + +#ifndef LIBSBP_PROFILING_RESOURCEBUCKET_H +#define LIBSBP_PROFILING_RESOURCEBUCKET_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * + * SBP_RESOURCEBUCKET + * + *****************************************************************************/ +/** A bucket containing various resources + * + * Information about allocation of various resources grouped by buckets. Refer + * to product documentation to understand the meaning and values in this + * message. + */ +typedef struct { + /** + * Bucket name + */ + char name[SBP_RESOURCE_BUCKET_NAME_MAX]; + + /** + * Number of threads + */ + u8 thread; + + /** + * Number of mutexes + */ + u8 mutex; + + /** + * Number of condition variables + */ + u8 cv; + + /** + * Number of IO handles + */ + u8 io; + + /** + * Number of bytes allocated on the heap + */ + u32 heap_bytes_alloc; + + /** + * Number of bytes freed on the heap + */ + u32 heap_bytes_free; + + /** + * Number of bytes written to IO handles + */ + u32 io_write; + + /** + * Number of bytes read from IO handles + */ + u32 io_read; +} sbp_resource_bucket_t; + +/** + * Get encoded size of an instance of sbp_resource_bucket_t + * + * @param msg sbp_resource_bucket_t instance + * @return Length of on-wire representation + */ +static inline size_t sbp_resource_bucket_encoded_len( + const sbp_resource_bucket_t *msg) { + (void)msg; + return SBP_RESOURCE_BUCKET_ENCODED_LEN; +} + +/** + * Encode an instance of sbp_resource_bucket_t to wire representation + * + * This function encodes the given instance in to the user provided buffer. The + * buffer provided to this function must be large enough to store the encoded + * message otherwise it will return SBP_ENCODE_ERROR without writing anything to + * the buffer. + * + * Specify the length of the destination buffer in the \p len parameter. If + * non-null the number of bytes written to the buffer will be returned in \p + * n_written. + * + * @param buf Destination buffer + * @param len Length of \p buf + * @param n_written If not null, on success will be set to the number of bytes + * written to \p buf + * @param msg Instance of sbp_resource_bucket_t to encode + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 sbp_resource_bucket_encode(uint8_t *buf, uint8_t len, + uint8_t *n_written, + const sbp_resource_bucket_t *msg); + +/** + * Decode an instance of sbp_resource_bucket_t from wire representation + * + * This function decodes the wire representation of a sbp_resource_bucket_t + * message to the given instance. The caller must specify the length of the + * buffer in the \p len parameter. If non-null the number of bytes read from the + * buffer will be returned in \p n_read. + * + * @param buf Wire representation of the sbp_resource_bucket_t instance + * @param len Length of \p buf + * @param n_read If not null, on success will be set to the number of bytes read + * from \p buf + * @param msg Destination + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 sbp_resource_bucket_decode(const uint8_t *buf, uint8_t len, + uint8_t *n_read, + sbp_resource_bucket_t *msg); + +/** + * Compare two instances of sbp_resource_bucket_t + * + * The two instances will be compared and a value returned consistent with the + * return codes of comparison functions from the C standard library + * + * 0 will be returned if \p a and \p b are considered equal + * A value less than 0 will be returned if \p a is considered to be less than \p + * b A value greater than 0 will be returned if \p b is considered to be greater + * than \p b + * + * @param a sbp_resource_bucket_t instance + * @param b sbp_resource_bucket_t instance + * @return 0, <0, >0 + */ +SBP_EXPORT int sbp_resource_bucket_cmp(const sbp_resource_bucket_t *a, + const sbp_resource_bucket_t *b); + +#ifdef __cplusplus +} + +static inline bool operator==(const sbp_resource_bucket_t &lhs, + const sbp_resource_bucket_t &rhs) { + return sbp_resource_bucket_cmp(&lhs, &rhs) == 0; +} + +static inline bool operator!=(const sbp_resource_bucket_t &lhs, + const sbp_resource_bucket_t &rhs) { + return sbp_resource_bucket_cmp(&lhs, &rhs) != 0; +} + +static inline bool operator<(const sbp_resource_bucket_t &lhs, + const sbp_resource_bucket_t &rhs) { + return sbp_resource_bucket_cmp(&lhs, &rhs) < 0; +} + +static inline bool operator<=(const sbp_resource_bucket_t &lhs, + const sbp_resource_bucket_t &rhs) { + return sbp_resource_bucket_cmp(&lhs, &rhs) <= 0; +} + +static inline bool operator>(const sbp_resource_bucket_t &lhs, + const sbp_resource_bucket_t &rhs) { + return sbp_resource_bucket_cmp(&lhs, &rhs) > 0; +} + +static inline bool operator>=(const sbp_resource_bucket_t &lhs, + const sbp_resource_bucket_t &rhs) { + return sbp_resource_bucket_cmp(&lhs, &rhs) >= 0; +} + +#endif // ifdef __cplusplus + +#endif /* LIBSBP_PROFILING_RESOURCEBUCKET_H */ diff --git a/c/include/libsbp/profiling_macros.h b/c/include/libsbp/profiling_macros.h index 77e9982876..8de5620f1b 100644 --- a/c/include/libsbp/profiling_macros.h +++ b/c/include/libsbp/profiling_macros.h @@ -38,4 +38,77 @@ */ #define SBP_MSG_MEASUREMENT_POINT_ENCODED_OVERHEAD 40u +/** + * Encoded length of sbp_msg_profiling_system_info_t + */ +#define SBP_MSG_PROFILING_SYSTEM_INFO_ENCODED_LEN 21u + +#define SBP_PROFILING_THREAD_INFO_THREAD_STATE_MASK (0x3u) +#define SBP_PROFILING_THREAD_INFO_THREAD_STATE_SHIFT (0u) +#define SBP_PROFILING_THREAD_INFO_THREAD_STATE_GET(flags) \ + ((u8)((u8)((flags) >> SBP_PROFILING_THREAD_INFO_THREAD_STATE_SHIFT) & \ + SBP_PROFILING_THREAD_INFO_THREAD_STATE_MASK)) +#define SBP_PROFILING_THREAD_INFO_THREAD_STATE_SET(flags, val) \ + do { \ + (flags) = \ + (u8)((flags & (~(SBP_PROFILING_THREAD_INFO_THREAD_STATE_MASK \ + << SBP_PROFILING_THREAD_INFO_THREAD_STATE_SHIFT))) | \ + (((val) & (SBP_PROFILING_THREAD_INFO_THREAD_STATE_MASK)) \ + << (SBP_PROFILING_THREAD_INFO_THREAD_STATE_SHIFT))); \ + } while (0) + +#define SBP_PROFILING_THREAD_INFO_THREAD_STATE_EXTERNAL (0) +#define SBP_PROFILING_THREAD_INFO_THREAD_STATE_RUNNING (1) +#define SBP_PROFILING_THREAD_INFO_THREAD_STATE_STOPPED (2) +/** + * The maximum number of items that can be stored in + * sbp_msg_profiling_thread_info_t::name before the maximum SBP message size is + * exceeded + */ +#define SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX 230u + +/** + * Encoded length of sbp_msg_profiling_thread_info_t + * + * This type is not fixed size and an instance of this message may be longer + * than the value indicated by this symbol. Users call + * #sbp_msg_profiling_thread_info_encoded_len to determine the actual size of an + * instance of this message. + * + * See the documentation for libsbp for more details regarding the message + * structure and its variable length component(s) + */ +#define SBP_MSG_PROFILING_THREAD_INFO_ENCODED_OVERHEAD 25u + +/** + * The maximum number of items that can be stored in sbp_resource_bucket_t::name + * before the maximum SBP message size is exceeded + */ +#define SBP_RESOURCE_BUCKET_NAME_MAX 21u + +/** + * Encoded length of sbp_resource_bucket_t + */ +#define SBP_RESOURCE_BUCKET_ENCODED_LEN 41u + +/** + * The maximum number of items that can be stored in + * sbp_msg_profiling_resource_counter_t::buckets before the maximum SBP message + * size is exceeded + */ +#define SBP_MSG_PROFILING_RESOURCE_COUNTER_BUCKETS_MAX 6u + +/** + * Encoded length of sbp_msg_profiling_resource_counter_t + * + * This type is not fixed size and an instance of this message may be longer + * than the value indicated by this symbol. Users call + * #sbp_msg_profiling_resource_counter_encoded_len to determine the actual size + * of an instance of this message. + * + * See the documentation for libsbp for more details regarding the message + * structure and its variable length component(s) + */ +#define SBP_MSG_PROFILING_RESOURCE_COUNTER_ENCODED_OVERHEAD 2u + #endif /* LIBSBP_PROFILING_MACROS_H */ diff --git a/c/include/libsbp/sbp_msg.h b/c/include/libsbp/sbp_msg.h index 7348322dc1..ee133e4aa7 100644 --- a/c/include/libsbp/sbp_msg.h +++ b/c/include/libsbp/sbp_msg.h @@ -207,6 +207,9 @@ typedef union { sbp_msg_pose_relative_t pose_relative; sbp_msg_pps_time_t pps_time; sbp_msg_print_dep_t print_dep; + sbp_msg_profiling_resource_counter_t profiling_resource_counter; + sbp_msg_profiling_system_info_t profiling_system_info; + sbp_msg_profiling_thread_info_t profiling_thread_info; sbp_msg_protection_level_dep_a_t protection_level_dep_a; sbp_msg_protection_level_t protection_level; sbp_msg_reference_frame_param_t reference_frame_param; @@ -713,6 +716,15 @@ static inline s8 sbp_message_encode(uint8_t *buf, uint8_t len, return sbp_msg_pps_time_encode(buf, len, n_written, &msg->pps_time); case SbpMsgPrintDep: return sbp_msg_print_dep_encode(buf, len, n_written, &msg->print_dep); + case SbpMsgProfilingResourceCounter: + return sbp_msg_profiling_resource_counter_encode( + buf, len, n_written, &msg->profiling_resource_counter); + case SbpMsgProfilingSystemInfo: + return sbp_msg_profiling_system_info_encode(buf, len, n_written, + &msg->profiling_system_info); + case SbpMsgProfilingThreadInfo: + return sbp_msg_profiling_thread_info_encode(buf, len, n_written, + &msg->profiling_thread_info); case SbpMsgProtectionLevelDepA: return sbp_msg_protection_level_dep_a_encode( buf, len, n_written, &msg->protection_level_dep_a); @@ -1368,6 +1380,15 @@ static inline s8 sbp_message_decode(const uint8_t *buf, uint8_t len, return sbp_msg_pps_time_decode(buf, len, n_read, &msg->pps_time); case SbpMsgPrintDep: return sbp_msg_print_dep_decode(buf, len, n_read, &msg->print_dep); + case SbpMsgProfilingResourceCounter: + return sbp_msg_profiling_resource_counter_decode( + buf, len, n_read, &msg->profiling_resource_counter); + case SbpMsgProfilingSystemInfo: + return sbp_msg_profiling_system_info_decode(buf, len, n_read, + &msg->profiling_system_info); + case SbpMsgProfilingThreadInfo: + return sbp_msg_profiling_thread_info_decode(buf, len, n_read, + &msg->profiling_thread_info); case SbpMsgProtectionLevelDepA: return sbp_msg_protection_level_dep_a_decode( buf, len, n_read, &msg->protection_level_dep_a); @@ -1942,6 +1963,15 @@ static inline size_t sbp_message_encoded_len(sbp_msg_type_t msg_type, return sbp_msg_pps_time_encoded_len(&msg->pps_time); case SbpMsgPrintDep: return sbp_msg_print_dep_encoded_len(&msg->print_dep); + case SbpMsgProfilingResourceCounter: + return sbp_msg_profiling_resource_counter_encoded_len( + &msg->profiling_resource_counter); + case SbpMsgProfilingSystemInfo: + return sbp_msg_profiling_system_info_encoded_len( + &msg->profiling_system_info); + case SbpMsgProfilingThreadInfo: + return sbp_msg_profiling_thread_info_encoded_len( + &msg->profiling_thread_info); case SbpMsgProtectionLevelDepA: return sbp_msg_protection_level_dep_a_encoded_len( &msg->protection_level_dep_a); @@ -2534,6 +2564,15 @@ static inline int sbp_message_cmp(sbp_msg_type_t msg_type, const sbp_msg_t *a, return sbp_msg_pps_time_cmp(&a->pps_time, &b->pps_time); case SbpMsgPrintDep: return sbp_msg_print_dep_cmp(&a->print_dep, &b->print_dep); + case SbpMsgProfilingResourceCounter: + return sbp_msg_profiling_resource_counter_cmp( + &a->profiling_resource_counter, &b->profiling_resource_counter); + case SbpMsgProfilingSystemInfo: + return sbp_msg_profiling_system_info_cmp(&a->profiling_system_info, + &b->profiling_system_info); + case SbpMsgProfilingThreadInfo: + return sbp_msg_profiling_thread_info_cmp(&a->profiling_thread_info, + &b->profiling_thread_info); case SbpMsgProtectionLevelDepA: return sbp_msg_protection_level_dep_a_cmp(&a->protection_level_dep_a, &b->protection_level_dep_a); diff --git a/c/include/libsbp/sbp_msg_type.h b/c/include/libsbp/sbp_msg_type.h index 9cb1d85180..6ebd25a09c 100644 --- a/c/include/libsbp/sbp_msg_type.h +++ b/c/include/libsbp/sbp_msg_type.h @@ -198,6 +198,9 @@ typedef enum { SbpMsgPoseRelative = 0x0245, SbpMsgPpsTime = 0xFF08, SbpMsgPrintDep = 0x0010, + SbpMsgProfilingResourceCounter = 0xCF03, + SbpMsgProfilingSystemInfo = 0xCF01, + SbpMsgProfilingThreadInfo = 0xCF02, SbpMsgProtectionLevelDepA = 0x0216, SbpMsgProtectionLevel = 0x0217, SbpMsgReferenceFrameParam = 0x0244, @@ -585,6 +588,12 @@ static inline const char *sbp_msg_type_to_string(sbp_msg_type_t msg_type) { return "MSG_PPS_TIME"; case SbpMsgPrintDep: return "MSG_PRINT_DEP"; + case SbpMsgProfilingResourceCounter: + return "MSG_PROFILING_RESOURCE_COUNTER"; + case SbpMsgProfilingSystemInfo: + return "MSG_PROFILING_SYSTEM_INFO"; + case SbpMsgProfilingThreadInfo: + return "MSG_PROFILING_THREAD_INFO"; case SbpMsgProtectionLevelDepA: return "MSG_PROTECTION_LEVEL_DEP_A"; case SbpMsgProtectionLevel: diff --git a/c/src/include/libsbp/internal/profiling.h b/c/src/include/libsbp/internal/profiling.h index 25b68930bc..84bb4fb675 100644 --- a/c/src/include/libsbp/internal/profiling.h +++ b/c/src/include/libsbp/internal/profiling.h @@ -47,6 +47,86 @@ bool sbp_msg_measurement_point_encode_internal( bool sbp_msg_measurement_point_decode_internal( sbp_decode_ctx_t *ctx, sbp_msg_measurement_point_t *msg); +/** + * Internal function to encode an SBP type to a buffer + * + * @param ctx Encode context + * @param msg SBP type instance + * @return true on success, false otherwise + */ +bool sbp_msg_profiling_system_info_encode_internal( + sbp_encode_ctx_t *ctx, const sbp_msg_profiling_system_info_t *msg); + +/** + * Internal function to decode an SBP type from a buffer + * + * @param ctx Decode context + * @param msg SBP type instance + * @return true on success, false otherwise + */ +bool sbp_msg_profiling_system_info_decode_internal( + sbp_decode_ctx_t *ctx, sbp_msg_profiling_system_info_t *msg); + +/** + * Internal function to encode an SBP type to a buffer + * + * @param ctx Encode context + * @param msg SBP type instance + * @return true on success, false otherwise + */ +bool sbp_msg_profiling_thread_info_encode_internal( + sbp_encode_ctx_t *ctx, const sbp_msg_profiling_thread_info_t *msg); + +/** + * Internal function to decode an SBP type from a buffer + * + * @param ctx Decode context + * @param msg SBP type instance + * @return true on success, false otherwise + */ +bool sbp_msg_profiling_thread_info_decode_internal( + sbp_decode_ctx_t *ctx, sbp_msg_profiling_thread_info_t *msg); + +/** + * Internal function to encode an SBP type to a buffer + * + * @param ctx Encode context + * @param msg SBP type instance + * @return true on success, false otherwise + */ +bool sbp_resource_bucket_encode_internal(sbp_encode_ctx_t *ctx, + const sbp_resource_bucket_t *msg); + +/** + * Internal function to decode an SBP type from a buffer + * + * @param ctx Decode context + * @param msg SBP type instance + * @return true on success, false otherwise + */ +bool sbp_resource_bucket_decode_internal(sbp_decode_ctx_t *ctx, + sbp_resource_bucket_t *msg); + +/** + * Internal function to encode an SBP type to a buffer + * + * @param ctx Encode context + * @param msg SBP type instance + * @return true on success, false otherwise + */ +bool sbp_msg_profiling_resource_counter_encode_internal( + sbp_encode_ctx_t *ctx, const sbp_msg_profiling_resource_counter_t *msg); + +/** + * Internal function to decode an SBP type from a buffer + * + * @param ctx Decode context + * @param msg SBP type instance + * @return true on success, false otherwise + */ +bool sbp_msg_profiling_resource_counter_decode_internal( + sbp_decode_ctx_t *ctx, sbp_msg_profiling_resource_counter_t *msg); + #ifdef __cplusplus } #endif diff --git a/c/src/profiling.c b/c/src/profiling.c index 814f46ae26..e783d75d63 100644 --- a/c/src/profiling.c +++ b/c/src/profiling.c @@ -275,3 +275,594 @@ int sbp_msg_measurement_point_cmp(const sbp_msg_measurement_point_t *a, ret = sbp_msg_measurement_point_func_strcmp(a, b); return ret; } + +bool sbp_msg_profiling_system_info_encode_internal( + sbp_encode_ctx_t *ctx, const sbp_msg_profiling_system_info_t *msg) { + if (!sbp_u64_encode(ctx, &msg->total_cpu_time)) { + return false; + } + if (!sbp_u64_encode(ctx, &msg->age)) { + return false; + } + if (!sbp_u8_encode(ctx, &msg->n_threads)) { + return false; + } + if (!sbp_u32_encode(ctx, &msg->heap_usage)) { + return false; + } + return true; +} + +s8 sbp_msg_profiling_system_info_encode( + uint8_t *buf, uint8_t len, uint8_t *n_written, + const sbp_msg_profiling_system_info_t *msg) { + sbp_encode_ctx_t ctx; + ctx.buf = buf; + ctx.buf_len = len; + ctx.offset = 0; + if (!sbp_msg_profiling_system_info_encode_internal(&ctx, msg)) { + return SBP_ENCODE_ERROR; + } + if (n_written != NULL) { + *n_written = (uint8_t)ctx.offset; + } + return SBP_OK; +} + +bool sbp_msg_profiling_system_info_decode_internal( + sbp_decode_ctx_t *ctx, sbp_msg_profiling_system_info_t *msg) { + if (!sbp_u64_decode(ctx, &msg->total_cpu_time)) { + return false; + } + if (!sbp_u64_decode(ctx, &msg->age)) { + return false; + } + if (!sbp_u8_decode(ctx, &msg->n_threads)) { + return false; + } + if (!sbp_u32_decode(ctx, &msg->heap_usage)) { + return false; + } + return true; +} + +s8 sbp_msg_profiling_system_info_decode(const uint8_t *buf, uint8_t len, + uint8_t *n_read, + sbp_msg_profiling_system_info_t *msg) { + sbp_decode_ctx_t ctx; + ctx.buf = buf; + ctx.buf_len = len; + ctx.offset = 0; + if (!sbp_msg_profiling_system_info_decode_internal(&ctx, msg)) { + return SBP_DECODE_ERROR; + } + if (n_read != NULL) { + *n_read = (uint8_t)ctx.offset; + } + return SBP_OK; +} + +s8 sbp_msg_profiling_system_info_send( + sbp_state_t *s, u16 sender_id, const sbp_msg_profiling_system_info_t *msg, + sbp_write_fn_t write) { + uint8_t payload[SBP_MAX_PAYLOAD_LEN]; + uint8_t payload_len; + s8 ret = sbp_msg_profiling_system_info_encode(payload, sizeof(payload), + &payload_len, msg); + if (ret != SBP_OK) { + return ret; + } + return sbp_internal_forward_payload(s, SbpMsgProfilingSystemInfo, sender_id, + payload_len, payload, write); +} + +int sbp_msg_profiling_system_info_cmp( + const sbp_msg_profiling_system_info_t *a, + const sbp_msg_profiling_system_info_t *b) { + int ret = 0; + + ret = sbp_u64_cmp(&a->total_cpu_time, &b->total_cpu_time); + if (ret != 0) { + return ret; + } + + ret = sbp_u64_cmp(&a->age, &b->age); + if (ret != 0) { + return ret; + } + + ret = sbp_u8_cmp(&a->n_threads, &b->n_threads); + if (ret != 0) { + return ret; + } + + ret = sbp_u32_cmp(&a->heap_usage, &b->heap_usage); + return ret; +} + +void sbp_msg_profiling_thread_info_name_init( + sbp_msg_profiling_thread_info_t *msg) { + sbp_null_terminated_string_init(&msg->name); +} + +bool sbp_msg_profiling_thread_info_name_valid( + const sbp_msg_profiling_thread_info_t *msg) { + return sbp_null_terminated_string_valid( + &msg->name, SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX); +} + +int sbp_msg_profiling_thread_info_name_strcmp( + const sbp_msg_profiling_thread_info_t *a, + const sbp_msg_profiling_thread_info_t *b) { + return sbp_null_terminated_string_strcmp( + &a->name, &b->name, SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX); +} + +size_t sbp_msg_profiling_thread_info_name_encoded_len( + const sbp_msg_profiling_thread_info_t *msg) { + return sbp_null_terminated_string_encoded_len( + &msg->name, SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX); +} + +size_t sbp_msg_profiling_thread_info_name_space_remaining( + const sbp_msg_profiling_thread_info_t *msg) { + return sbp_null_terminated_string_space_remaining( + &msg->name, SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX); +} +bool sbp_msg_profiling_thread_info_name_set( + sbp_msg_profiling_thread_info_t *msg, const char *new_str, + bool should_trunc, size_t *n_written) { + return sbp_null_terminated_string_set(&msg->name, + SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX, + should_trunc, n_written, new_str); +} + +bool sbp_msg_profiling_thread_info_name_set_raw( + sbp_msg_profiling_thread_info_t *msg, const char *new_buf, + size_t new_buf_len, bool should_trunc, size_t *n_written) { + return sbp_null_terminated_string_set_raw( + &msg->name, SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX, should_trunc, + n_written, new_buf, new_buf_len); +} + +bool sbp_msg_profiling_thread_info_name_printf( + sbp_msg_profiling_thread_info_t *msg, bool should_trunc, size_t *n_written, + const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + bool ret = sbp_null_terminated_string_vprintf( + &msg->name, SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX, should_trunc, + n_written, fmt, ap); + va_end(ap); + return ret; +} + +bool sbp_msg_profiling_thread_info_name_vprintf( + sbp_msg_profiling_thread_info_t *msg, bool should_trunc, size_t *n_written, + const char *fmt, va_list ap) { + return sbp_null_terminated_string_vprintf( + &msg->name, SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX, should_trunc, + n_written, fmt, ap); +} + +bool sbp_msg_profiling_thread_info_name_append_printf( + sbp_msg_profiling_thread_info_t *msg, bool should_trunc, size_t *n_written, + const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + bool ret = sbp_null_terminated_string_append_vprintf( + &msg->name, SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX, should_trunc, + n_written, fmt, ap); + va_end(ap); + return ret; +} + +bool sbp_msg_profiling_thread_info_name_append_vprintf( + sbp_msg_profiling_thread_info_t *msg, bool should_trunc, size_t *n_written, + const char *fmt, va_list ap) { + return sbp_null_terminated_string_append_vprintf( + &msg->name, SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX, should_trunc, + n_written, fmt, ap); +} + +const char *sbp_msg_profiling_thread_info_name_get( + const sbp_msg_profiling_thread_info_t *msg) { + return sbp_null_terminated_string_get(&msg->name, + SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX); +} + +size_t sbp_msg_profiling_thread_info_name_strlen( + const sbp_msg_profiling_thread_info_t *msg) { + return sbp_null_terminated_string_strlen( + &msg->name, SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX); +} + +bool sbp_msg_profiling_thread_info_encode_internal( + sbp_encode_ctx_t *ctx, const sbp_msg_profiling_thread_info_t *msg) { + if (!sbp_u64_encode(ctx, &msg->total_cpu_time)) { + return false; + } + if (!sbp_u64_encode(ctx, &msg->age)) { + return false; + } + if (!sbp_u8_encode(ctx, &msg->state)) { + return false; + } + if (!sbp_u32_encode(ctx, &msg->stack_size)) { + return false; + } + if (!sbp_u32_encode(ctx, &msg->stack_usage)) { + return false; + } + if (!sbp_null_terminated_string_encode( + &msg->name, SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX, ctx)) { + return false; + } + return true; +} + +s8 sbp_msg_profiling_thread_info_encode( + uint8_t *buf, uint8_t len, uint8_t *n_written, + const sbp_msg_profiling_thread_info_t *msg) { + sbp_encode_ctx_t ctx; + ctx.buf = buf; + ctx.buf_len = len; + ctx.offset = 0; + if (!sbp_msg_profiling_thread_info_encode_internal(&ctx, msg)) { + return SBP_ENCODE_ERROR; + } + if (n_written != NULL) { + *n_written = (uint8_t)ctx.offset; + } + return SBP_OK; +} + +bool sbp_msg_profiling_thread_info_decode_internal( + sbp_decode_ctx_t *ctx, sbp_msg_profiling_thread_info_t *msg) { + if (!sbp_u64_decode(ctx, &msg->total_cpu_time)) { + return false; + } + if (!sbp_u64_decode(ctx, &msg->age)) { + return false; + } + if (!sbp_u8_decode(ctx, &msg->state)) { + return false; + } + if (!sbp_u32_decode(ctx, &msg->stack_size)) { + return false; + } + if (!sbp_u32_decode(ctx, &msg->stack_usage)) { + return false; + } + if (!sbp_null_terminated_string_decode( + &msg->name, SBP_MSG_PROFILING_THREAD_INFO_NAME_MAX, ctx)) { + return false; + } + return true; +} + +s8 sbp_msg_profiling_thread_info_decode(const uint8_t *buf, uint8_t len, + uint8_t *n_read, + sbp_msg_profiling_thread_info_t *msg) { + sbp_decode_ctx_t ctx; + ctx.buf = buf; + ctx.buf_len = len; + ctx.offset = 0; + if (!sbp_msg_profiling_thread_info_decode_internal(&ctx, msg)) { + return SBP_DECODE_ERROR; + } + if (n_read != NULL) { + *n_read = (uint8_t)ctx.offset; + } + return SBP_OK; +} + +s8 sbp_msg_profiling_thread_info_send( + sbp_state_t *s, u16 sender_id, const sbp_msg_profiling_thread_info_t *msg, + sbp_write_fn_t write) { + uint8_t payload[SBP_MAX_PAYLOAD_LEN]; + uint8_t payload_len; + s8 ret = sbp_msg_profiling_thread_info_encode(payload, sizeof(payload), + &payload_len, msg); + if (ret != SBP_OK) { + return ret; + } + return sbp_internal_forward_payload(s, SbpMsgProfilingThreadInfo, sender_id, + payload_len, payload, write); +} + +int sbp_msg_profiling_thread_info_cmp( + const sbp_msg_profiling_thread_info_t *a, + const sbp_msg_profiling_thread_info_t *b) { + int ret = 0; + + ret = sbp_u64_cmp(&a->total_cpu_time, &b->total_cpu_time); + if (ret != 0) { + return ret; + } + + ret = sbp_u64_cmp(&a->age, &b->age); + if (ret != 0) { + return ret; + } + + ret = sbp_u8_cmp(&a->state, &b->state); + if (ret != 0) { + return ret; + } + + ret = sbp_u32_cmp(&a->stack_size, &b->stack_size); + if (ret != 0) { + return ret; + } + + ret = sbp_u32_cmp(&a->stack_usage, &b->stack_usage); + if (ret != 0) { + return ret; + } + + ret = sbp_msg_profiling_thread_info_name_strcmp(a, b); + return ret; +} + +bool sbp_resource_bucket_encode_internal(sbp_encode_ctx_t *ctx, + const sbp_resource_bucket_t *msg) { + for (size_t i = 0; i < SBP_RESOURCE_BUCKET_NAME_MAX; i++) { + if (!sbp_char_encode(ctx, &msg->name[i])) { + return false; + } + } + if (!sbp_u8_encode(ctx, &msg->thread)) { + return false; + } + if (!sbp_u8_encode(ctx, &msg->mutex)) { + return false; + } + if (!sbp_u8_encode(ctx, &msg->cv)) { + return false; + } + if (!sbp_u8_encode(ctx, &msg->io)) { + return false; + } + if (!sbp_u32_encode(ctx, &msg->heap_bytes_alloc)) { + return false; + } + if (!sbp_u32_encode(ctx, &msg->heap_bytes_free)) { + return false; + } + if (!sbp_u32_encode(ctx, &msg->io_write)) { + return false; + } + if (!sbp_u32_encode(ctx, &msg->io_read)) { + return false; + } + return true; +} + +s8 sbp_resource_bucket_encode(uint8_t *buf, uint8_t len, uint8_t *n_written, + const sbp_resource_bucket_t *msg) { + sbp_encode_ctx_t ctx; + ctx.buf = buf; + ctx.buf_len = len; + ctx.offset = 0; + if (!sbp_resource_bucket_encode_internal(&ctx, msg)) { + return SBP_ENCODE_ERROR; + } + if (n_written != NULL) { + *n_written = (uint8_t)ctx.offset; + } + return SBP_OK; +} + +bool sbp_resource_bucket_decode_internal(sbp_decode_ctx_t *ctx, + sbp_resource_bucket_t *msg) { + for (uint8_t i = 0; i < SBP_RESOURCE_BUCKET_NAME_MAX; i++) { + if (!sbp_char_decode(ctx, &msg->name[i])) { + return false; + } + } + if (!sbp_u8_decode(ctx, &msg->thread)) { + return false; + } + if (!sbp_u8_decode(ctx, &msg->mutex)) { + return false; + } + if (!sbp_u8_decode(ctx, &msg->cv)) { + return false; + } + if (!sbp_u8_decode(ctx, &msg->io)) { + return false; + } + if (!sbp_u32_decode(ctx, &msg->heap_bytes_alloc)) { + return false; + } + if (!sbp_u32_decode(ctx, &msg->heap_bytes_free)) { + return false; + } + if (!sbp_u32_decode(ctx, &msg->io_write)) { + return false; + } + if (!sbp_u32_decode(ctx, &msg->io_read)) { + return false; + } + return true; +} + +s8 sbp_resource_bucket_decode(const uint8_t *buf, uint8_t len, uint8_t *n_read, + sbp_resource_bucket_t *msg) { + sbp_decode_ctx_t ctx; + ctx.buf = buf; + ctx.buf_len = len; + ctx.offset = 0; + if (!sbp_resource_bucket_decode_internal(&ctx, msg)) { + return SBP_DECODE_ERROR; + } + if (n_read != NULL) { + *n_read = (uint8_t)ctx.offset; + } + return SBP_OK; +} + +int sbp_resource_bucket_cmp(const sbp_resource_bucket_t *a, + const sbp_resource_bucket_t *b) { + int ret = 0; + + for (uint8_t i = 0; i < SBP_RESOURCE_BUCKET_NAME_MAX; i++) { + ret = sbp_char_cmp(&a->name[i], &b->name[i]); + if (ret != 0) { + return ret; + } + } + if (ret != 0) { + return ret; + } + + ret = sbp_u8_cmp(&a->thread, &b->thread); + if (ret != 0) { + return ret; + } + + ret = sbp_u8_cmp(&a->mutex, &b->mutex); + if (ret != 0) { + return ret; + } + + ret = sbp_u8_cmp(&a->cv, &b->cv); + if (ret != 0) { + return ret; + } + + ret = sbp_u8_cmp(&a->io, &b->io); + if (ret != 0) { + return ret; + } + + ret = sbp_u32_cmp(&a->heap_bytes_alloc, &b->heap_bytes_alloc); + if (ret != 0) { + return ret; + } + + ret = sbp_u32_cmp(&a->heap_bytes_free, &b->heap_bytes_free); + if (ret != 0) { + return ret; + } + + ret = sbp_u32_cmp(&a->io_write, &b->io_write); + if (ret != 0) { + return ret; + } + + ret = sbp_u32_cmp(&a->io_read, &b->io_read); + return ret; +} + +bool sbp_msg_profiling_resource_counter_encode_internal( + sbp_encode_ctx_t *ctx, const sbp_msg_profiling_resource_counter_t *msg) { + if (!sbp_u8_encode(ctx, &msg->seq_no)) { + return false; + } + if (!sbp_u8_encode(ctx, &msg->seq_len)) { + return false; + } + for (size_t i = 0; i < msg->n_buckets; i++) { + if (!sbp_resource_bucket_encode_internal(ctx, &msg->buckets[i])) { + return false; + } + } + return true; +} + +s8 sbp_msg_profiling_resource_counter_encode( + uint8_t *buf, uint8_t len, uint8_t *n_written, + const sbp_msg_profiling_resource_counter_t *msg) { + sbp_encode_ctx_t ctx; + ctx.buf = buf; + ctx.buf_len = len; + ctx.offset = 0; + if (!sbp_msg_profiling_resource_counter_encode_internal(&ctx, msg)) { + return SBP_ENCODE_ERROR; + } + if (n_written != NULL) { + *n_written = (uint8_t)ctx.offset; + } + return SBP_OK; +} + +bool sbp_msg_profiling_resource_counter_decode_internal( + sbp_decode_ctx_t *ctx, sbp_msg_profiling_resource_counter_t *msg) { + if (!sbp_u8_decode(ctx, &msg->seq_no)) { + return false; + } + if (!sbp_u8_decode(ctx, &msg->seq_len)) { + return false; + } + if (((ctx->buf_len - ctx->offset) % SBP_RESOURCE_BUCKET_ENCODED_LEN) != 0) { + return false; + } + msg->n_buckets = + (uint8_t)((ctx->buf_len - ctx->offset) / SBP_RESOURCE_BUCKET_ENCODED_LEN); + for (uint8_t i = 0; i < msg->n_buckets; i++) { + if (!sbp_resource_bucket_decode_internal(ctx, &msg->buckets[i])) { + return false; + } + } + return true; +} + +s8 sbp_msg_profiling_resource_counter_decode( + const uint8_t *buf, uint8_t len, uint8_t *n_read, + sbp_msg_profiling_resource_counter_t *msg) { + sbp_decode_ctx_t ctx; + ctx.buf = buf; + ctx.buf_len = len; + ctx.offset = 0; + if (!sbp_msg_profiling_resource_counter_decode_internal(&ctx, msg)) { + return SBP_DECODE_ERROR; + } + if (n_read != NULL) { + *n_read = (uint8_t)ctx.offset; + } + return SBP_OK; +} + +s8 sbp_msg_profiling_resource_counter_send( + sbp_state_t *s, u16 sender_id, + const sbp_msg_profiling_resource_counter_t *msg, sbp_write_fn_t write) { + uint8_t payload[SBP_MAX_PAYLOAD_LEN]; + uint8_t payload_len; + s8 ret = sbp_msg_profiling_resource_counter_encode(payload, sizeof(payload), + &payload_len, msg); + if (ret != SBP_OK) { + return ret; + } + return sbp_internal_forward_payload(s, SbpMsgProfilingResourceCounter, + sender_id, payload_len, payload, write); +} + +int sbp_msg_profiling_resource_counter_cmp( + const sbp_msg_profiling_resource_counter_t *a, + const sbp_msg_profiling_resource_counter_t *b) { + int ret = 0; + + ret = sbp_u8_cmp(&a->seq_no, &b->seq_no); + if (ret != 0) { + return ret; + } + + ret = sbp_u8_cmp(&a->seq_len, &b->seq_len); + if (ret != 0) { + return ret; + } + + ret = sbp_u8_cmp(&a->n_buckets, &b->n_buckets); + if (ret != 0) { + return ret; + } + for (uint8_t i = 0; i < a->n_buckets; i++) { + ret = sbp_resource_bucket_cmp(&a->buckets[i], &b->buckets[i]); + if (ret != 0) { + return ret; + } + } + return ret; +} diff --git a/c/test/auto_check_sbp_profiling_MsgProfilingResourceCounter.c b/c/test/auto_check_sbp_profiling_MsgProfilingResourceCounter.c new file mode 100644 index 0000000000..a69d6b011b --- /dev/null +++ b/c/test/auto_check_sbp_profiling_MsgProfilingResourceCounter.c @@ -0,0 +1,784 @@ +/* + * Copyright (C) 2015-2021 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +// This file was auto-generated from +// spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingResourceCounter.yaml +// by generate.py. Do not modify by hand! + +#include +#include +#include +#include // for debugging +#include // for malloc + +static struct { + u32 n_callbacks_logged; + u16 sender_id; + sbp_msg_type_t msg_type; + sbp_msg_t msg; + void *context; +} last_msg; + +static size_t dummy_wr = 0; +static size_t dummy_rd = 0; +static u8 dummy_buff[1024]; +static void *last_io_context; + +static void *DUMMY_MEMORY_FOR_CALLBACKS = (void *)0xdeadbeef; +static void *DUMMY_MEMORY_FOR_IO = (void *)0xdead0000; + +static void dummy_reset() { + dummy_rd = dummy_wr = 0; + memset(dummy_buff, 0, sizeof(dummy_buff)); +} + +static s32 dummy_write(u8 *buff, u32 n, void *context) { + last_io_context = context; + size_t real_n = n; //(dummy_n > n) ? n : dummy_n; + memcpy(dummy_buff + dummy_wr, buff, real_n); + dummy_wr += real_n; + return (s32)real_n; +} + +static s32 dummy_read(u8 *buff, u32 n, void *context) { + last_io_context = context; + size_t real_n = n; //(dummy_n > n) ? n : dummy_n; + memcpy(buff, dummy_buff + dummy_rd, real_n); + dummy_rd += real_n; + return (s32)real_n; +} + +static void logging_reset() { memset(&last_msg, 0, sizeof(last_msg)); } + +static void msg_callback(u16 sender_id, sbp_msg_type_t msg_type, + const sbp_msg_t *msg, void *context) { + last_msg.n_callbacks_logged++; + last_msg.sender_id = sender_id; + last_msg.msg_type = msg_type; + last_msg.msg = *msg; + last_msg.context = context; +} + +START_TEST(test_auto_check_sbp_profiling_MsgProfilingResourceCounter) { + static sbp_msg_callbacks_node_t n; + + // State of the SBP message parser. + // Must be statically allocated. + sbp_state_t sbp_state; + + // + // Run tests: + // + // Test successful parsing of a message + { + // SBP parser state must be initialized before sbp_process is called. + // We re-initialize before every test so that callbacks for the same message + // types can be + // allocated multiple times across different tests. + sbp_state_init(&sbp_state); + + sbp_state_set_io_context(&sbp_state, &DUMMY_MEMORY_FOR_IO); + + logging_reset(); + + sbp_callback_register(&sbp_state, 0xcf03, &msg_callback, + &DUMMY_MEMORY_FOR_CALLBACKS, &n); + + u8 encoded_frame[] = { + 85, 3, 207, 0, 16, 248, 1, 3, 70, 117, 115, 105, 111, 110, + 32, 101, 110, 103, 105, 110, 101, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 2, 0, 248, 38, 14, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 78, 84, 82, 73, 80, 32, 99, + 108, 105, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 230, 73, 1, 0, 0, 0, 0, 0, 111, 3, + 0, 0, 64, 76, 0, 0, 83, 83, 82, 50, 79, 83, 82, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 72, 13, 66, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 80, 101, 114, 105, 111, 100, 105, 99, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, + 1, 0, 72, 197, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 73, 77, 85, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 129, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, + 102, 0, 0, 115, 98, 112, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 2, 2, 2, + 243, 169, 0, 0, 0, 0, 0, 0, 187, 151, 3, 0, 242, 1, + 0, 0, 181, 153, + }; + + dummy_reset(); + + sbp_msg_t test_msg; + memset(&test_msg, 0, sizeof(test_msg)); + + test_msg.profiling_resource_counter.buckets[0].cv = 2; + + test_msg.profiling_resource_counter.buckets[0].heap_bytes_alloc = 927480; + + test_msg.profiling_resource_counter.buckets[0].heap_bytes_free = 0; + + test_msg.profiling_resource_counter.buckets[0].io = 0; + + test_msg.profiling_resource_counter.buckets[0].io_read = 0; + + test_msg.profiling_resource_counter.buckets[0].io_write = 0; + + test_msg.profiling_resource_counter.buckets[0].mutex = 2; + + { + const char assign_string[] = { + (char)70, (char)117, (char)115, (char)105, (char)111, (char)110, + (char)32, (char)101, (char)110, (char)103, (char)105, (char)110, + (char)101, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0}; + memcpy(test_msg.profiling_resource_counter.buckets[0].name, assign_string, + sizeof(assign_string)); + } + + test_msg.profiling_resource_counter.buckets[0].thread = 1; + + test_msg.profiling_resource_counter.buckets[1].cv = 1; + + test_msg.profiling_resource_counter.buckets[1].heap_bytes_alloc = 84454; + + test_msg.profiling_resource_counter.buckets[1].heap_bytes_free = 0; + + test_msg.profiling_resource_counter.buckets[1].io = 1; + + test_msg.profiling_resource_counter.buckets[1].io_read = 19520; + + test_msg.profiling_resource_counter.buckets[1].io_write = 879; + + test_msg.profiling_resource_counter.buckets[1].mutex = 1; + + { + const char assign_string[] = { + (char)78, (char)84, (char)82, (char)73, (char)80, (char)32, + (char)99, (char)108, (char)105, (char)101, (char)110, (char)116, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0}; + memcpy(test_msg.profiling_resource_counter.buckets[1].name, assign_string, + sizeof(assign_string)); + } + + test_msg.profiling_resource_counter.buckets[1].thread = 1; + + test_msg.profiling_resource_counter.buckets[2].cv = 1; + + test_msg.profiling_resource_counter.buckets[2].heap_bytes_alloc = 4328776; + + test_msg.profiling_resource_counter.buckets[2].heap_bytes_free = 0; + + test_msg.profiling_resource_counter.buckets[2].io = 0; + + test_msg.profiling_resource_counter.buckets[2].io_read = 0; + + test_msg.profiling_resource_counter.buckets[2].io_write = 0; + + test_msg.profiling_resource_counter.buckets[2].mutex = 1; + + { + const char assign_string[] = { + (char)83, (char)83, (char)82, (char)50, (char)79, (char)83, (char)82, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0}; + memcpy(test_msg.profiling_resource_counter.buckets[2].name, assign_string, + sizeof(assign_string)); + } + + test_msg.profiling_resource_counter.buckets[2].thread = 1; + + test_msg.profiling_resource_counter.buckets[3].cv = 1; + + test_msg.profiling_resource_counter.buckets[3].heap_bytes_alloc = 247112; + + test_msg.profiling_resource_counter.buckets[3].heap_bytes_free = 0; + + test_msg.profiling_resource_counter.buckets[3].io = 0; + + test_msg.profiling_resource_counter.buckets[3].io_read = 0; + + test_msg.profiling_resource_counter.buckets[3].io_write = 0; + + test_msg.profiling_resource_counter.buckets[3].mutex = 2; + + { + const char assign_string[] = { + (char)80, (char)101, (char)114, (char)105, (char)111, (char)100, + (char)105, (char)99, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0}; + memcpy(test_msg.profiling_resource_counter.buckets[3].name, assign_string, + sizeof(assign_string)); + } + + test_msg.profiling_resource_counter.buckets[3].thread = 1; + + test_msg.profiling_resource_counter.buckets[4].cv = 1; + + test_msg.profiling_resource_counter.buckets[4].heap_bytes_alloc = 18305; + + test_msg.profiling_resource_counter.buckets[4].heap_bytes_free = 0; + + test_msg.profiling_resource_counter.buckets[4].io = 1; + + test_msg.profiling_resource_counter.buckets[4].io_read = 26207; + + test_msg.profiling_resource_counter.buckets[4].io_write = 0; + + test_msg.profiling_resource_counter.buckets[4].mutex = 1; + + { + const char assign_string[] = { + (char)73, (char)77, (char)85, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0}; + memcpy(test_msg.profiling_resource_counter.buckets[4].name, assign_string, + sizeof(assign_string)); + } + + test_msg.profiling_resource_counter.buckets[4].thread = 1; + + test_msg.profiling_resource_counter.buckets[5].cv = 2; + + test_msg.profiling_resource_counter.buckets[5].heap_bytes_alloc = 43507; + + test_msg.profiling_resource_counter.buckets[5].heap_bytes_free = 0; + + test_msg.profiling_resource_counter.buckets[5].io = 2; + + test_msg.profiling_resource_counter.buckets[5].io_read = 498; + + test_msg.profiling_resource_counter.buckets[5].io_write = 235451; + + test_msg.profiling_resource_counter.buckets[5].mutex = 2; + + { + const char assign_string[] = { + (char)115, (char)98, (char)112, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0}; + memcpy(test_msg.profiling_resource_counter.buckets[5].name, assign_string, + sizeof(assign_string)); + } + + test_msg.profiling_resource_counter.buckets[5].thread = 5; + + test_msg.profiling_resource_counter.n_buckets = 6; + + test_msg.profiling_resource_counter.seq_len = 3; + + test_msg.profiling_resource_counter.seq_no = 1; + + sbp_message_send(&sbp_state, SbpMsgProfilingResourceCounter, 4096, + &test_msg, &dummy_write); + + ck_assert_msg(dummy_wr == sizeof(encoded_frame), + "not enough data was written to dummy_buff (expected: %zu, " + "actual: %zu)", + sizeof(encoded_frame), dummy_wr); + ck_assert_msg(memcmp(dummy_buff, encoded_frame, sizeof(encoded_frame)) == 0, + "frame was not encoded properly"); + + while (dummy_rd < dummy_wr) { + ck_assert_msg(sbp_process(&sbp_state, &dummy_read) >= SBP_OK, + "sbp_process threw an error!"); + } + + ck_assert_msg(last_msg.n_callbacks_logged == 1, + "msg_callback: one callback should have been logged"); + ck_assert_msg(last_msg.sender_id == 4096, + "msg_callback: sender_id decoded incorrectly"); + + ck_assert_msg(sbp_message_cmp(SbpMsgProfilingResourceCounter, &last_msg.msg, + &test_msg) == 0, + "Sent and received messages did not compare equal"); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[0].cv == 2, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[0].cv, expected 2, is " + "%" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[0].cv); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[0].heap_bytes_alloc == + 927480, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[0].heap_bytes_alloc, " + "expected 927480, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[0] + .heap_bytes_alloc); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[0].heap_bytes_free == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[0].heap_bytes_free, " + "expected 0, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[0] + .heap_bytes_free); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[0].io == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[0].io, expected 0, is " + "%" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[0].io); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[0].io_read == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[0].io_read, expected " + "0, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[0].io_read); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[0].io_write == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[0].io_write, expected " + "0, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[0].io_write); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[0].mutex == 2, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[0].mutex, expected 2, " + "is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[0].mutex); + + { + const char check_string[] = { + (char)70, (char)117, (char)115, (char)105, (char)111, (char)110, + (char)32, (char)101, (char)110, (char)103, (char)105, (char)110, + (char)101, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0}; + ck_assert_msg( + memcmp(&last_msg.msg.profiling_resource_counter.buckets[0].name, + check_string, sizeof(check_string)) == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[0].name, expected " + "string '%s', is '%s'", + check_string, + last_msg.msg.profiling_resource_counter.buckets[0].name); + } + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[0].thread == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[0].thread, expected " + "1, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[0].thread); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[1].cv == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[1].cv, expected 1, is " + "%" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[1].cv); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[1].heap_bytes_alloc == + 84454, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[1].heap_bytes_alloc, " + "expected 84454, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[1] + .heap_bytes_alloc); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[1].heap_bytes_free == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[1].heap_bytes_free, " + "expected 0, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[1] + .heap_bytes_free); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[1].io == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[1].io, expected 1, is " + "%" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[1].io); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[1].io_read == 19520, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[1].io_read, expected " + "19520, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[1].io_read); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[1].io_write == 879, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[1].io_write, expected " + "879, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[1].io_write); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[1].mutex == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[1].mutex, expected 1, " + "is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[1].mutex); + + { + const char check_string[] = { + (char)78, (char)84, (char)82, (char)73, (char)80, (char)32, + (char)99, (char)108, (char)105, (char)101, (char)110, (char)116, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0}; + ck_assert_msg( + memcmp(&last_msg.msg.profiling_resource_counter.buckets[1].name, + check_string, sizeof(check_string)) == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[1].name, expected " + "string '%s', is '%s'", + check_string, + last_msg.msg.profiling_resource_counter.buckets[1].name); + } + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[1].thread == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[1].thread, expected " + "1, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[1].thread); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[2].cv == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[2].cv, expected 1, is " + "%" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[2].cv); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[2].heap_bytes_alloc == + 4328776, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[2].heap_bytes_alloc, " + "expected 4328776, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[2] + .heap_bytes_alloc); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[2].heap_bytes_free == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[2].heap_bytes_free, " + "expected 0, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[2] + .heap_bytes_free); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[2].io == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[2].io, expected 0, is " + "%" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[2].io); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[2].io_read == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[2].io_read, expected " + "0, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[2].io_read); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[2].io_write == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[2].io_write, expected " + "0, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[2].io_write); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[2].mutex == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[2].mutex, expected 1, " + "is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[2].mutex); + + { + const char check_string[] = { + (char)83, (char)83, (char)82, (char)50, (char)79, (char)83, (char)82, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0}; + ck_assert_msg( + memcmp(&last_msg.msg.profiling_resource_counter.buckets[2].name, + check_string, sizeof(check_string)) == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[2].name, expected " + "string '%s', is '%s'", + check_string, + last_msg.msg.profiling_resource_counter.buckets[2].name); + } + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[2].thread == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[2].thread, expected " + "1, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[2].thread); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[3].cv == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[3].cv, expected 1, is " + "%" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[3].cv); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[3].heap_bytes_alloc == + 247112, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[3].heap_bytes_alloc, " + "expected 247112, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[3] + .heap_bytes_alloc); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[3].heap_bytes_free == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[3].heap_bytes_free, " + "expected 0, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[3] + .heap_bytes_free); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[3].io == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[3].io, expected 0, is " + "%" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[3].io); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[3].io_read == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[3].io_read, expected " + "0, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[3].io_read); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[3].io_write == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[3].io_write, expected " + "0, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[3].io_write); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[3].mutex == 2, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[3].mutex, expected 2, " + "is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[3].mutex); + + { + const char check_string[] = { + (char)80, (char)101, (char)114, (char)105, (char)111, (char)100, + (char)105, (char)99, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0}; + ck_assert_msg( + memcmp(&last_msg.msg.profiling_resource_counter.buckets[3].name, + check_string, sizeof(check_string)) == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[3].name, expected " + "string '%s', is '%s'", + check_string, + last_msg.msg.profiling_resource_counter.buckets[3].name); + } + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[3].thread == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[3].thread, expected " + "1, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[3].thread); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[4].cv == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[4].cv, expected 1, is " + "%" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[4].cv); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[4].heap_bytes_alloc == + 18305, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[4].heap_bytes_alloc, " + "expected 18305, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[4] + .heap_bytes_alloc); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[4].heap_bytes_free == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[4].heap_bytes_free, " + "expected 0, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[4] + .heap_bytes_free); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[4].io == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[4].io, expected 1, is " + "%" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[4].io); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[4].io_read == 26207, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[4].io_read, expected " + "26207, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[4].io_read); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[4].io_write == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[4].io_write, expected " + "0, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[4].io_write); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[4].mutex == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[4].mutex, expected 1, " + "is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[4].mutex); + + { + const char check_string[] = { + (char)73, (char)77, (char)85, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0}; + ck_assert_msg( + memcmp(&last_msg.msg.profiling_resource_counter.buckets[4].name, + check_string, sizeof(check_string)) == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[4].name, expected " + "string '%s', is '%s'", + check_string, + last_msg.msg.profiling_resource_counter.buckets[4].name); + } + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[4].thread == 1, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[4].thread, expected " + "1, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[4].thread); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[5].cv == 2, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[5].cv, expected 2, is " + "%" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[5].cv); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[5].heap_bytes_alloc == + 43507, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[5].heap_bytes_alloc, " + "expected 43507, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[5] + .heap_bytes_alloc); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[5].heap_bytes_free == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[5].heap_bytes_free, " + "expected 0, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[5] + .heap_bytes_free); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[5].io == 2, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[5].io, expected 2, is " + "%" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[5].io); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[5].io_read == 498, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[5].io_read, expected " + "498, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[5].io_read); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[5].io_write == 235451, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[5].io_write, expected " + "235451, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[5].io_write); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[5].mutex == 2, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[5].mutex, expected 2, " + "is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[5].mutex); + + { + const char check_string[] = { + (char)115, (char)98, (char)112, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0}; + ck_assert_msg( + memcmp(&last_msg.msg.profiling_resource_counter.buckets[5].name, + check_string, sizeof(check_string)) == 0, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[5].name, expected " + "string '%s', is '%s'", + check_string, + last_msg.msg.profiling_resource_counter.buckets[5].name); + } + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.buckets[5].thread == 5, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.buckets[5].thread, expected " + "5, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.buckets[5].thread); + + ck_assert_msg(last_msg.msg.profiling_resource_counter.n_buckets == 6, + "incorrect value for " + "last_msg.msg.profiling_resource_counter.n_buckets, expected " + "6, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.n_buckets); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.seq_len == 3, + "incorrect value for last_msg.msg.profiling_resource_counter.seq_len, " + "expected 3, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.seq_len); + + ck_assert_msg( + last_msg.msg.profiling_resource_counter.seq_no == 1, + "incorrect value for last_msg.msg.profiling_resource_counter.seq_no, " + "expected 1, is %" PRId64, + (int64_t)last_msg.msg.profiling_resource_counter.seq_no); + } +} +END_TEST + +Suite *auto_check_sbp_profiling_MsgProfilingResourceCounter_suite(void) { + Suite *s = suite_create( + "SBP generated test suite: " + "auto_check_sbp_profiling_MsgProfilingResourceCounter"); + TCase *tc_acq = tcase_create( + "Automated_Suite_auto_check_sbp_profiling_MsgProfilingResourceCounter"); + tcase_add_test(tc_acq, + test_auto_check_sbp_profiling_MsgProfilingResourceCounter); + suite_add_tcase(s, tc_acq); + return s; +} \ No newline at end of file diff --git a/c/test/auto_check_sbp_profiling_MsgProfilingSystemInfo.c b/c/test/auto_check_sbp_profiling_MsgProfilingSystemInfo.c new file mode 100644 index 0000000000..fab3a9989d --- /dev/null +++ b/c/test/auto_check_sbp_profiling_MsgProfilingSystemInfo.c @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2015-2021 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +// This file was auto-generated from +// spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingSystemInfo.yaml by +// generate.py. Do not modify by hand! + +#include +#include +#include +#include // for debugging +#include // for malloc + +static struct { + u32 n_callbacks_logged; + u16 sender_id; + sbp_msg_type_t msg_type; + sbp_msg_t msg; + void *context; +} last_msg; + +static size_t dummy_wr = 0; +static size_t dummy_rd = 0; +static u8 dummy_buff[1024]; +static void *last_io_context; + +static void *DUMMY_MEMORY_FOR_CALLBACKS = (void *)0xdeadbeef; +static void *DUMMY_MEMORY_FOR_IO = (void *)0xdead0000; + +static void dummy_reset() { + dummy_rd = dummy_wr = 0; + memset(dummy_buff, 0, sizeof(dummy_buff)); +} + +static s32 dummy_write(u8 *buff, u32 n, void *context) { + last_io_context = context; + size_t real_n = n; //(dummy_n > n) ? n : dummy_n; + memcpy(dummy_buff + dummy_wr, buff, real_n); + dummy_wr += real_n; + return (s32)real_n; +} + +static s32 dummy_read(u8 *buff, u32 n, void *context) { + last_io_context = context; + size_t real_n = n; //(dummy_n > n) ? n : dummy_n; + memcpy(buff, dummy_buff + dummy_rd, real_n); + dummy_rd += real_n; + return (s32)real_n; +} + +static void logging_reset() { memset(&last_msg, 0, sizeof(last_msg)); } + +static void msg_callback(u16 sender_id, sbp_msg_type_t msg_type, + const sbp_msg_t *msg, void *context) { + last_msg.n_callbacks_logged++; + last_msg.sender_id = sender_id; + last_msg.msg_type = msg_type; + last_msg.msg = *msg; + last_msg.context = context; +} + +START_TEST(test_auto_check_sbp_profiling_MsgProfilingSystemInfo) { + static sbp_msg_callbacks_node_t n; + + // State of the SBP message parser. + // Must be statically allocated. + sbp_state_t sbp_state; + + // + // Run tests: + // + // Test successful parsing of a message + { + // SBP parser state must be initialized before sbp_process is called. + // We re-initialize before every test so that callbacks for the same message + // types can be + // allocated multiple times across different tests. + sbp_state_init(&sbp_state); + + sbp_state_set_io_context(&sbp_state, &DUMMY_MEMORY_FOR_IO); + + logging_reset(); + + sbp_callback_register(&sbp_state, 0xcf01, &msg_callback, + &DUMMY_MEMORY_FOR_CALLBACKS, &n); + + u8 encoded_frame[] = { + 85, 1, 207, 0, 16, 21, 98, 40, 52, 0, 0, 0, 0, 0, 114, + 12, 157, 0, 0, 0, 0, 0, 27, 72, 195, 226, 0, 252, 65, + }; + + dummy_reset(); + + sbp_msg_t test_msg; + memset(&test_msg, 0, sizeof(test_msg)); + + test_msg.profiling_system_info.age = 10292338; + + test_msg.profiling_system_info.heap_usage = 14861128; + + test_msg.profiling_system_info.n_threads = 27; + + test_msg.profiling_system_info.total_cpu_time = 3418210; + + sbp_message_send(&sbp_state, SbpMsgProfilingSystemInfo, 4096, &test_msg, + &dummy_write); + + ck_assert_msg(dummy_wr == sizeof(encoded_frame), + "not enough data was written to dummy_buff (expected: %zu, " + "actual: %zu)", + sizeof(encoded_frame), dummy_wr); + ck_assert_msg(memcmp(dummy_buff, encoded_frame, sizeof(encoded_frame)) == 0, + "frame was not encoded properly"); + + while (dummy_rd < dummy_wr) { + ck_assert_msg(sbp_process(&sbp_state, &dummy_read) >= SBP_OK, + "sbp_process threw an error!"); + } + + ck_assert_msg(last_msg.n_callbacks_logged == 1, + "msg_callback: one callback should have been logged"); + ck_assert_msg(last_msg.sender_id == 4096, + "msg_callback: sender_id decoded incorrectly"); + + ck_assert_msg(sbp_message_cmp(SbpMsgProfilingSystemInfo, &last_msg.msg, + &test_msg) == 0, + "Sent and received messages did not compare equal"); + + ck_assert_msg(last_msg.msg.profiling_system_info.age == 10292338, + "incorrect value for last_msg.msg.profiling_system_info.age, " + "expected 10292338, is %" PRId64, + (int64_t)last_msg.msg.profiling_system_info.age); + + ck_assert_msg( + last_msg.msg.profiling_system_info.heap_usage == 14861128, + "incorrect value for last_msg.msg.profiling_system_info.heap_usage, " + "expected 14861128, is %" PRId64, + (int64_t)last_msg.msg.profiling_system_info.heap_usage); + + ck_assert_msg( + last_msg.msg.profiling_system_info.n_threads == 27, + "incorrect value for last_msg.msg.profiling_system_info.n_threads, " + "expected 27, is %" PRId64, + (int64_t)last_msg.msg.profiling_system_info.n_threads); + + ck_assert_msg(last_msg.msg.profiling_system_info.total_cpu_time == 3418210, + "incorrect value for " + "last_msg.msg.profiling_system_info.total_cpu_time, expected " + "3418210, is %" PRId64, + (int64_t)last_msg.msg.profiling_system_info.total_cpu_time); + } +} +END_TEST + +Suite *auto_check_sbp_profiling_MsgProfilingSystemInfo_suite(void) { + Suite *s = suite_create( + "SBP generated test suite: " + "auto_check_sbp_profiling_MsgProfilingSystemInfo"); + TCase *tc_acq = tcase_create( + "Automated_Suite_auto_check_sbp_profiling_MsgProfilingSystemInfo"); + tcase_add_test(tc_acq, test_auto_check_sbp_profiling_MsgProfilingSystemInfo); + suite_add_tcase(s, tc_acq); + return s; +} \ No newline at end of file diff --git a/c/test/auto_check_sbp_profiling_MsgProfilingThreadInfo.c b/c/test/auto_check_sbp_profiling_MsgProfilingThreadInfo.c new file mode 100644 index 0000000000..cc4b122c88 --- /dev/null +++ b/c/test/auto_check_sbp_profiling_MsgProfilingThreadInfo.c @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2015-2021 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +// This file was auto-generated from +// spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingThreadInfo.yaml by +// generate.py. Do not modify by hand! + +#include +#include +#include +#include // for debugging +#include // for malloc + +static struct { + u32 n_callbacks_logged; + u16 sender_id; + sbp_msg_type_t msg_type; + sbp_msg_t msg; + void *context; +} last_msg; + +static size_t dummy_wr = 0; +static size_t dummy_rd = 0; +static u8 dummy_buff[1024]; +static void *last_io_context; + +static void *DUMMY_MEMORY_FOR_CALLBACKS = (void *)0xdeadbeef; +static void *DUMMY_MEMORY_FOR_IO = (void *)0xdead0000; + +static void dummy_reset() { + dummy_rd = dummy_wr = 0; + memset(dummy_buff, 0, sizeof(dummy_buff)); +} + +static s32 dummy_write(u8 *buff, u32 n, void *context) { + last_io_context = context; + size_t real_n = n; //(dummy_n > n) ? n : dummy_n; + memcpy(dummy_buff + dummy_wr, buff, real_n); + dummy_wr += real_n; + return (s32)real_n; +} + +static s32 dummy_read(u8 *buff, u32 n, void *context) { + last_io_context = context; + size_t real_n = n; //(dummy_n > n) ? n : dummy_n; + memcpy(buff, dummy_buff + dummy_rd, real_n); + dummy_rd += real_n; + return (s32)real_n; +} + +static void logging_reset() { memset(&last_msg, 0, sizeof(last_msg)); } + +static void msg_callback(u16 sender_id, sbp_msg_type_t msg_type, + const sbp_msg_t *msg, void *context) { + last_msg.n_callbacks_logged++; + last_msg.sender_id = sender_id; + last_msg.msg_type = msg_type; + last_msg.msg = *msg; + last_msg.context = context; +} + +START_TEST(test_auto_check_sbp_profiling_MsgProfilingThreadInfo) { + static sbp_msg_callbacks_node_t n; + + // State of the SBP message parser. + // Must be statically allocated. + sbp_state_t sbp_state; + + // + // Run tests: + // + // Test successful parsing of a message + { + // SBP parser state must be initialized before sbp_process is called. + // We re-initialize before every test so that callbacks for the same message + // types can be + // allocated multiple times across different tests. + sbp_state_init(&sbp_state); + + sbp_state_set_io_context(&sbp_state, &DUMMY_MEMORY_FOR_IO); + + logging_reset(); + + sbp_callback_register(&sbp_state, 0xcf02, &msg_callback, + &DUMMY_MEMORY_FOR_CALLBACKS, &n); + + u8 encoded_frame[] = { + 85, 2, 207, 0, 16, 39, 119, 91, 10, 0, 0, 0, + 0, 0, 110, 5, 155, 0, 0, 0, 0, 0, 1, 0, + 0, 128, 0, 208, 53, 4, 0, 70, 117, 115, 105, 111, + 110, 32, 101, 110, 103, 105, 110, 101, 0, 242, 170, + }; + + dummy_reset(); + + sbp_msg_t test_msg; + memset(&test_msg, 0, sizeof(test_msg)); + + test_msg.profiling_thread_info.age = 10159470; + + size_t written; + ck_assert_msg( + sbp_msg_profiling_thread_info_name_set( + &test_msg.profiling_thread_info, "Fusion engine", false, &written), + "Can't assign text"); + ck_assert_msg(written == strlen("Fusion engine"), + "Wrote different to expected"); + ck_assert_msg(sbp_msg_profiling_thread_info_name_encoded_len( + &test_msg.profiling_thread_info) == 14, + "String not encoded properly"); + + test_msg.profiling_thread_info.stack_size = 8388608; + + test_msg.profiling_thread_info.stack_usage = 275920; + + test_msg.profiling_thread_info.state = 1; + + test_msg.profiling_thread_info.total_cpu_time = 678775; + + sbp_message_send(&sbp_state, SbpMsgProfilingThreadInfo, 4096, &test_msg, + &dummy_write); + + ck_assert_msg(dummy_wr == sizeof(encoded_frame), + "not enough data was written to dummy_buff (expected: %zu, " + "actual: %zu)", + sizeof(encoded_frame), dummy_wr); + ck_assert_msg(memcmp(dummy_buff, encoded_frame, sizeof(encoded_frame)) == 0, + "frame was not encoded properly"); + + while (dummy_rd < dummy_wr) { + ck_assert_msg(sbp_process(&sbp_state, &dummy_read) >= SBP_OK, + "sbp_process threw an error!"); + } + + ck_assert_msg(last_msg.n_callbacks_logged == 1, + "msg_callback: one callback should have been logged"); + ck_assert_msg(last_msg.sender_id == 4096, + "msg_callback: sender_id decoded incorrectly"); + + ck_assert_msg(sbp_message_cmp(SbpMsgProfilingThreadInfo, &last_msg.msg, + &test_msg) == 0, + "Sent and received messages did not compare equal"); + + ck_assert_msg(last_msg.msg.profiling_thread_info.age == 10159470, + "incorrect value for last_msg.msg.profiling_thread_info.age, " + "expected 10159470, is %" PRId64, + (int64_t)last_msg.msg.profiling_thread_info.age); + + ck_assert_msg(sbp_msg_profiling_thread_info_name_encoded_len( + &last_msg.msg.profiling_thread_info) == 14, + "Invalid encoded len"); + ck_assert_msg(strcmp(sbp_msg_profiling_thread_info_name_get( + &last_msg.msg.profiling_thread_info), + "Fusion engine") == 0, + "String not decoded properly"); + + ck_assert_msg( + last_msg.msg.profiling_thread_info.stack_size == 8388608, + "incorrect value for last_msg.msg.profiling_thread_info.stack_size, " + "expected 8388608, is %" PRId64, + (int64_t)last_msg.msg.profiling_thread_info.stack_size); + + ck_assert_msg( + last_msg.msg.profiling_thread_info.stack_usage == 275920, + "incorrect value for last_msg.msg.profiling_thread_info.stack_usage, " + "expected 275920, is %" PRId64, + (int64_t)last_msg.msg.profiling_thread_info.stack_usage); + + ck_assert_msg( + last_msg.msg.profiling_thread_info.state == 1, + "incorrect value for last_msg.msg.profiling_thread_info.state, " + "expected 1, is %" PRId64, + (int64_t)last_msg.msg.profiling_thread_info.state); + + ck_assert_msg(last_msg.msg.profiling_thread_info.total_cpu_time == 678775, + "incorrect value for " + "last_msg.msg.profiling_thread_info.total_cpu_time, expected " + "678775, is %" PRId64, + (int64_t)last_msg.msg.profiling_thread_info.total_cpu_time); + } +} +END_TEST + +Suite *auto_check_sbp_profiling_MsgProfilingThreadInfo_suite(void) { + Suite *s = suite_create( + "SBP generated test suite: " + "auto_check_sbp_profiling_MsgProfilingThreadInfo"); + TCase *tc_acq = tcase_create( + "Automated_Suite_auto_check_sbp_profiling_MsgProfilingThreadInfo"); + tcase_add_test(tc_acq, test_auto_check_sbp_profiling_MsgProfilingThreadInfo); + suite_add_tcase(s, tc_acq); + return s; +} \ No newline at end of file diff --git a/c/test/check_main.c b/c/test/check_main.c index c392aa1269..1b3b63164d 100644 --- a/c/test/check_main.c +++ b/c/test/check_main.c @@ -204,6 +204,12 @@ int main(void) { srunner_add_suite(sr, auto_check_sbp_piksi_MsgUartState_suite()); srunner_add_suite(sr, auto_check_sbp_piksi_MsgUartStateDepA_suite()); srunner_add_suite(sr, auto_check_sbp_profiling_MsgMeasurementPoint_suite()); + srunner_add_suite( + sr, auto_check_sbp_profiling_MsgProfilingResourceCounter_suite()); + srunner_add_suite(sr, + auto_check_sbp_profiling_MsgProfilingSystemInfo_suite()); + srunner_add_suite(sr, + auto_check_sbp_profiling_MsgProfilingThreadInfo_suite()); srunner_add_suite(sr, auto_check_sbp_sbas_MsgSbasRaw_suite()); srunner_add_suite(sr, auto_check_sbp_settings_MsgSettingsReadByIndexDone_suite()); diff --git a/c/test/check_suites.h b/c/test/check_suites.h index e712b6f95d..db661aec8a 100644 --- a/c/test/check_suites.h +++ b/c/test/check_suites.h @@ -182,6 +182,9 @@ Suite* auto_check_sbp_piksi_MsgThreadState_suite(void); Suite* auto_check_sbp_piksi_MsgUartState_suite(void); Suite* auto_check_sbp_piksi_MsgUartStateDepA_suite(void); Suite* auto_check_sbp_profiling_MsgMeasurementPoint_suite(void); +Suite* auto_check_sbp_profiling_MsgProfilingResourceCounter_suite(void); +Suite* auto_check_sbp_profiling_MsgProfilingSystemInfo_suite(void); +Suite* auto_check_sbp_profiling_MsgProfilingThreadInfo_suite(void); Suite* auto_check_sbp_sbas_MsgSbasRaw_suite(void); Suite* auto_check_sbp_settings_MsgSettingsReadByIndexDone_suite(void); Suite* auto_check_sbp_settings_MsgSettingsReadByIndexReq_suite(void); diff --git a/c/test/cpp/auto_check_sbp_profiling_MsgProfilingResourceCounter.cc b/c/test/cpp/auto_check_sbp_profiling_MsgProfilingResourceCounter.cc new file mode 100644 index 0000000000..0cd17ca6e3 --- /dev/null +++ b/c/test/cpp/auto_check_sbp_profiling_MsgProfilingResourceCounter.cc @@ -0,0 +1,1317 @@ +/* + * Copyright (C) 2015-2021 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +// This file was auto-generated from +// spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingResourceCounter.yaml +// by generate.py. Do not modify by hand! + +#include +#include +#include +#include +#include + +namespace { + +template +void assign(T &dest, const U &source) { + dest = static_cast(source); +} +class Testauto_check_sbp_profiling_MsgProfilingResourceCounter0 + : public ::testing::Test { + public: + Testauto_check_sbp_profiling_MsgProfilingResourceCounter0() { + assign(test_msg_.buckets[0].cv, 2); + assign(test_msg_.buckets[0].heap_bytes_alloc, 927480); + assign(test_msg_.buckets[0].heap_bytes_free, 0); + assign(test_msg_.buckets[0].io, 0); + assign(test_msg_.buckets[0].io_read, 0); + assign(test_msg_.buckets[0].io_write, 0); + assign(test_msg_.buckets[0].mutex, 2); + { + const char assign_string[] = { + (char)70, (char)117, (char)115, (char)105, (char)111, (char)110, + (char)32, (char)101, (char)110, (char)103, (char)105, (char)110, + (char)101, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0}; + memcpy(test_msg_.buckets[0].name, assign_string, sizeof(assign_string)); + } + assign(test_msg_.buckets[0].thread, 1); + + assign(test_msg_.buckets[1].cv, 1); + assign(test_msg_.buckets[1].heap_bytes_alloc, 84454); + assign(test_msg_.buckets[1].heap_bytes_free, 0); + assign(test_msg_.buckets[1].io, 1); + assign(test_msg_.buckets[1].io_read, 19520); + assign(test_msg_.buckets[1].io_write, 879); + assign(test_msg_.buckets[1].mutex, 1); + { + const char assign_string[] = { + (char)78, (char)84, (char)82, (char)73, (char)80, (char)32, + (char)99, (char)108, (char)105, (char)101, (char)110, (char)116, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0}; + memcpy(test_msg_.buckets[1].name, assign_string, sizeof(assign_string)); + } + assign(test_msg_.buckets[1].thread, 1); + + assign(test_msg_.buckets[2].cv, 1); + assign(test_msg_.buckets[2].heap_bytes_alloc, 4328776); + assign(test_msg_.buckets[2].heap_bytes_free, 0); + assign(test_msg_.buckets[2].io, 0); + assign(test_msg_.buckets[2].io_read, 0); + assign(test_msg_.buckets[2].io_write, 0); + assign(test_msg_.buckets[2].mutex, 1); + { + const char assign_string[] = { + (char)83, (char)83, (char)82, (char)50, (char)79, (char)83, (char)82, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0}; + memcpy(test_msg_.buckets[2].name, assign_string, sizeof(assign_string)); + } + assign(test_msg_.buckets[2].thread, 1); + + assign(test_msg_.buckets[3].cv, 1); + assign(test_msg_.buckets[3].heap_bytes_alloc, 247112); + assign(test_msg_.buckets[3].heap_bytes_free, 0); + assign(test_msg_.buckets[3].io, 0); + assign(test_msg_.buckets[3].io_read, 0); + assign(test_msg_.buckets[3].io_write, 0); + assign(test_msg_.buckets[3].mutex, 2); + { + const char assign_string[] = { + (char)80, (char)101, (char)114, (char)105, (char)111, (char)100, + (char)105, (char)99, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0}; + memcpy(test_msg_.buckets[3].name, assign_string, sizeof(assign_string)); + } + assign(test_msg_.buckets[3].thread, 1); + + assign(test_msg_.buckets[4].cv, 1); + assign(test_msg_.buckets[4].heap_bytes_alloc, 18305); + assign(test_msg_.buckets[4].heap_bytes_free, 0); + assign(test_msg_.buckets[4].io, 1); + assign(test_msg_.buckets[4].io_read, 26207); + assign(test_msg_.buckets[4].io_write, 0); + assign(test_msg_.buckets[4].mutex, 1); + { + const char assign_string[] = { + (char)73, (char)77, (char)85, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0}; + memcpy(test_msg_.buckets[4].name, assign_string, sizeof(assign_string)); + } + assign(test_msg_.buckets[4].thread, 1); + + assign(test_msg_.buckets[5].cv, 2); + assign(test_msg_.buckets[5].heap_bytes_alloc, 43507); + assign(test_msg_.buckets[5].heap_bytes_free, 0); + assign(test_msg_.buckets[5].io, 2); + assign(test_msg_.buckets[5].io_read, 498); + assign(test_msg_.buckets[5].io_write, 235451); + assign(test_msg_.buckets[5].mutex, 2); + { + const char assign_string[] = { + (char)115, (char)98, (char)112, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, + (char)0, (char)0, (char)0, (char)0, (char)0, (char)0, (char)0}; + memcpy(test_msg_.buckets[5].name, assign_string, sizeof(assign_string)); + } + assign(test_msg_.buckets[5].thread, 5); + assign(test_msg_.n_buckets, 6); + assign(test_msg_.seq_len, 3); + assign(test_msg_.seq_no, 1); + } + + class SlowReader final : public sbp::IReader { + public: + SlowReader(const uint8_t *buf, uint32_t len) + : sbp::IReader(), buf_{buf}, len_{len} {} + + s32 read(uint8_t *buf, const uint32_t n) override { + if (n == 0) { + return 0; + } + if (remaining() == 0) { + return -1; + } + skip_next_read = !skip_next_read; + if (skip_next_read) { + return 0; + } + uint32_t real_n = std::min(n, 1u); + memcpy(buf, buf_ + offset_, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return len_ - offset_; } + + static s32 read_static(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->read(buf, len); + } + + private: + const uint8_t *buf_; + uint32_t len_; + uint32_t offset_{}; + bool skip_next_read{}; + }; + + class Reader final : public sbp::IReader { + public: + Reader(const uint8_t *buf, uint32_t len) + : sbp::IReader(), buf_{buf}, len_{len} {} + + s32 read(uint8_t *buf, const uint32_t n) override { + if (n == 0) { + return 0; + } + uint32_t real_n = std::min(n, remaining()); + if (real_n == 0) { + return -1; + } + memcpy(buf, buf_ + offset_, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return len_ - offset_; } + + static s32 read_static(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->read(buf, len); + } + + private: + const uint8_t *buf_; + uint32_t len_; + uint32_t offset_{}; + }; + + class SlowWriter final : public sbp::IWriter { + public: + explicit SlowWriter(uint32_t max_len = cMaxLen) + : IWriter(), max_len_{max_len} {} + static constexpr uint32_t cMaxLen = SBP_MAX_FRAME_LEN; + + s32 write(const uint8_t *buf, uint32_t n) override { + if (n == 0) { + return 0; + } + uint32_t real_n = std::min(n, 1u); + if (real_n == 0) { + return -1; + } + memcpy(buf_ + offset_, buf, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return max_len_ - offset_; } + + const uint8_t *data() const noexcept { return buf_; } + + uint32_t len() const noexcept { return offset_; } + + static s32 write_static(const uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + static s32 write_c(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + private: + uint8_t buf_[cMaxLen]; + uint32_t max_len_; + uint32_t offset_{}; + }; + + class Writer final : public sbp::IWriter { + public: + explicit Writer(uint32_t max_len = cMaxLen) + : IWriter(), max_len_{max_len} {} + static constexpr uint32_t cMaxLen = SBP_MAX_FRAME_LEN; + + s32 write(const uint8_t *buf, uint32_t n) override { + if (n == 0) { + return 0; + } + uint32_t real_n = std::min(n, remaining()); + if (real_n == 0) { + return -1; + } + memcpy(buf_ + offset_, buf, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return max_len_ - offset_; } + + const uint8_t *data() const noexcept { return buf_; } + + uint32_t len() const noexcept { return offset_; } + + static s32 write_static(const uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + static s32 write_c(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + private: + uint8_t buf_[cMaxLen]; + uint32_t max_len_; + uint32_t offset_{}; + }; + + struct CppHandler final + : public sbp::MessageHandler { + using sbp::MessageHandler< + sbp_msg_profiling_resource_counter_t>::MessageHandler; + + struct Output final { + uint16_t sender_id; + sbp_msg_profiling_resource_counter_t msg; + }; + + std::vector outputs{}; + + protected: + void handle_sbp_msg( + uint16_t sender_id, + const sbp_msg_profiling_resource_counter_t &msg) override { + outputs.emplace_back(); + outputs.back().sender_id = sender_id; + memcpy(&outputs.back().msg, &msg, sizeof(msg)); + } + }; + + struct CHandler final { + explicit CHandler(sbp_state_t *state) : state_{state} { + sbp_callback_register(state, SbpMsgProfilingResourceCounter, + &CHandler::callback_static, this, &node_); + } + + ~CHandler() { sbp_remove_callback(state_, &node_); } + + struct Output final { + uint16_t sender_id; + sbp_msg_profiling_resource_counter_t msg; + }; + + std::vector outputs{}; + + private: + void callback(uint16_t sender_id, sbp_msg_type_t msg_type, + const sbp_msg_t *msg) { + ASSERT_EQ(msg_type, SbpMsgProfilingResourceCounter); + outputs.emplace_back(); + outputs.back().sender_id = sender_id; + memcpy(&outputs.back().msg, &msg->profiling_resource_counter, + sizeof(msg->profiling_resource_counter)); + } + + static void callback_static(uint16_t sender_id, sbp_msg_type_t msg_type, + const sbp_msg_t *msg, void *ctx) { + static_cast(ctx)->callback(sender_id, msg_type, msg); + } + + sbp_msg_callbacks_node_t node_{}; + sbp_state_t *state_; + }; + + struct TestMsgInfo { + sbp_msg_profiling_resource_counter_t test_msg; + sbp_msg_t test_msg_wrapped; + sbp_msg_type_t msg_type; + uint16_t sender_id; + uint8_t preamble; + uint16_t crc; + const uint8_t *encoded_frame; + uint32_t frame_len; + const uint8_t *encoded_payload; + uint8_t payload_len; + + Reader get_frame_reader() const noexcept { + return Reader{encoded_frame, frame_len}; + } + + Reader get_frame_reader(uint32_t max) const noexcept { + assert(max <= frame_len); + return Reader{encoded_frame, max}; + } + + SlowReader get_slow_frame_reader() const noexcept { + return SlowReader{encoded_frame, frame_len}; + } + + Writer get_frame_writer() const noexcept { return Writer{frame_len}; } + + Writer get_frame_writer(uint32_t max) const noexcept { return Writer{max}; } + + SlowWriter get_slow_frame_writer() const noexcept { + return SlowWriter{frame_len}; + } + }; + + TestMsgInfo get_test_msg_info() const noexcept { + TestMsgInfo info; + memcpy(&info.test_msg, &test_msg_, sizeof(test_msg_)); + memcpy(&info.test_msg_wrapped.profiling_resource_counter, &test_msg_, + sizeof(test_msg_)); + info.msg_type = static_cast(SbpMsgProfilingResourceCounter); + info.sender_id = 4096; + info.preamble = 0x55; + info.crc = 0x99b5; + info.encoded_frame = encoded_frame_; + info.frame_len = sizeof(encoded_frame_); + info.encoded_payload = encoded_payload_; + info.payload_len = 248; + + return info; + } + + protected: + void comparison_tests(const sbp_msg_profiling_resource_counter_t &lesser, + const sbp_msg_profiling_resource_counter_t &greater) { + sbp_msg_t wrapped_lesser = + sbp::MessageTraits::to_sbp_msg( + lesser); + sbp_msg_t wrapped_greater = + sbp::MessageTraits::to_sbp_msg( + greater); + + EXPECT_EQ(sbp_msg_profiling_resource_counter_cmp(&lesser, &lesser), 0); + EXPECT_EQ(sbp_msg_profiling_resource_counter_cmp(&greater, &greater), 0); + EXPECT_LE(sbp_msg_profiling_resource_counter_cmp(&lesser, &greater), 0); + EXPECT_GT(sbp_msg_profiling_resource_counter_cmp(&greater, &lesser), 0); + + EXPECT_EQ(sbp_message_cmp(SbpMsgProfilingResourceCounter, &wrapped_lesser, + &wrapped_lesser), + 0); + EXPECT_EQ(sbp_message_cmp(SbpMsgProfilingResourceCounter, &wrapped_greater, + &wrapped_greater), + 0); + EXPECT_LE(sbp_message_cmp(SbpMsgProfilingResourceCounter, &wrapped_lesser, + &wrapped_greater), + 0); + EXPECT_GT(sbp_message_cmp(SbpMsgProfilingResourceCounter, &wrapped_greater, + &wrapped_lesser), + 0); + + // lesser vs lesser + EXPECT_TRUE(lesser == lesser); + EXPECT_FALSE(lesser != lesser); + EXPECT_FALSE(lesser < lesser); + EXPECT_TRUE(lesser <= lesser); + EXPECT_FALSE(lesser > lesser); + EXPECT_TRUE(lesser >= lesser); + + // greater vs greater + EXPECT_TRUE(greater == greater); + EXPECT_FALSE(greater != greater); + EXPECT_FALSE(greater < greater); + EXPECT_TRUE(greater <= greater); + EXPECT_FALSE(greater > greater); + EXPECT_TRUE(greater >= greater); + + // lesser vs greater + EXPECT_FALSE(lesser == greater); + EXPECT_TRUE(lesser != greater); + EXPECT_TRUE(lesser < greater); + EXPECT_TRUE(lesser <= greater); + EXPECT_FALSE(lesser > greater); + EXPECT_FALSE(lesser >= greater); + + // greater vs lesser + EXPECT_FALSE(greater == lesser); + EXPECT_TRUE(greater != lesser); + EXPECT_FALSE(greater < lesser); + EXPECT_FALSE(greater <= lesser); + EXPECT_TRUE(greater > lesser); + EXPECT_TRUE(greater >= lesser); + } + + template ::value, bool> = true> + void make_lesser_greater(T &lesser, T &greater) { + if (lesser > std::numeric_limits::min()) { + lesser--; + } else { + greater++; + } + } + + template ::value, bool> = true> + void make_lesser_greater(T &lesser, T &greater) { + (void)lesser; + greater += static_cast(1.0); + } + + void make_lesser_greater(sbp_string_t &lesser, sbp_string_t &greater) { + if (greater.data[0] == 'z') { + lesser.data[0]--; + } else { + greater.data[0]++; + } + } + + template + void make_lesser_greater(char (&lesser)[N], char (&greater)[N]) { + if (lesser[0] == 'z') { + lesser[0]--; + } else { + greater[0]++; + } + } + + private: + sbp_msg_profiling_resource_counter_t test_msg_{}; + uint8_t encoded_frame_[248 + 8] = { + 85, 3, 207, 0, 16, 248, 1, 3, 70, 117, 115, 105, 111, 110, 32, + 101, 110, 103, 105, 110, 101, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 2, 2, 0, 248, 38, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 78, 84, 82, 73, 80, 32, 99, 108, 105, 101, 110, + 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 230, + 73, 1, 0, 0, 0, 0, 0, 111, 3, 0, 0, 64, 76, 0, 0, + 83, 83, 82, 50, 79, 83, 82, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 72, 13, 66, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 101, 114, 105, + 111, 100, 105, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 1, 0, 72, 197, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 73, 77, 85, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 129, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, + 102, 0, 0, 115, 98, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 2, 2, 2, 243, 169, + 0, 0, 0, 0, 0, 0, 187, 151, 3, 0, 242, 1, 0, 0, 181, + 153, + }; + uint8_t encoded_payload_[248] = { + 1, 3, 70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 248, 38, 14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 84, + 82, 73, 80, 32, 99, 108, 105, 101, 110, 116, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 230, 73, 1, 0, 0, 0, 0, + 0, 111, 3, 0, 0, 64, 76, 0, 0, 83, 83, 82, 50, 79, 83, + 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 72, 13, 66, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 80, 101, 114, 105, 111, 100, 105, 99, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, + 72, 197, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 73, 77, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 129, 71, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 95, 102, 0, 0, 115, 98, 112, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 2, 2, 2, 243, 169, 0, 0, 0, 0, 0, 0, + 187, 151, 3, 0, 242, 1, 0, 0, + }; +}; + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, EncodedLen) { + auto info = get_test_msg_info(); + EXPECT_EQ(sbp_msg_profiling_resource_counter_encoded_len(&info.test_msg), + info.payload_len); + + EXPECT_EQ(sbp_message_encoded_len(SbpMsgProfilingResourceCounter, + &info.test_msg_wrapped), + info.payload_len); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, EncodeToBuf) { + auto info = get_test_msg_info(); + uint8_t buf[248]; + uint8_t n_written; + + EXPECT_EQ(sbp_msg_profiling_resource_counter_encode( + &buf[0], sizeof(buf), &n_written, &info.test_msg), + SBP_OK); + EXPECT_EQ(n_written, 248); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 248), 0); + + memset(&buf[0], 0, sizeof(buf)); + EXPECT_EQ(sbp_message_encode(&buf[0], sizeof(buf), &n_written, + SbpMsgProfilingResourceCounter, + &info.test_msg_wrapped), + SBP_OK); + EXPECT_EQ(n_written, 248); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 248), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + EncodeToBufWithoutNwritten) { + auto info = get_test_msg_info(); + uint8_t buf[248]; + + EXPECT_EQ(sbp_msg_profiling_resource_counter_encode(&buf[0], sizeof(buf), + nullptr, &info.test_msg), + SBP_OK); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 248), 0); +} +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + EncodedToBufUnderflow) { + auto info = get_test_msg_info(); + uint8_t buf[248]; + + for (uint8_t i = 0; i < 248; i++) { + EXPECT_EQ(sbp_msg_profiling_resource_counter_encode(&buf[0], i, nullptr, + &info.test_msg), + SBP_ENCODE_ERROR); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + DecodeFromBuf) { + auto info = get_test_msg_info(); + sbp_msg_profiling_resource_counter_t msg{}; + uint8_t n_read; + + EXPECT_EQ(sbp_msg_profiling_resource_counter_decode( + &info.encoded_payload[0], info.payload_len, &n_read, &msg), + SBP_OK); + EXPECT_EQ(n_read, 248); + EXPECT_EQ(msg, info.test_msg); + + sbp_msg_t wrapped_msg{}; + EXPECT_EQ( + sbp_message_decode(&info.encoded_payload[0], info.payload_len, &n_read, + SbpMsgProfilingResourceCounter, &wrapped_msg), + SBP_OK); + EXPECT_EQ(n_read, 248); + EXPECT_EQ(msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + DecodeFromBufWithoutNread) { + auto info = get_test_msg_info(); + sbp_msg_profiling_resource_counter_t msg{}; + + EXPECT_EQ(sbp_msg_profiling_resource_counter_decode( + &info.encoded_payload[0], info.payload_len, nullptr, &msg), + SBP_OK); + EXPECT_EQ(msg, info.test_msg); +} +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + DecodeFromBufUnderflow) { + auto info = get_test_msg_info(); + sbp_msg_profiling_resource_counter_t msg{}; + + for (uint8_t i = 0; i < info.payload_len; i++) { + int expected_return = SBP_DECODE_ERROR; + size_t overhead = []() -> size_t { + sbp_msg_profiling_resource_counter_t t{}; + return sbp_msg_profiling_resource_counter_encoded_len(&t); + }(); + size_t elem_size = []() -> size_t { + sbp_msg_profiling_resource_counter_t t{}; + t.n_buckets = 1; + return sbp_msg_profiling_resource_counter_encoded_len(&t); + }() - overhead; + + if (i >= overhead) { + if (((i - overhead) % elem_size) == 0) { + expected_return = SBP_OK; + } + } + + EXPECT_EQ(sbp_msg_profiling_resource_counter_decode( + &info.encoded_payload[0], i, nullptr, &msg), + expected_return); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + ReceiveThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto reader = info.get_frame_reader(); + sbp_state_set_io_context(&state, &reader); + + CHandler handler{&state}; + + while (reader.remaining() > 0) { + EXPECT_GE(sbp_process(&state, &Reader::read_static), SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + ReceiveThroughSbpStateUnderflow) { + auto info = get_test_msg_info(); + + for (uint32_t i = 0; i < info.frame_len; i++) { + sbp_state_t state; + sbp_state_init(&state); + + auto reader = info.get_frame_reader(i); + sbp_state_set_io_context(&state, &reader); + + CHandler handler(&state); + + int most_recent_return = sbp_process(&state, &Reader::read_static); + while (most_recent_return == SBP_OK || reader.remaining() > 0) { + most_recent_return = sbp_process(&state, &Reader::read_static); + } + + EXPECT_NE(most_recent_return, SBP_OK); + EXPECT_EQ(reader.remaining(), 0); + + EXPECT_EQ(handler.outputs.size(), 0); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, SlowRead) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto reader = info.get_slow_frame_reader(); + sbp_state_set_io_context(&state, &reader); + + CHandler handler{&state}; + + while (reader.remaining() > 0) { + EXPECT_GE(sbp_process(&state, &SlowReader::read_static), SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, BadCRC) { + auto info = get_test_msg_info(); + uint8_t buf[SBP_MAX_FRAME_LEN]; + memcpy(&buf[0], info.encoded_frame, info.frame_len); + + // Introduce a CRC error which should cause an error return and no callback + buf[info.frame_len - 1]++; + + sbp_state_t state; + sbp_state_init(&state); + + Reader reader{buf, info.frame_len}; + sbp_state_set_io_context(&state, &reader); + + CHandler handler{&state}; + + while (reader.remaining() > 0) { + int res = sbp_process(&state, &Reader::read_static); + EXPECT_EQ(res, reader.remaining() == 0 ? SBP_CRC_ERROR : SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + SendThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp_msg_profiling_resource_counter_send( + &state, info.sender_id, &info.test_msg, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), &info.encoded_frame[0], writer.len()), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + SendWrappedThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ( + sbp_message_send(&state, SbpMsgProfilingResourceCounter, info.sender_id, + &info.test_msg_wrapped, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + SendThroughSbpStateUnderflow) { + auto info = get_test_msg_info(); + + for (uint32_t i = 0; i < info.frame_len; i++) { + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(i); + sbp_state_set_io_context(&state, &writer); + + EXPECT_NE( + sbp_message_send(&state, SbpMsgProfilingResourceCounter, info.sender_id, + &info.test_msg_wrapped, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), i); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, i), 0); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + DISABLED_SlowWrite) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_slow_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ( + sbp_message_send(&state, SbpMsgProfilingResourceCounter, info.sender_id, + &info.test_msg_wrapped, &SlowWriter::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, Comparison) { + auto info = get_test_msg_info(); + + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[0].cv, greater.buckets[0].cv); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[0].heap_bytes_alloc, + greater.buckets[0].heap_bytes_alloc); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[0].heap_bytes_free, + greater.buckets[0].heap_bytes_free); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[0].io, greater.buckets[0].io); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[0].io_read, greater.buckets[0].io_read); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[0].io_write, + greater.buckets[0].io_write); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[0].mutex, greater.buckets[0].mutex); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[0].name, greater.buckets[0].name); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[0].thread, greater.buckets[0].thread); + comparison_tests(lesser, greater); + } + + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[1].cv, greater.buckets[1].cv); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[1].heap_bytes_alloc, + greater.buckets[1].heap_bytes_alloc); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[1].heap_bytes_free, + greater.buckets[1].heap_bytes_free); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[1].io, greater.buckets[1].io); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[1].io_read, greater.buckets[1].io_read); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[1].io_write, + greater.buckets[1].io_write); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[1].mutex, greater.buckets[1].mutex); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[1].name, greater.buckets[1].name); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[1].thread, greater.buckets[1].thread); + comparison_tests(lesser, greater); + } + + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[2].cv, greater.buckets[2].cv); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[2].heap_bytes_alloc, + greater.buckets[2].heap_bytes_alloc); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[2].heap_bytes_free, + greater.buckets[2].heap_bytes_free); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[2].io, greater.buckets[2].io); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[2].io_read, greater.buckets[2].io_read); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[2].io_write, + greater.buckets[2].io_write); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[2].mutex, greater.buckets[2].mutex); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[2].name, greater.buckets[2].name); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[2].thread, greater.buckets[2].thread); + comparison_tests(lesser, greater); + } + + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[3].cv, greater.buckets[3].cv); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[3].heap_bytes_alloc, + greater.buckets[3].heap_bytes_alloc); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[3].heap_bytes_free, + greater.buckets[3].heap_bytes_free); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[3].io, greater.buckets[3].io); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[3].io_read, greater.buckets[3].io_read); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[3].io_write, + greater.buckets[3].io_write); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[3].mutex, greater.buckets[3].mutex); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[3].name, greater.buckets[3].name); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[3].thread, greater.buckets[3].thread); + comparison_tests(lesser, greater); + } + + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[4].cv, greater.buckets[4].cv); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[4].heap_bytes_alloc, + greater.buckets[4].heap_bytes_alloc); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[4].heap_bytes_free, + greater.buckets[4].heap_bytes_free); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[4].io, greater.buckets[4].io); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[4].io_read, greater.buckets[4].io_read); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[4].io_write, + greater.buckets[4].io_write); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[4].mutex, greater.buckets[4].mutex); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[4].name, greater.buckets[4].name); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[4].thread, greater.buckets[4].thread); + comparison_tests(lesser, greater); + } + + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[5].cv, greater.buckets[5].cv); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[5].heap_bytes_alloc, + greater.buckets[5].heap_bytes_alloc); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[5].heap_bytes_free, + greater.buckets[5].heap_bytes_free); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[5].io, greater.buckets[5].io); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[5].io_read, greater.buckets[5].io_read); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[5].io_write, + greater.buckets[5].io_write); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[5].mutex, greater.buckets[5].mutex); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[5].name, greater.buckets[5].name); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.buckets[5].thread, greater.buckets[5].thread); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.n_buckets, greater.n_buckets); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.seq_len, greater.seq_len); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_resource_counter_t lesser = info.test_msg; + sbp_msg_profiling_resource_counter_t greater = info.test_msg; + make_lesser_greater(lesser.seq_no, greater.seq_no); + comparison_tests(lesser, greater); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + CppTraitsProperties) { + // EXPECT_EQ(sbp::MessageTraits::id, + // SbpMsgProfilingResourceCounter); + EXPECT_STREQ(sbp::MessageTraits::name, + "MSG_PROFILING_RESOURCE_COUNTER"); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + CppTraitsFromSbpMsgT) { + auto info = get_test_msg_info(); + + const sbp_msg_t &const_sbp_msg_t = info.test_msg_wrapped; + sbp_msg_t &non_const_sbp_msg_t = info.test_msg_wrapped; + + const sbp_msg_profiling_resource_counter_t &const_unwrapped = + sbp::MessageTraits::get( + const_sbp_msg_t); + sbp_msg_profiling_resource_counter_t &non_const_unwrapped = + sbp::MessageTraits::get( + non_const_sbp_msg_t); + + EXPECT_EQ((const void *)&const_sbp_msg_t, (const void *)&const_unwrapped); + EXPECT_EQ((void *)&non_const_sbp_msg_t, (void *)&non_const_unwrapped); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + CppTraitsToSbpMsgT) { + auto info = get_test_msg_info(); + + sbp_msg_t msg1 = + sbp::MessageTraits::to_sbp_msg( + info.test_msg); + EXPECT_EQ(msg1.profiling_resource_counter, info.test_msg); + + sbp_msg_t msg2; + sbp::MessageTraits::to_sbp_msg( + info.test_msg, &msg2); + EXPECT_EQ(msg2.profiling_resource_counter, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + CppTraitsEncodedLen) { + auto info = get_test_msg_info(); + EXPECT_EQ( + sbp::MessageTraits::encoded_len( + info.test_msg), + info.payload_len); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + CppTraitsSendThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp::MessageTraits::send( + &state, info.sender_id, info.test_msg, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), &info.encoded_frame[0], writer.len()), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + CppTraitsEncodeToBuf) { + auto info = get_test_msg_info(); + uint8_t buf[248]; + uint8_t n_written; + + EXPECT_EQ(sbp::MessageTraits::encode( + &buf[0], sizeof(buf), &n_written, info.test_msg), + SBP_OK); + EXPECT_EQ(n_written, 248); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 248), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + CppTraitsDecodeFromBuf) { + auto info = get_test_msg_info(); + sbp_msg_profiling_resource_counter_t msg{}; + uint8_t n_read; + + EXPECT_EQ(sbp::MessageTraits::decode( + &info.encoded_payload[0], info.payload_len, &n_read, &msg), + SBP_OK); + EXPECT_EQ(n_read, 248); + EXPECT_EQ(msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + ReceiveThroughMessageHandler) { + auto info = get_test_msg_info(); + auto reader = info.get_frame_reader(); + + sbp::State state{}; + state.set_reader(&reader); + + CppHandler handler{&state}; + + while (reader.remaining() > 0) { + EXPECT_GE(state.process(), SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + ProcessSbpMsgTThroughMessageHandler) { + auto info = get_test_msg_info(); + sbp::State state{}; + CppHandler handler(&state); + + state.process_message(info.sender_id, SbpMsgProfilingResourceCounter, + &info.test_msg_wrapped); + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + SendThroughCppState) { + auto info = get_test_msg_info(); + auto writer = info.get_frame_writer(); + + sbp::State state{}; + state.set_writer(&writer); + + EXPECT_EQ(state.send_message(info.sender_id, info.test_msg), SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingResourceCounter0, + SendWrappedSbpMsgTThroughCppState) { + auto info = get_test_msg_info(); + auto writer = info.get_frame_writer(); + + sbp::State state{}; + state.set_writer(&writer); + + EXPECT_EQ(state.send_message(info.sender_id, SbpMsgProfilingResourceCounter, + info.test_msg_wrapped), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +} // namespace \ No newline at end of file diff --git a/c/test/cpp/auto_check_sbp_profiling_MsgProfilingSystemInfo.cc b/c/test/cpp/auto_check_sbp_profiling_MsgProfilingSystemInfo.cc new file mode 100644 index 0000000000..996e4ed7ae --- /dev/null +++ b/c/test/cpp/auto_check_sbp_profiling_MsgProfilingSystemInfo.cc @@ -0,0 +1,824 @@ +/* + * Copyright (C) 2015-2021 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +// This file was auto-generated from +// spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingSystemInfo.yaml by +// generate.py. Do not modify by hand! + +#include +#include +#include +#include +#include + +namespace { + +template +void assign(T &dest, const U &source) { + dest = static_cast(source); +} +class Testauto_check_sbp_profiling_MsgProfilingSystemInfo0 + : public ::testing::Test { + public: + Testauto_check_sbp_profiling_MsgProfilingSystemInfo0() { + assign(test_msg_.age, 10292338); + assign(test_msg_.heap_usage, 14861128); + assign(test_msg_.n_threads, 27); + assign(test_msg_.total_cpu_time, 3418210); + } + + class SlowReader final : public sbp::IReader { + public: + SlowReader(const uint8_t *buf, uint32_t len) + : sbp::IReader(), buf_{buf}, len_{len} {} + + s32 read(uint8_t *buf, const uint32_t n) override { + if (n == 0) { + return 0; + } + if (remaining() == 0) { + return -1; + } + skip_next_read = !skip_next_read; + if (skip_next_read) { + return 0; + } + uint32_t real_n = std::min(n, 1u); + memcpy(buf, buf_ + offset_, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return len_ - offset_; } + + static s32 read_static(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->read(buf, len); + } + + private: + const uint8_t *buf_; + uint32_t len_; + uint32_t offset_{}; + bool skip_next_read{}; + }; + + class Reader final : public sbp::IReader { + public: + Reader(const uint8_t *buf, uint32_t len) + : sbp::IReader(), buf_{buf}, len_{len} {} + + s32 read(uint8_t *buf, const uint32_t n) override { + if (n == 0) { + return 0; + } + uint32_t real_n = std::min(n, remaining()); + if (real_n == 0) { + return -1; + } + memcpy(buf, buf_ + offset_, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return len_ - offset_; } + + static s32 read_static(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->read(buf, len); + } + + private: + const uint8_t *buf_; + uint32_t len_; + uint32_t offset_{}; + }; + + class SlowWriter final : public sbp::IWriter { + public: + explicit SlowWriter(uint32_t max_len = cMaxLen) + : IWriter(), max_len_{max_len} {} + static constexpr uint32_t cMaxLen = SBP_MAX_FRAME_LEN; + + s32 write(const uint8_t *buf, uint32_t n) override { + if (n == 0) { + return 0; + } + uint32_t real_n = std::min(n, 1u); + if (real_n == 0) { + return -1; + } + memcpy(buf_ + offset_, buf, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return max_len_ - offset_; } + + const uint8_t *data() const noexcept { return buf_; } + + uint32_t len() const noexcept { return offset_; } + + static s32 write_static(const uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + static s32 write_c(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + private: + uint8_t buf_[cMaxLen]; + uint32_t max_len_; + uint32_t offset_{}; + }; + + class Writer final : public sbp::IWriter { + public: + explicit Writer(uint32_t max_len = cMaxLen) + : IWriter(), max_len_{max_len} {} + static constexpr uint32_t cMaxLen = SBP_MAX_FRAME_LEN; + + s32 write(const uint8_t *buf, uint32_t n) override { + if (n == 0) { + return 0; + } + uint32_t real_n = std::min(n, remaining()); + if (real_n == 0) { + return -1; + } + memcpy(buf_ + offset_, buf, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return max_len_ - offset_; } + + const uint8_t *data() const noexcept { return buf_; } + + uint32_t len() const noexcept { return offset_; } + + static s32 write_static(const uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + static s32 write_c(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + private: + uint8_t buf_[cMaxLen]; + uint32_t max_len_; + uint32_t offset_{}; + }; + + struct CppHandler final + : public sbp::MessageHandler { + using sbp::MessageHandler::MessageHandler; + + struct Output final { + uint16_t sender_id; + sbp_msg_profiling_system_info_t msg; + }; + + std::vector outputs{}; + + protected: + void handle_sbp_msg(uint16_t sender_id, + const sbp_msg_profiling_system_info_t &msg) override { + outputs.emplace_back(); + outputs.back().sender_id = sender_id; + memcpy(&outputs.back().msg, &msg, sizeof(msg)); + } + }; + + struct CHandler final { + explicit CHandler(sbp_state_t *state) : state_{state} { + sbp_callback_register(state, SbpMsgProfilingSystemInfo, + &CHandler::callback_static, this, &node_); + } + + ~CHandler() { sbp_remove_callback(state_, &node_); } + + struct Output final { + uint16_t sender_id; + sbp_msg_profiling_system_info_t msg; + }; + + std::vector outputs{}; + + private: + void callback(uint16_t sender_id, sbp_msg_type_t msg_type, + const sbp_msg_t *msg) { + ASSERT_EQ(msg_type, SbpMsgProfilingSystemInfo); + outputs.emplace_back(); + outputs.back().sender_id = sender_id; + memcpy(&outputs.back().msg, &msg->profiling_system_info, + sizeof(msg->profiling_system_info)); + } + + static void callback_static(uint16_t sender_id, sbp_msg_type_t msg_type, + const sbp_msg_t *msg, void *ctx) { + static_cast(ctx)->callback(sender_id, msg_type, msg); + } + + sbp_msg_callbacks_node_t node_{}; + sbp_state_t *state_; + }; + + struct TestMsgInfo { + sbp_msg_profiling_system_info_t test_msg; + sbp_msg_t test_msg_wrapped; + sbp_msg_type_t msg_type; + uint16_t sender_id; + uint8_t preamble; + uint16_t crc; + const uint8_t *encoded_frame; + uint32_t frame_len; + const uint8_t *encoded_payload; + uint8_t payload_len; + + Reader get_frame_reader() const noexcept { + return Reader{encoded_frame, frame_len}; + } + + Reader get_frame_reader(uint32_t max) const noexcept { + assert(max <= frame_len); + return Reader{encoded_frame, max}; + } + + SlowReader get_slow_frame_reader() const noexcept { + return SlowReader{encoded_frame, frame_len}; + } + + Writer get_frame_writer() const noexcept { return Writer{frame_len}; } + + Writer get_frame_writer(uint32_t max) const noexcept { return Writer{max}; } + + SlowWriter get_slow_frame_writer() const noexcept { + return SlowWriter{frame_len}; + } + }; + + TestMsgInfo get_test_msg_info() const noexcept { + TestMsgInfo info; + memcpy(&info.test_msg, &test_msg_, sizeof(test_msg_)); + memcpy(&info.test_msg_wrapped.profiling_system_info, &test_msg_, + sizeof(test_msg_)); + info.msg_type = static_cast(SbpMsgProfilingSystemInfo); + info.sender_id = 4096; + info.preamble = 0x55; + info.crc = 0x41fc; + info.encoded_frame = encoded_frame_; + info.frame_len = sizeof(encoded_frame_); + info.encoded_payload = encoded_payload_; + info.payload_len = 21; + + return info; + } + + protected: + void comparison_tests(const sbp_msg_profiling_system_info_t &lesser, + const sbp_msg_profiling_system_info_t &greater) { + sbp_msg_t wrapped_lesser = + sbp::MessageTraits::to_sbp_msg(lesser); + sbp_msg_t wrapped_greater = + sbp::MessageTraits::to_sbp_msg( + greater); + + EXPECT_EQ(sbp_msg_profiling_system_info_cmp(&lesser, &lesser), 0); + EXPECT_EQ(sbp_msg_profiling_system_info_cmp(&greater, &greater), 0); + EXPECT_LE(sbp_msg_profiling_system_info_cmp(&lesser, &greater), 0); + EXPECT_GT(sbp_msg_profiling_system_info_cmp(&greater, &lesser), 0); + + EXPECT_EQ(sbp_message_cmp(SbpMsgProfilingSystemInfo, &wrapped_lesser, + &wrapped_lesser), + 0); + EXPECT_EQ(sbp_message_cmp(SbpMsgProfilingSystemInfo, &wrapped_greater, + &wrapped_greater), + 0); + EXPECT_LE(sbp_message_cmp(SbpMsgProfilingSystemInfo, &wrapped_lesser, + &wrapped_greater), + 0); + EXPECT_GT(sbp_message_cmp(SbpMsgProfilingSystemInfo, &wrapped_greater, + &wrapped_lesser), + 0); + + // lesser vs lesser + EXPECT_TRUE(lesser == lesser); + EXPECT_FALSE(lesser != lesser); + EXPECT_FALSE(lesser < lesser); + EXPECT_TRUE(lesser <= lesser); + EXPECT_FALSE(lesser > lesser); + EXPECT_TRUE(lesser >= lesser); + + // greater vs greater + EXPECT_TRUE(greater == greater); + EXPECT_FALSE(greater != greater); + EXPECT_FALSE(greater < greater); + EXPECT_TRUE(greater <= greater); + EXPECT_FALSE(greater > greater); + EXPECT_TRUE(greater >= greater); + + // lesser vs greater + EXPECT_FALSE(lesser == greater); + EXPECT_TRUE(lesser != greater); + EXPECT_TRUE(lesser < greater); + EXPECT_TRUE(lesser <= greater); + EXPECT_FALSE(lesser > greater); + EXPECT_FALSE(lesser >= greater); + + // greater vs lesser + EXPECT_FALSE(greater == lesser); + EXPECT_TRUE(greater != lesser); + EXPECT_FALSE(greater < lesser); + EXPECT_FALSE(greater <= lesser); + EXPECT_TRUE(greater > lesser); + EXPECT_TRUE(greater >= lesser); + } + + template ::value, bool> = true> + void make_lesser_greater(T &lesser, T &greater) { + if (lesser > std::numeric_limits::min()) { + lesser--; + } else { + greater++; + } + } + + template ::value, bool> = true> + void make_lesser_greater(T &lesser, T &greater) { + (void)lesser; + greater += static_cast(1.0); + } + + void make_lesser_greater(sbp_string_t &lesser, sbp_string_t &greater) { + if (greater.data[0] == 'z') { + lesser.data[0]--; + } else { + greater.data[0]++; + } + } + + template + void make_lesser_greater(char (&lesser)[N], char (&greater)[N]) { + if (lesser[0] == 'z') { + lesser[0]--; + } else { + greater[0]++; + } + } + + private: + sbp_msg_profiling_system_info_t test_msg_{}; + uint8_t encoded_frame_[21 + 8] = { + 85, 1, 207, 0, 16, 21, 98, 40, 52, 0, 0, 0, 0, 0, 114, + 12, 157, 0, 0, 0, 0, 0, 27, 72, 195, 226, 0, 252, 65, + }; + uint8_t encoded_payload_[21] = { + 98, 40, 52, 0, 0, 0, 0, 0, 114, 12, 157, + 0, 0, 0, 0, 0, 27, 72, 195, 226, 0, + }; +}; + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, EncodedLen) { + auto info = get_test_msg_info(); + EXPECT_EQ(sbp_msg_profiling_system_info_encoded_len(&info.test_msg), + info.payload_len); + + EXPECT_EQ(sbp_message_encoded_len(SbpMsgProfilingSystemInfo, + &info.test_msg_wrapped), + info.payload_len); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, EncodeToBuf) { + auto info = get_test_msg_info(); + uint8_t buf[21]; + uint8_t n_written; + + EXPECT_EQ(sbp_msg_profiling_system_info_encode(&buf[0], sizeof(buf), + &n_written, &info.test_msg), + SBP_OK); + EXPECT_EQ(n_written, 21); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 21), 0); + + memset(&buf[0], 0, sizeof(buf)); + EXPECT_EQ( + sbp_message_encode(&buf[0], sizeof(buf), &n_written, + SbpMsgProfilingSystemInfo, &info.test_msg_wrapped), + SBP_OK); + EXPECT_EQ(n_written, 21); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 21), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + EncodeToBufWithoutNwritten) { + auto info = get_test_msg_info(); + uint8_t buf[21]; + + EXPECT_EQ(sbp_msg_profiling_system_info_encode(&buf[0], sizeof(buf), nullptr, + &info.test_msg), + SBP_OK); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 21), 0); +} +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + EncodedToBufUnderflow) { + auto info = get_test_msg_info(); + uint8_t buf[21]; + + for (uint8_t i = 0; i < 21; i++) { + EXPECT_EQ(sbp_msg_profiling_system_info_encode(&buf[0], i, nullptr, + &info.test_msg), + SBP_ENCODE_ERROR); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, DecodeFromBuf) { + auto info = get_test_msg_info(); + sbp_msg_profiling_system_info_t msg{}; + uint8_t n_read; + + EXPECT_EQ(sbp_msg_profiling_system_info_decode( + &info.encoded_payload[0], info.payload_len, &n_read, &msg), + SBP_OK); + EXPECT_EQ(n_read, 21); + EXPECT_EQ(msg, info.test_msg); + + sbp_msg_t wrapped_msg{}; + EXPECT_EQ( + sbp_message_decode(&info.encoded_payload[0], info.payload_len, &n_read, + SbpMsgProfilingSystemInfo, &wrapped_msg), + SBP_OK); + EXPECT_EQ(n_read, 21); + EXPECT_EQ(msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + DecodeFromBufWithoutNread) { + auto info = get_test_msg_info(); + sbp_msg_profiling_system_info_t msg{}; + + EXPECT_EQ(sbp_msg_profiling_system_info_decode( + &info.encoded_payload[0], info.payload_len, nullptr, &msg), + SBP_OK); + EXPECT_EQ(msg, info.test_msg); +} +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + DecodeFromBufUnderflow) { + auto info = get_test_msg_info(); + sbp_msg_profiling_system_info_t msg{}; + + for (uint8_t i = 0; i < info.payload_len; i++) { + int expected_return = SBP_DECODE_ERROR; + + EXPECT_EQ(sbp_msg_profiling_system_info_decode(&info.encoded_payload[0], i, + nullptr, &msg), + expected_return); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + ReceiveThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto reader = info.get_frame_reader(); + sbp_state_set_io_context(&state, &reader); + + CHandler handler{&state}; + + while (reader.remaining() > 0) { + EXPECT_GE(sbp_process(&state, &Reader::read_static), SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + ReceiveThroughSbpStateUnderflow) { + auto info = get_test_msg_info(); + + for (uint32_t i = 0; i < info.frame_len; i++) { + sbp_state_t state; + sbp_state_init(&state); + + auto reader = info.get_frame_reader(i); + sbp_state_set_io_context(&state, &reader); + + CHandler handler(&state); + + int most_recent_return = sbp_process(&state, &Reader::read_static); + while (most_recent_return == SBP_OK || reader.remaining() > 0) { + most_recent_return = sbp_process(&state, &Reader::read_static); + } + + EXPECT_NE(most_recent_return, SBP_OK); + EXPECT_EQ(reader.remaining(), 0); + + EXPECT_EQ(handler.outputs.size(), 0); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, SlowRead) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto reader = info.get_slow_frame_reader(); + sbp_state_set_io_context(&state, &reader); + + CHandler handler{&state}; + + while (reader.remaining() > 0) { + EXPECT_GE(sbp_process(&state, &SlowReader::read_static), SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, BadCRC) { + auto info = get_test_msg_info(); + uint8_t buf[SBP_MAX_FRAME_LEN]; + memcpy(&buf[0], info.encoded_frame, info.frame_len); + + // Introduce a CRC error which should cause an error return and no callback + buf[info.frame_len - 1]++; + + sbp_state_t state; + sbp_state_init(&state); + + Reader reader{buf, info.frame_len}; + sbp_state_set_io_context(&state, &reader); + + CHandler handler{&state}; + + while (reader.remaining() > 0) { + int res = sbp_process(&state, &Reader::read_static); + EXPECT_EQ(res, reader.remaining() == 0 ? SBP_CRC_ERROR : SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + SendThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp_msg_profiling_system_info_send( + &state, info.sender_id, &info.test_msg, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), &info.encoded_frame[0], writer.len()), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + SendWrappedThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp_message_send(&state, SbpMsgProfilingSystemInfo, info.sender_id, + &info.test_msg_wrapped, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + SendThroughSbpStateUnderflow) { + auto info = get_test_msg_info(); + + for (uint32_t i = 0; i < info.frame_len; i++) { + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(i); + sbp_state_set_io_context(&state, &writer); + + EXPECT_NE( + sbp_message_send(&state, SbpMsgProfilingSystemInfo, info.sender_id, + &info.test_msg_wrapped, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), i); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, i), 0); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + DISABLED_SlowWrite) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_slow_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp_message_send(&state, SbpMsgProfilingSystemInfo, info.sender_id, + &info.test_msg_wrapped, &SlowWriter::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, Comparison) { + auto info = get_test_msg_info(); + { + sbp_msg_profiling_system_info_t lesser = info.test_msg; + sbp_msg_profiling_system_info_t greater = info.test_msg; + make_lesser_greater(lesser.age, greater.age); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_system_info_t lesser = info.test_msg; + sbp_msg_profiling_system_info_t greater = info.test_msg; + make_lesser_greater(lesser.heap_usage, greater.heap_usage); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_system_info_t lesser = info.test_msg; + sbp_msg_profiling_system_info_t greater = info.test_msg; + make_lesser_greater(lesser.n_threads, greater.n_threads); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_system_info_t lesser = info.test_msg; + sbp_msg_profiling_system_info_t greater = info.test_msg; + make_lesser_greater(lesser.total_cpu_time, greater.total_cpu_time); + comparison_tests(lesser, greater); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + CppTraitsProperties) { + // EXPECT_EQ(sbp::MessageTraits::id, + // SbpMsgProfilingSystemInfo); + EXPECT_STREQ(sbp::MessageTraits::name, + "MSG_PROFILING_SYSTEM_INFO"); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + CppTraitsFromSbpMsgT) { + auto info = get_test_msg_info(); + + const sbp_msg_t &const_sbp_msg_t = info.test_msg_wrapped; + sbp_msg_t &non_const_sbp_msg_t = info.test_msg_wrapped; + + const sbp_msg_profiling_system_info_t &const_unwrapped = + sbp::MessageTraits::get(const_sbp_msg_t); + sbp_msg_profiling_system_info_t &non_const_unwrapped = + sbp::MessageTraits::get( + non_const_sbp_msg_t); + + EXPECT_EQ((const void *)&const_sbp_msg_t, (const void *)&const_unwrapped); + EXPECT_EQ((void *)&non_const_sbp_msg_t, (void *)&non_const_unwrapped); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + CppTraitsToSbpMsgT) { + auto info = get_test_msg_info(); + + sbp_msg_t msg1 = + sbp::MessageTraits::to_sbp_msg( + info.test_msg); + EXPECT_EQ(msg1.profiling_system_info, info.test_msg); + + sbp_msg_t msg2; + sbp::MessageTraits::to_sbp_msg(info.test_msg, + &msg2); + EXPECT_EQ(msg2.profiling_system_info, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + CppTraitsEncodedLen) { + auto info = get_test_msg_info(); + EXPECT_EQ(sbp::MessageTraits::encoded_len( + info.test_msg), + info.payload_len); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + CppTraitsSendThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp::MessageTraits::send( + &state, info.sender_id, info.test_msg, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), &info.encoded_frame[0], writer.len()), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + CppTraitsEncodeToBuf) { + auto info = get_test_msg_info(); + uint8_t buf[21]; + uint8_t n_written; + + EXPECT_EQ(sbp::MessageTraits::encode( + &buf[0], sizeof(buf), &n_written, info.test_msg), + SBP_OK); + EXPECT_EQ(n_written, 21); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 21), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + CppTraitsDecodeFromBuf) { + auto info = get_test_msg_info(); + sbp_msg_profiling_system_info_t msg{}; + uint8_t n_read; + + EXPECT_EQ(sbp::MessageTraits::decode( + &info.encoded_payload[0], info.payload_len, &n_read, &msg), + SBP_OK); + EXPECT_EQ(n_read, 21); + EXPECT_EQ(msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + ReceiveThroughMessageHandler) { + auto info = get_test_msg_info(); + auto reader = info.get_frame_reader(); + + sbp::State state{}; + state.set_reader(&reader); + + CppHandler handler{&state}; + + while (reader.remaining() > 0) { + EXPECT_GE(state.process(), SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + ProcessSbpMsgTThroughMessageHandler) { + auto info = get_test_msg_info(); + sbp::State state{}; + CppHandler handler(&state); + + state.process_message(info.sender_id, SbpMsgProfilingSystemInfo, + &info.test_msg_wrapped); + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + SendThroughCppState) { + auto info = get_test_msg_info(); + auto writer = info.get_frame_writer(); + + sbp::State state{}; + state.set_writer(&writer); + + EXPECT_EQ(state.send_message(info.sender_id, info.test_msg), SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingSystemInfo0, + SendWrappedSbpMsgTThroughCppState) { + auto info = get_test_msg_info(); + auto writer = info.get_frame_writer(); + + sbp::State state{}; + state.set_writer(&writer); + + EXPECT_EQ(state.send_message(info.sender_id, SbpMsgProfilingSystemInfo, + info.test_msg_wrapped), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +} // namespace \ No newline at end of file diff --git a/c/test/cpp/auto_check_sbp_profiling_MsgProfilingThreadInfo.cc b/c/test/cpp/auto_check_sbp_profiling_MsgProfilingThreadInfo.cc new file mode 100644 index 0000000000..dcfb643ace --- /dev/null +++ b/c/test/cpp/auto_check_sbp_profiling_MsgProfilingThreadInfo.cc @@ -0,0 +1,991 @@ +/* + * Copyright (C) 2015-2021 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +// This file was auto-generated from +// spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingThreadInfo.yaml by +// generate.py. Do not modify by hand! + +#include +#include +#include +#include +#include + +namespace { + +template +void assign(T &dest, const U &source) { + dest = static_cast(source); +} +class Testauto_check_sbp_profiling_MsgProfilingThreadInfo0 + : public ::testing::Test { + public: + Testauto_check_sbp_profiling_MsgProfilingThreadInfo0() { + assign(test_msg_.age, 10159470); + + size_t written; + EXPECT_TRUE(sbp_msg_profiling_thread_info_name_set( + &test_msg_, "Fusion engine", false, &written)); + EXPECT_EQ(written, strlen("Fusion engine")); + EXPECT_EQ(sbp_msg_profiling_thread_info_name_encoded_len(&test_msg_), 14); + assign(test_msg_.stack_size, 8388608); + assign(test_msg_.stack_usage, 275920); + assign(test_msg_.state, 1); + assign(test_msg_.total_cpu_time, 678775); + } + + class SlowReader final : public sbp::IReader { + public: + SlowReader(const uint8_t *buf, uint32_t len) + : sbp::IReader(), buf_{buf}, len_{len} {} + + s32 read(uint8_t *buf, const uint32_t n) override { + if (n == 0) { + return 0; + } + if (remaining() == 0) { + return -1; + } + skip_next_read = !skip_next_read; + if (skip_next_read) { + return 0; + } + uint32_t real_n = std::min(n, 1u); + memcpy(buf, buf_ + offset_, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return len_ - offset_; } + + static s32 read_static(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->read(buf, len); + } + + private: + const uint8_t *buf_; + uint32_t len_; + uint32_t offset_{}; + bool skip_next_read{}; + }; + + class Reader final : public sbp::IReader { + public: + Reader(const uint8_t *buf, uint32_t len) + : sbp::IReader(), buf_{buf}, len_{len} {} + + s32 read(uint8_t *buf, const uint32_t n) override { + if (n == 0) { + return 0; + } + uint32_t real_n = std::min(n, remaining()); + if (real_n == 0) { + return -1; + } + memcpy(buf, buf_ + offset_, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return len_ - offset_; } + + static s32 read_static(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->read(buf, len); + } + + private: + const uint8_t *buf_; + uint32_t len_; + uint32_t offset_{}; + }; + + class SlowWriter final : public sbp::IWriter { + public: + explicit SlowWriter(uint32_t max_len = cMaxLen) + : IWriter(), max_len_{max_len} {} + static constexpr uint32_t cMaxLen = SBP_MAX_FRAME_LEN; + + s32 write(const uint8_t *buf, uint32_t n) override { + if (n == 0) { + return 0; + } + uint32_t real_n = std::min(n, 1u); + if (real_n == 0) { + return -1; + } + memcpy(buf_ + offset_, buf, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return max_len_ - offset_; } + + const uint8_t *data() const noexcept { return buf_; } + + uint32_t len() const noexcept { return offset_; } + + static s32 write_static(const uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + static s32 write_c(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + private: + uint8_t buf_[cMaxLen]; + uint32_t max_len_; + uint32_t offset_{}; + }; + + class Writer final : public sbp::IWriter { + public: + explicit Writer(uint32_t max_len = cMaxLen) + : IWriter(), max_len_{max_len} {} + static constexpr uint32_t cMaxLen = SBP_MAX_FRAME_LEN; + + s32 write(const uint8_t *buf, uint32_t n) override { + if (n == 0) { + return 0; + } + uint32_t real_n = std::min(n, remaining()); + if (real_n == 0) { + return -1; + } + memcpy(buf_ + offset_, buf, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return max_len_ - offset_; } + + const uint8_t *data() const noexcept { return buf_; } + + uint32_t len() const noexcept { return offset_; } + + static s32 write_static(const uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + static s32 write_c(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + private: + uint8_t buf_[cMaxLen]; + uint32_t max_len_; + uint32_t offset_{}; + }; + + struct CppHandler final + : public sbp::MessageHandler { + using sbp::MessageHandler::MessageHandler; + + struct Output final { + uint16_t sender_id; + sbp_msg_profiling_thread_info_t msg; + }; + + std::vector outputs{}; + + protected: + void handle_sbp_msg(uint16_t sender_id, + const sbp_msg_profiling_thread_info_t &msg) override { + outputs.emplace_back(); + outputs.back().sender_id = sender_id; + memcpy(&outputs.back().msg, &msg, sizeof(msg)); + } + }; + + struct CHandler final { + explicit CHandler(sbp_state_t *state) : state_{state} { + sbp_callback_register(state, SbpMsgProfilingThreadInfo, + &CHandler::callback_static, this, &node_); + } + + ~CHandler() { sbp_remove_callback(state_, &node_); } + + struct Output final { + uint16_t sender_id; + sbp_msg_profiling_thread_info_t msg; + }; + + std::vector outputs{}; + + private: + void callback(uint16_t sender_id, sbp_msg_type_t msg_type, + const sbp_msg_t *msg) { + ASSERT_EQ(msg_type, SbpMsgProfilingThreadInfo); + outputs.emplace_back(); + outputs.back().sender_id = sender_id; + memcpy(&outputs.back().msg, &msg->profiling_thread_info, + sizeof(msg->profiling_thread_info)); + } + + static void callback_static(uint16_t sender_id, sbp_msg_type_t msg_type, + const sbp_msg_t *msg, void *ctx) { + static_cast(ctx)->callback(sender_id, msg_type, msg); + } + + sbp_msg_callbacks_node_t node_{}; + sbp_state_t *state_; + }; + + struct TestMsgInfo { + sbp_msg_profiling_thread_info_t test_msg; + sbp_msg_t test_msg_wrapped; + sbp_msg_type_t msg_type; + uint16_t sender_id; + uint8_t preamble; + uint16_t crc; + const uint8_t *encoded_frame; + uint32_t frame_len; + const uint8_t *encoded_payload; + uint8_t payload_len; + + Reader get_frame_reader() const noexcept { + return Reader{encoded_frame, frame_len}; + } + + Reader get_frame_reader(uint32_t max) const noexcept { + assert(max <= frame_len); + return Reader{encoded_frame, max}; + } + + SlowReader get_slow_frame_reader() const noexcept { + return SlowReader{encoded_frame, frame_len}; + } + + Writer get_frame_writer() const noexcept { return Writer{frame_len}; } + + Writer get_frame_writer(uint32_t max) const noexcept { return Writer{max}; } + + SlowWriter get_slow_frame_writer() const noexcept { + return SlowWriter{frame_len}; + } + }; + + TestMsgInfo get_test_msg_info() const noexcept { + TestMsgInfo info; + memcpy(&info.test_msg, &test_msg_, sizeof(test_msg_)); + memcpy(&info.test_msg_wrapped.profiling_thread_info, &test_msg_, + sizeof(test_msg_)); + info.msg_type = static_cast(SbpMsgProfilingThreadInfo); + info.sender_id = 4096; + info.preamble = 0x55; + info.crc = 0xaaf2; + info.encoded_frame = encoded_frame_; + info.frame_len = sizeof(encoded_frame_); + info.encoded_payload = encoded_payload_; + info.payload_len = 39; + + return info; + } + + protected: + void comparison_tests(const sbp_msg_profiling_thread_info_t &lesser, + const sbp_msg_profiling_thread_info_t &greater) { + sbp_msg_t wrapped_lesser = + sbp::MessageTraits::to_sbp_msg(lesser); + sbp_msg_t wrapped_greater = + sbp::MessageTraits::to_sbp_msg( + greater); + + EXPECT_EQ(sbp_msg_profiling_thread_info_cmp(&lesser, &lesser), 0); + EXPECT_EQ(sbp_msg_profiling_thread_info_cmp(&greater, &greater), 0); + EXPECT_LE(sbp_msg_profiling_thread_info_cmp(&lesser, &greater), 0); + EXPECT_GT(sbp_msg_profiling_thread_info_cmp(&greater, &lesser), 0); + + EXPECT_EQ(sbp_message_cmp(SbpMsgProfilingThreadInfo, &wrapped_lesser, + &wrapped_lesser), + 0); + EXPECT_EQ(sbp_message_cmp(SbpMsgProfilingThreadInfo, &wrapped_greater, + &wrapped_greater), + 0); + EXPECT_LE(sbp_message_cmp(SbpMsgProfilingThreadInfo, &wrapped_lesser, + &wrapped_greater), + 0); + EXPECT_GT(sbp_message_cmp(SbpMsgProfilingThreadInfo, &wrapped_greater, + &wrapped_lesser), + 0); + + // lesser vs lesser + EXPECT_TRUE(lesser == lesser); + EXPECT_FALSE(lesser != lesser); + EXPECT_FALSE(lesser < lesser); + EXPECT_TRUE(lesser <= lesser); + EXPECT_FALSE(lesser > lesser); + EXPECT_TRUE(lesser >= lesser); + + // greater vs greater + EXPECT_TRUE(greater == greater); + EXPECT_FALSE(greater != greater); + EXPECT_FALSE(greater < greater); + EXPECT_TRUE(greater <= greater); + EXPECT_FALSE(greater > greater); + EXPECT_TRUE(greater >= greater); + + // lesser vs greater + EXPECT_FALSE(lesser == greater); + EXPECT_TRUE(lesser != greater); + EXPECT_TRUE(lesser < greater); + EXPECT_TRUE(lesser <= greater); + EXPECT_FALSE(lesser > greater); + EXPECT_FALSE(lesser >= greater); + + // greater vs lesser + EXPECT_FALSE(greater == lesser); + EXPECT_TRUE(greater != lesser); + EXPECT_FALSE(greater < lesser); + EXPECT_FALSE(greater <= lesser); + EXPECT_TRUE(greater > lesser); + EXPECT_TRUE(greater >= lesser); + } + + template ::value, bool> = true> + void make_lesser_greater(T &lesser, T &greater) { + if (lesser > std::numeric_limits::min()) { + lesser--; + } else { + greater++; + } + } + + template ::value, bool> = true> + void make_lesser_greater(T &lesser, T &greater) { + (void)lesser; + greater += static_cast(1.0); + } + + void make_lesser_greater(sbp_string_t &lesser, sbp_string_t &greater) { + if (greater.data[0] == 'z') { + lesser.data[0]--; + } else { + greater.data[0]++; + } + } + + template + void make_lesser_greater(char (&lesser)[N], char (&greater)[N]) { + if (lesser[0] == 'z') { + lesser[0]--; + } else { + greater[0]++; + } + } + + private: + sbp_msg_profiling_thread_info_t test_msg_{}; + uint8_t encoded_frame_[39 + 8] = { + 85, 2, 207, 0, 16, 39, 119, 91, 10, 0, 0, 0, + 0, 0, 110, 5, 155, 0, 0, 0, 0, 0, 1, 0, + 0, 128, 0, 208, 53, 4, 0, 70, 117, 115, 105, 111, + 110, 32, 101, 110, 103, 105, 110, 101, 0, 242, 170, + }; + uint8_t encoded_payload_[39] = { + 119, 91, 10, 0, 0, 0, 0, 0, 110, 5, 155, 0, 0, + 0, 0, 0, 1, 0, 0, 128, 0, 208, 53, 4, 0, 70, + 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, 0, + }; +}; + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, EncodedLen) { + auto info = get_test_msg_info(); + EXPECT_EQ(sbp_msg_profiling_thread_info_encoded_len(&info.test_msg), + info.payload_len); + + EXPECT_EQ(sbp_message_encoded_len(SbpMsgProfilingThreadInfo, + &info.test_msg_wrapped), + info.payload_len); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, EncodeToBuf) { + auto info = get_test_msg_info(); + uint8_t buf[39]; + uint8_t n_written; + + EXPECT_EQ(sbp_msg_profiling_thread_info_encode(&buf[0], sizeof(buf), + &n_written, &info.test_msg), + SBP_OK); + EXPECT_EQ(n_written, 39); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 39), 0); + + memset(&buf[0], 0, sizeof(buf)); + EXPECT_EQ( + sbp_message_encode(&buf[0], sizeof(buf), &n_written, + SbpMsgProfilingThreadInfo, &info.test_msg_wrapped), + SBP_OK); + EXPECT_EQ(n_written, 39); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 39), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + EncodeToBufWithoutNwritten) { + auto info = get_test_msg_info(); + uint8_t buf[39]; + + EXPECT_EQ(sbp_msg_profiling_thread_info_encode(&buf[0], sizeof(buf), nullptr, + &info.test_msg), + SBP_OK); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 39), 0); +} +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + EncodedToBufUnderflow) { + auto info = get_test_msg_info(); + uint8_t buf[39]; + + for (uint8_t i = 0; i < 39; i++) { + EXPECT_EQ(sbp_msg_profiling_thread_info_encode(&buf[0], i, nullptr, + &info.test_msg), + SBP_ENCODE_ERROR); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, DecodeFromBuf) { + auto info = get_test_msg_info(); + sbp_msg_profiling_thread_info_t msg{}; + uint8_t n_read; + + EXPECT_EQ(sbp_msg_profiling_thread_info_decode( + &info.encoded_payload[0], info.payload_len, &n_read, &msg), + SBP_OK); + EXPECT_EQ(n_read, 39); + EXPECT_EQ(msg, info.test_msg); + + sbp_msg_t wrapped_msg{}; + EXPECT_EQ( + sbp_message_decode(&info.encoded_payload[0], info.payload_len, &n_read, + SbpMsgProfilingThreadInfo, &wrapped_msg), + SBP_OK); + EXPECT_EQ(n_read, 39); + EXPECT_EQ(msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + DecodeFromBufWithoutNread) { + auto info = get_test_msg_info(); + sbp_msg_profiling_thread_info_t msg{}; + + EXPECT_EQ(sbp_msg_profiling_thread_info_decode( + &info.encoded_payload[0], info.payload_len, nullptr, &msg), + SBP_OK); + EXPECT_EQ(msg, info.test_msg); +} +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + DecodeFromBufUnderflow) { + auto info = get_test_msg_info(); + sbp_msg_profiling_thread_info_t msg{}; + + for (uint8_t i = 0; i < info.payload_len; i++) { + int expected_return = SBP_DECODE_ERROR; + size_t overhead = SBP_MSG_PROFILING_THREAD_INFO_ENCODED_OVERHEAD; + // size_t overhead = []()->size_t{sbp_msg_profiling_thread_info_t t{}; + // return sbp_msg_profiling_thread_info_encoded_len(&t); }(); + if (i >= overhead) { + expected_return = SBP_OK; + } + + EXPECT_EQ(sbp_msg_profiling_thread_info_decode(&info.encoded_payload[0], i, + nullptr, &msg), + expected_return); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + ReceiveThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto reader = info.get_frame_reader(); + sbp_state_set_io_context(&state, &reader); + + CHandler handler{&state}; + + while (reader.remaining() > 0) { + EXPECT_GE(sbp_process(&state, &Reader::read_static), SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + ReceiveThroughSbpStateUnderflow) { + auto info = get_test_msg_info(); + + for (uint32_t i = 0; i < info.frame_len; i++) { + sbp_state_t state; + sbp_state_init(&state); + + auto reader = info.get_frame_reader(i); + sbp_state_set_io_context(&state, &reader); + + CHandler handler(&state); + + int most_recent_return = sbp_process(&state, &Reader::read_static); + while (most_recent_return == SBP_OK || reader.remaining() > 0) { + most_recent_return = sbp_process(&state, &Reader::read_static); + } + + EXPECT_NE(most_recent_return, SBP_OK); + EXPECT_EQ(reader.remaining(), 0); + + EXPECT_EQ(handler.outputs.size(), 0); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, SlowRead) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto reader = info.get_slow_frame_reader(); + sbp_state_set_io_context(&state, &reader); + + CHandler handler{&state}; + + while (reader.remaining() > 0) { + EXPECT_GE(sbp_process(&state, &SlowReader::read_static), SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, BadCRC) { + auto info = get_test_msg_info(); + uint8_t buf[SBP_MAX_FRAME_LEN]; + memcpy(&buf[0], info.encoded_frame, info.frame_len); + + // Introduce a CRC error which should cause an error return and no callback + buf[info.frame_len - 1]++; + + sbp_state_t state; + sbp_state_init(&state); + + Reader reader{buf, info.frame_len}; + sbp_state_set_io_context(&state, &reader); + + CHandler handler{&state}; + + while (reader.remaining() > 0) { + int res = sbp_process(&state, &Reader::read_static); + EXPECT_EQ(res, reader.remaining() == 0 ? SBP_CRC_ERROR : SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + SendThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp_msg_profiling_thread_info_send( + &state, info.sender_id, &info.test_msg, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), &info.encoded_frame[0], writer.len()), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + SendWrappedThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp_message_send(&state, SbpMsgProfilingThreadInfo, info.sender_id, + &info.test_msg_wrapped, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + SendThroughSbpStateUnderflow) { + auto info = get_test_msg_info(); + + for (uint32_t i = 0; i < info.frame_len; i++) { + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(i); + sbp_state_set_io_context(&state, &writer); + + EXPECT_NE( + sbp_message_send(&state, SbpMsgProfilingThreadInfo, info.sender_id, + &info.test_msg_wrapped, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), i); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, i), 0); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + DISABLED_SlowWrite) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_slow_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp_message_send(&state, SbpMsgProfilingThreadInfo, info.sender_id, + &info.test_msg_wrapped, &SlowWriter::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, Comparison) { + auto info = get_test_msg_info(); + { + sbp_msg_profiling_thread_info_t lesser = info.test_msg; + sbp_msg_profiling_thread_info_t greater = info.test_msg; + make_lesser_greater(lesser.age, greater.age); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_thread_info_t lesser = info.test_msg; + sbp_msg_profiling_thread_info_t greater = info.test_msg; + make_lesser_greater(lesser.name, greater.name); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_thread_info_t lesser = info.test_msg; + sbp_msg_profiling_thread_info_t greater = info.test_msg; + make_lesser_greater(lesser.stack_size, greater.stack_size); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_thread_info_t lesser = info.test_msg; + sbp_msg_profiling_thread_info_t greater = info.test_msg; + make_lesser_greater(lesser.stack_usage, greater.stack_usage); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_thread_info_t lesser = info.test_msg; + sbp_msg_profiling_thread_info_t greater = info.test_msg; + make_lesser_greater(lesser.state, greater.state); + comparison_tests(lesser, greater); + } + { + sbp_msg_profiling_thread_info_t lesser = info.test_msg; + sbp_msg_profiling_thread_info_t greater = info.test_msg; + make_lesser_greater(lesser.total_cpu_time, greater.total_cpu_time); + comparison_tests(lesser, greater); + } +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + CppTraitsProperties) { + // EXPECT_EQ(sbp::MessageTraits::id, + // SbpMsgProfilingThreadInfo); + EXPECT_STREQ(sbp::MessageTraits::name, + "MSG_PROFILING_THREAD_INFO"); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + CppTraitsFromSbpMsgT) { + auto info = get_test_msg_info(); + + const sbp_msg_t &const_sbp_msg_t = info.test_msg_wrapped; + sbp_msg_t &non_const_sbp_msg_t = info.test_msg_wrapped; + + const sbp_msg_profiling_thread_info_t &const_unwrapped = + sbp::MessageTraits::get(const_sbp_msg_t); + sbp_msg_profiling_thread_info_t &non_const_unwrapped = + sbp::MessageTraits::get( + non_const_sbp_msg_t); + + EXPECT_EQ((const void *)&const_sbp_msg_t, (const void *)&const_unwrapped); + EXPECT_EQ((void *)&non_const_sbp_msg_t, (void *)&non_const_unwrapped); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + CppTraitsToSbpMsgT) { + auto info = get_test_msg_info(); + + sbp_msg_t msg1 = + sbp::MessageTraits::to_sbp_msg( + info.test_msg); + EXPECT_EQ(msg1.profiling_thread_info, info.test_msg); + + sbp_msg_t msg2; + sbp::MessageTraits::to_sbp_msg(info.test_msg, + &msg2); + EXPECT_EQ(msg2.profiling_thread_info, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + CppTraitsEncodedLen) { + auto info = get_test_msg_info(); + EXPECT_EQ(sbp::MessageTraits::encoded_len( + info.test_msg), + info.payload_len); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + CppTraitsSendThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp::MessageTraits::send( + &state, info.sender_id, info.test_msg, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), &info.encoded_frame[0], writer.len()), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + CppTraitsEncodeToBuf) { + auto info = get_test_msg_info(); + uint8_t buf[39]; + uint8_t n_written; + + EXPECT_EQ(sbp::MessageTraits::encode( + &buf[0], sizeof(buf), &n_written, info.test_msg), + SBP_OK); + EXPECT_EQ(n_written, 39); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 39), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + CppTraitsDecodeFromBuf) { + auto info = get_test_msg_info(); + sbp_msg_profiling_thread_info_t msg{}; + uint8_t n_read; + + EXPECT_EQ(sbp::MessageTraits::decode( + &info.encoded_payload[0], info.payload_len, &n_read, &msg), + SBP_OK); + EXPECT_EQ(n_read, 39); + EXPECT_EQ(msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + ReceiveThroughMessageHandler) { + auto info = get_test_msg_info(); + auto reader = info.get_frame_reader(); + + sbp::State state{}; + state.set_reader(&reader); + + CppHandler handler{&state}; + + while (reader.remaining() > 0) { + EXPECT_GE(state.process(), SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + ProcessSbpMsgTThroughMessageHandler) { + auto info = get_test_msg_info(); + sbp::State state{}; + CppHandler handler(&state); + + state.process_message(info.sender_id, SbpMsgProfilingThreadInfo, + &info.test_msg_wrapped); + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + SendThroughCppState) { + auto info = get_test_msg_info(); + auto writer = info.get_frame_writer(); + + sbp::State state{}; + state.set_writer(&writer); + + EXPECT_EQ(state.send_message(info.sender_id, info.test_msg), SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0, + SendWrappedSbpMsgTThroughCppState) { + auto info = get_test_msg_info(); + auto writer = info.get_frame_writer(); + + sbp::State state{}; + state.set_writer(&writer); + + EXPECT_EQ(state.send_message(info.sender_id, SbpMsgProfilingThreadInfo, + info.test_msg_wrapped), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +class Testauto_check_sbp_profiling_MsgProfilingThreadInfo0_name + : public Testauto_check_sbp_profiling_MsgProfilingThreadInfo0 {}; + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0_name, StringInit) { + sbp_msg_profiling_thread_info_t t{}; + sbp_msg_profiling_thread_info_name_init(&t); + EXPECT_TRUE(sbp_msg_profiling_thread_info_name_valid(&t)); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0_name, IsValid) { + sbp_msg_profiling_thread_info_t t{}; + + size_t written; + EXPECT_TRUE(sbp_msg_profiling_thread_info_name_set(&t, "Fusion engine", false, + &written)); + EXPECT_EQ(written, strlen("Fusion engine")); + EXPECT_EQ(sbp_msg_profiling_thread_info_name_encoded_len(&t), 14); + EXPECT_TRUE(sbp_msg_profiling_thread_info_name_valid(&t)); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0_name, + SpaceRemaining) { + sbp_msg_profiling_thread_info_t t{}; + size_t empty_space_remaining = + sbp_msg_profiling_thread_info_name_space_remaining(&t); + + size_t written; + EXPECT_TRUE(sbp_msg_profiling_thread_info_name_set(&t, "Fusion engine", false, + &written)); + EXPECT_EQ(written, strlen("Fusion engine")); + EXPECT_EQ(sbp_msg_profiling_thread_info_name_encoded_len(&t), 14); + size_t assigned_space_remaining = + sbp_msg_profiling_thread_info_name_space_remaining(&t); + EXPECT_LT(assigned_space_remaining, empty_space_remaining); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0_name, SetRaw) { + auto info = get_test_msg_info(); + sbp_msg_profiling_thread_info_t t{}; + + size_t nwritten{}; + + EXPECT_TRUE(sbp_msg_profiling_thread_info_name_set_raw( + &t, info.test_msg.name.data, + sbp_msg_profiling_thread_info_name_strlen(&info.test_msg), false, + &nwritten)); + EXPECT_EQ(sbp_msg_profiling_thread_info_name_encoded_len(&info.test_msg), + sbp_msg_profiling_thread_info_name_encoded_len(&t)); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0_name, Set) { + sbp_msg_profiling_thread_info_t t{}; + size_t nwritten{}; + const char *text = "Fusion engine"; + + EXPECT_TRUE( + sbp_msg_profiling_thread_info_name_set(&t, text, false, &nwritten)); + EXPECT_EQ(nwritten, strlen(text)); + EXPECT_STREQ(sbp_msg_profiling_thread_info_name_get(&t), text); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0_name, Printf) { + sbp_msg_profiling_thread_info_t t{}; + size_t nwritten{}; + const char *text = "Fusion engine"; + + EXPECT_TRUE(sbp_msg_profiling_thread_info_name_printf(&t, false, &nwritten, + "%s", text)); + EXPECT_EQ(nwritten, strlen(text)); + EXPECT_STREQ(sbp_msg_profiling_thread_info_name_get(&t), text); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0_name, Vprintf) { + sbp_msg_profiling_thread_info_t t{}; + size_t nwritten{}; + const char *text = "Fusion engine"; + + auto lambda = [&t, &nwritten](const char *format, ...) -> bool { + va_list ap; + va_start(ap, format); + bool ret = sbp_msg_profiling_thread_info_name_vprintf(&t, false, &nwritten, + format, ap); + va_end(ap); + return ret; + }; + + EXPECT_TRUE(lambda("%s", text)); + EXPECT_EQ(nwritten, strlen(text)); + EXPECT_STREQ(sbp_msg_profiling_thread_info_name_get(&t), text); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0_name, + AppendPrintf) { + sbp_msg_profiling_thread_info_t t{}; + size_t nwritten{}; + char part1[] = "Fusion engine"; + char part2[] = "Fusion engine"; + + part1[1] = 0; + + EXPECT_TRUE(sbp_msg_profiling_thread_info_name_printf(&t, false, &nwritten, + "%s", &part1[0])); + EXPECT_EQ(nwritten, 1); + EXPECT_STREQ(sbp_msg_profiling_thread_info_name_get(&t), &part1[0]); + + EXPECT_TRUE(sbp_msg_profiling_thread_info_name_append_printf( + &t, false, &nwritten, "%s", &part2[1])); + EXPECT_EQ(nwritten, strlen(&part2[1])); + EXPECT_STREQ(sbp_msg_profiling_thread_info_name_get(&t), "Fusion engine"); +} + +TEST_F(Testauto_check_sbp_profiling_MsgProfilingThreadInfo0_name, + AppendVprintf) { + sbp_msg_profiling_thread_info_t t{}; + size_t nwritten{}; + char part1[] = "Fusion engine"; + char part2[] = "Fusion engine"; + + part1[1] = 0; + + EXPECT_TRUE(sbp_msg_profiling_thread_info_name_printf(&t, false, &nwritten, + "%s", &part1[0])); + EXPECT_EQ(nwritten, 1); + EXPECT_STREQ(sbp_msg_profiling_thread_info_name_get(&t), &part1[0]); + + auto lambda = [&t, &nwritten](const char *format, ...) -> bool { + va_list ap; + va_start(ap, format); + bool ret = sbp_msg_profiling_thread_info_name_append_vprintf( + &t, false, &nwritten, format, ap); + va_end(ap); + return ret; + }; + + EXPECT_TRUE(lambda("%s", &part2[1])); + EXPECT_EQ(nwritten, strlen(&part2[1])); + EXPECT_STREQ(sbp_msg_profiling_thread_info_name_get(&t), "Fusion engine"); +} + +} // namespace \ No newline at end of file diff --git a/generator/sbpg/targets/resources/rust/test/sbp_tests_main_template.rs b/generator/sbpg/targets/resources/rust/test/sbp_tests_main_template.rs index 41b47b7320..c7da9ef9d2 100644 --- a/generator/sbpg/targets/resources/rust/test/sbp_tests_main_template.rs +++ b/generator/sbpg/targets/resources/rust/test/sbp_tests_main_template.rs @@ -12,6 +12,7 @@ // This file was auto-generated. Do not modify by hand! #![allow(clippy::excessive_precision)] +#![allow(clippy::legacy_numeric_constants)] ((*- for test_name in test_names *)) mod (((test_name))); diff --git a/haskell/src/SwiftNav/SBP/Msg.hs b/haskell/src/SwiftNav/SBP/Msg.hs index 2076678b7d..3e46239095 100644 --- a/haskell/src/SwiftNav/SBP/Msg.hs +++ b/haskell/src/SwiftNav/SBP/Msg.hs @@ -206,6 +206,9 @@ data SBPMsg = | SBPMsgPoseRelative MsgPoseRelative Msg | SBPMsgPpsTime MsgPpsTime Msg | SBPMsgPrintDep MsgPrintDep Msg + | SBPMsgProfilingResourceCounter MsgProfilingResourceCounter Msg + | SBPMsgProfilingSystemInfo MsgProfilingSystemInfo Msg + | SBPMsgProfilingThreadInfo MsgProfilingThreadInfo Msg | SBPMsgProtectionLevel MsgProtectionLevel Msg | SBPMsgProtectionLevelDepA MsgProtectionLevelDepA Msg | SBPMsgReferenceFrameParam MsgReferenceFrameParam Msg @@ -453,6 +456,9 @@ instance Binary SBPMsg where | _msgSBPType == msgPoseRelative = SBPMsgPoseRelative (decode (fromStrict (unBytes _msgSBPPayload))) m | _msgSBPType == msgPpsTime = SBPMsgPpsTime (decode (fromStrict (unBytes _msgSBPPayload))) m | _msgSBPType == msgPrintDep = SBPMsgPrintDep (decode (fromStrict (unBytes _msgSBPPayload))) m + | _msgSBPType == msgProfilingResourceCounter = SBPMsgProfilingResourceCounter (decode (fromStrict (unBytes _msgSBPPayload))) m + | _msgSBPType == msgProfilingSystemInfo = SBPMsgProfilingSystemInfo (decode (fromStrict (unBytes _msgSBPPayload))) m + | _msgSBPType == msgProfilingThreadInfo = SBPMsgProfilingThreadInfo (decode (fromStrict (unBytes _msgSBPPayload))) m | _msgSBPType == msgProtectionLevel = SBPMsgProtectionLevel (decode (fromStrict (unBytes _msgSBPPayload))) m | _msgSBPType == msgProtectionLevelDepA = SBPMsgProtectionLevelDepA (decode (fromStrict (unBytes _msgSBPPayload))) m | _msgSBPType == msgReferenceFrameParam = SBPMsgReferenceFrameParam (decode (fromStrict (unBytes _msgSBPPayload))) m @@ -692,6 +698,9 @@ instance Binary SBPMsg where encoder (SBPMsgPoseRelative _ m) = put m encoder (SBPMsgPpsTime _ m) = put m encoder (SBPMsgPrintDep _ m) = put m + encoder (SBPMsgProfilingResourceCounter _ m) = put m + encoder (SBPMsgProfilingSystemInfo _ m) = put m + encoder (SBPMsgProfilingThreadInfo _ m) = put m encoder (SBPMsgProtectionLevel _ m) = put m encoder (SBPMsgProtectionLevelDepA _ m) = put m encoder (SBPMsgReferenceFrameParam _ m) = put m @@ -935,6 +944,9 @@ instance FromJSON SBPMsg where | msgType == msgPoseRelative = SBPMsgPoseRelative <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj | msgType == msgPpsTime = SBPMsgPpsTime <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj | msgType == msgPrintDep = SBPMsgPrintDep <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj + | msgType == msgProfilingResourceCounter = SBPMsgProfilingResourceCounter <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj + | msgType == msgProfilingSystemInfo = SBPMsgProfilingSystemInfo <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj + | msgType == msgProfilingThreadInfo = SBPMsgProfilingThreadInfo <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj | msgType == msgProtectionLevel = SBPMsgProtectionLevel <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj | msgType == msgProtectionLevelDepA = SBPMsgProtectionLevelDepA <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj | msgType == msgReferenceFrameParam = SBPMsgReferenceFrameParam <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj @@ -1179,6 +1191,9 @@ instance ToJSON SBPMsg where toJSON (SBPMsgPoseRelative n m) = toJSON n <<>> toJSON m toJSON (SBPMsgPpsTime n m) = toJSON n <<>> toJSON m toJSON (SBPMsgPrintDep n m) = toJSON n <<>> toJSON m + toJSON (SBPMsgProfilingResourceCounter n m) = toJSON n <<>> toJSON m + toJSON (SBPMsgProfilingSystemInfo n m) = toJSON n <<>> toJSON m + toJSON (SBPMsgProfilingThreadInfo n m) = toJSON n <<>> toJSON m toJSON (SBPMsgProtectionLevel n m) = toJSON n <<>> toJSON m toJSON (SBPMsgProtectionLevelDepA n m) = toJSON n <<>> toJSON m toJSON (SBPMsgReferenceFrameParam n m) = toJSON n <<>> toJSON m @@ -1417,6 +1432,9 @@ instance HasMsg SBPMsg where msg f (SBPMsgPoseRelative n m) = SBPMsgPoseRelative n <$> f m msg f (SBPMsgPpsTime n m) = SBPMsgPpsTime n <$> f m msg f (SBPMsgPrintDep n m) = SBPMsgPrintDep n <$> f m + msg f (SBPMsgProfilingResourceCounter n m) = SBPMsgProfilingResourceCounter n <$> f m + msg f (SBPMsgProfilingSystemInfo n m) = SBPMsgProfilingSystemInfo n <$> f m + msg f (SBPMsgProfilingThreadInfo n m) = SBPMsgProfilingThreadInfo n <$> f m msg f (SBPMsgProtectionLevel n m) = SBPMsgProtectionLevel n <$> f m msg f (SBPMsgProtectionLevelDepA n m) = SBPMsgProtectionLevelDepA n <$> f m msg f (SBPMsgReferenceFrameParam n m) = SBPMsgReferenceFrameParam n <$> f m diff --git a/haskell/src/SwiftNav/SBP/Profiling.hs b/haskell/src/SwiftNav/SBP/Profiling.hs index bf3e338297..31ca5a2bba 100644 --- a/haskell/src/SwiftNav/SBP/Profiling.hs +++ b/haskell/src/SwiftNav/SBP/Profiling.hs @@ -91,3 +91,171 @@ instance Binary MsgMeasurementPoint where $(makeSBP 'msgMeasurementPoint ''MsgMeasurementPoint) $(makeJSON "_msgMeasurementPoint_" ''MsgMeasurementPoint) $(makeLenses ''MsgMeasurementPoint) + +msgProfilingSystemInfo :: Word16 +msgProfilingSystemInfo = 0xCF01 + +-- | SBP class for message MSG_PROFILING_SYSTEM_INFO (0xCF01). +-- +-- Contains basic information about system resource usage. System is defined +-- in terms of the source of this message and may vary from sender to sender. +-- Refer to product documentation to understand the exact scope and meaning of +-- this message. +data MsgProfilingSystemInfo = MsgProfilingSystemInfo + { _msgProfilingSystemInfo_total_cpu_time :: !Word64 + -- ^ Total cpu time in microseconds consumed by this system + , _msgProfilingSystemInfo_age :: !Word64 + -- ^ Age of the producing system in microseconds + , _msgProfilingSystemInfo_n_threads :: !Word8 + -- ^ Number of threads being tracked by this system + , _msgProfilingSystemInfo_heap_usage :: !Word32 + -- ^ Number of bytes allocated on the heap + } deriving ( Show, Read, Eq ) + +instance Binary MsgProfilingSystemInfo where + get = do + _msgProfilingSystemInfo_total_cpu_time <- getWord64le + _msgProfilingSystemInfo_age <- getWord64le + _msgProfilingSystemInfo_n_threads <- getWord8 + _msgProfilingSystemInfo_heap_usage <- getWord32le + pure MsgProfilingSystemInfo {..} + + put MsgProfilingSystemInfo {..} = do + putWord64le _msgProfilingSystemInfo_total_cpu_time + putWord64le _msgProfilingSystemInfo_age + putWord8 _msgProfilingSystemInfo_n_threads + putWord32le _msgProfilingSystemInfo_heap_usage + +$(makeSBP 'msgProfilingSystemInfo ''MsgProfilingSystemInfo) +$(makeJSON "_msgProfilingSystemInfo_" ''MsgProfilingSystemInfo) +$(makeLenses ''MsgProfilingSystemInfo) + +msgProfilingThreadInfo :: Word16 +msgProfilingThreadInfo = 0xCF02 + +-- | SBP class for message MSG_PROFILING_THREAD_INFO (0xCF02). +-- +-- Contains profiling information related to a single thread being tracked by +-- the producing system. Refer to product documentation to understand the +-- exact scope and meaning of this message. +data MsgProfilingThreadInfo = MsgProfilingThreadInfo + { _msgProfilingThreadInfo_total_cpu_time :: !Word64 + -- ^ Total cpu time in microseconds consumed by this thread + , _msgProfilingThreadInfo_age :: !Word64 + -- ^ Age of the thread in microseconds + , _msgProfilingThreadInfo_state :: !Word8 + -- ^ Thread state + , _msgProfilingThreadInfo_stack_size :: !Word32 + -- ^ Stack size in bytes + , _msgProfilingThreadInfo_stack_usage :: !Word32 + -- ^ Stack highwater usage in bytes + , _msgProfilingThreadInfo_name :: !Text + -- ^ Thread name + } deriving ( Show, Read, Eq ) + +instance Binary MsgProfilingThreadInfo where + get = do + _msgProfilingThreadInfo_total_cpu_time <- getWord64le + _msgProfilingThreadInfo_age <- getWord64le + _msgProfilingThreadInfo_state <- getWord8 + _msgProfilingThreadInfo_stack_size <- getWord32le + _msgProfilingThreadInfo_stack_usage <- getWord32le + _msgProfilingThreadInfo_name <- decodeUtf8 . toStrict <$> getRemainingLazyByteString + pure MsgProfilingThreadInfo {..} + + put MsgProfilingThreadInfo {..} = do + putWord64le _msgProfilingThreadInfo_total_cpu_time + putWord64le _msgProfilingThreadInfo_age + putWord8 _msgProfilingThreadInfo_state + putWord32le _msgProfilingThreadInfo_stack_size + putWord32le _msgProfilingThreadInfo_stack_usage + putByteString $ encodeUtf8 _msgProfilingThreadInfo_name + +$(makeSBP 'msgProfilingThreadInfo ''MsgProfilingThreadInfo) +$(makeJSON "_msgProfilingThreadInfo_" ''MsgProfilingThreadInfo) +$(makeLenses ''MsgProfilingThreadInfo) + +-- | ResourceBucket. +-- +-- Information about allocation of various resources grouped by buckets. Refer +-- to product documentation to understand the meaning and values in this +-- message. +data ResourceBucket = ResourceBucket + { _resourceBucket_name :: !Text + -- ^ Bucket name + , _resourceBucket_thread :: !Word8 + -- ^ Number of threads + , _resourceBucket_mutex :: !Word8 + -- ^ Number of mutexes + , _resourceBucket_cv :: !Word8 + -- ^ Number of condition variables + , _resourceBucket_io :: !Word8 + -- ^ Number of IO handles + , _resourceBucket_heap_bytes_alloc :: !Word32 + -- ^ Number of bytes allocated on the heap + , _resourceBucket_heap_bytes_free :: !Word32 + -- ^ Number of bytes freed on the heap + , _resourceBucket_io_write :: !Word32 + -- ^ Number of bytes written to IO handles + , _resourceBucket_io_read :: !Word32 + -- ^ Number of bytes read from IO handles + } deriving ( Show, Read, Eq ) + +instance Binary ResourceBucket where + get = do + _resourceBucket_name <- decodeUtf8 <$> getByteString 21 + _resourceBucket_thread <- getWord8 + _resourceBucket_mutex <- getWord8 + _resourceBucket_cv <- getWord8 + _resourceBucket_io <- getWord8 + _resourceBucket_heap_bytes_alloc <- getWord32le + _resourceBucket_heap_bytes_free <- getWord32le + _resourceBucket_io_write <- getWord32le + _resourceBucket_io_read <- getWord32le + pure ResourceBucket {..} + + put ResourceBucket {..} = do + putByteString $ encodeUtf8 _resourceBucket_name + putWord8 _resourceBucket_thread + putWord8 _resourceBucket_mutex + putWord8 _resourceBucket_cv + putWord8 _resourceBucket_io + putWord32le _resourceBucket_heap_bytes_alloc + putWord32le _resourceBucket_heap_bytes_free + putWord32le _resourceBucket_io_write + putWord32le _resourceBucket_io_read + +$(makeJSON "_resourceBucket_" ''ResourceBucket) +$(makeLenses ''ResourceBucket) + +msgProfilingResourceCounter :: Word16 +msgProfilingResourceCounter = 0xCF03 + +-- | SBP class for message MSG_PROFILING_RESOURCE_COUNTER (0xCF03). +-- +-- Information about resource buckets. Refer to product documentation to +-- understand the meaning and values in this message. +data MsgProfilingResourceCounter = MsgProfilingResourceCounter + { _msgProfilingResourceCounter_seq_no :: !Word8 + -- ^ Message number in complete sequence + , _msgProfilingResourceCounter_seq_len :: !Word8 + -- ^ Length of message sequence + , _msgProfilingResourceCounter_buckets :: ![ResourceBucket] + -- ^ List of resource buckets + } deriving ( Show, Read, Eq ) + +instance Binary MsgProfilingResourceCounter where + get = do + _msgProfilingResourceCounter_seq_no <- getWord8 + _msgProfilingResourceCounter_seq_len <- getWord8 + _msgProfilingResourceCounter_buckets <- whileM (not <$> isEmpty) get + pure MsgProfilingResourceCounter {..} + + put MsgProfilingResourceCounter {..} = do + putWord8 _msgProfilingResourceCounter_seq_no + putWord8 _msgProfilingResourceCounter_seq_len + mapM_ put _msgProfilingResourceCounter_buckets + +$(makeSBP 'msgProfilingResourceCounter ''MsgProfilingResourceCounter) +$(makeJSON "_msgProfilingResourceCounter_" ''MsgProfilingResourceCounter) +$(makeLenses ''MsgProfilingResourceCounter) diff --git a/java/src/com/swiftnav/sbp/client/MessageTable.java b/java/src/com/swiftnav/sbp/client/MessageTable.java index e3c1a5e8a1..7d085851c6 100644 --- a/java/src/com/swiftnav/sbp/client/MessageTable.java +++ b/java/src/com/swiftnav/sbp/client/MessageTable.java @@ -179,6 +179,9 @@ import com.swiftnav.sbp.piksi.MsgUartState; import com.swiftnav.sbp.piksi.MsgUartStateDepa; import com.swiftnav.sbp.profiling.MsgMeasurementPoint; +import com.swiftnav.sbp.profiling.MsgProfilingResourceCounter; +import com.swiftnav.sbp.profiling.MsgProfilingSystemInfo; +import com.swiftnav.sbp.profiling.MsgProfilingThreadInfo; import com.swiftnav.sbp.sbas.MsgSbasRaw; import com.swiftnav.sbp.settings.MsgSettingsReadByIndexDone; import com.swiftnav.sbp.settings.MsgSettingsReadByIndexReq; @@ -583,6 +586,12 @@ static SBPMessage dispatch(SBPMessage msg) throws SBPBinaryException { return new MsgFrontEndGain(msg); case MsgMeasurementPoint.TYPE: return new MsgMeasurementPoint(msg); + case MsgProfilingSystemInfo.TYPE: + return new MsgProfilingSystemInfo(msg); + case MsgProfilingThreadInfo.TYPE: + return new MsgProfilingThreadInfo(msg); + case MsgProfilingResourceCounter.TYPE: + return new MsgProfilingResourceCounter(msg); case MsgSbasRaw.TYPE: return new MsgSbasRaw(msg); case MsgSettingsSave.TYPE: diff --git a/java/src/com/swiftnav/sbp/profiling/MsgProfilingResourceCounter.java b/java/src/com/swiftnav/sbp/profiling/MsgProfilingResourceCounter.java new file mode 100644 index 0000000000..63441507db --- /dev/null +++ b/java/src/com/swiftnav/sbp/profiling/MsgProfilingResourceCounter.java @@ -0,0 +1,87 @@ +/* Copyright (C) 2015-2022 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ +package com.swiftnav.sbp.profiling; + +// This file was auto-generated from yaml/swiftnav/sbp/profiling.yaml by generate.py. +// Do not modify by hand! + + +import com.swiftnav.sbp.SBPBinaryException; +import com.swiftnav.sbp.SBPMessage; +import com.swiftnav.sbp.SBPStruct; +import org.json.JSONObject; + +/** + * SBP class for message MSG_PROFILING_RESOURCE_COUNTER (0xCF03). + * + *

You can have MSG_PROFILING_RESOURCE_COUNTER inherent its fields directly from an inherited SBP + * object, or construct it inline using a dict of its fields. + * + *

Information about resource buckets. Refer to product documentation to understand the meaning + * and values in this message. + */ +public class MsgProfilingResourceCounter extends SBPMessage { + public static final int TYPE = 0xCF03; + + /** Message number in complete sequence */ + public int seq_no; + + /** Length of message sequence */ + public int seq_len; + + /** List of resource buckets */ + public ResourceBucket[] buckets; + + public MsgProfilingResourceCounter(int sender) { + super(sender, TYPE); + } + + public MsgProfilingResourceCounter() { + super(TYPE); + } + + public MsgProfilingResourceCounter(SBPMessage msg) throws SBPBinaryException { + super(msg); + if (msg.type != TYPE) + throw new SBPBinaryException( + "Type mismatch for MsgProfilingResourceCounter, expected 52995, actual " + + msg.type); + } + + @Override + protected void parse(Parser parser) throws SBPBinaryException { + /* Parse fields from binary */ + seq_no = parser.getU8(); + seq_len = parser.getU8(); + buckets = parser.getArray(ResourceBucket.class); + } + + @Override + protected void build(Builder builder) { + builder.putU8(seq_no); + builder.putU8(seq_len); + builder.putArray(buckets); + } + + @Override + public JSONObject toJSON() { + JSONObject obj = super.toJSON(); + obj.put("seq_no", seq_no); + obj.put("seq_len", seq_len); + obj.put("buckets", SBPStruct.toJSONArray(buckets)); + return obj; + } + + @Override + public String getFriendlyName() { + return "PROFILING RESOURCE COUNTER"; + } +} diff --git a/java/src/com/swiftnav/sbp/profiling/MsgProfilingSystemInfo.java b/java/src/com/swiftnav/sbp/profiling/MsgProfilingSystemInfo.java new file mode 100644 index 0000000000..88518e919e --- /dev/null +++ b/java/src/com/swiftnav/sbp/profiling/MsgProfilingSystemInfo.java @@ -0,0 +1,93 @@ +/* Copyright (C) 2015-2022 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ +package com.swiftnav.sbp.profiling; + +// This file was auto-generated from yaml/swiftnav/sbp/profiling.yaml by generate.py. +// Do not modify by hand! + + +import com.swiftnav.sbp.SBPBinaryException; +import com.swiftnav.sbp.SBPMessage; +import java.math.BigInteger; +import org.json.JSONObject; + +/** + * SBP class for message MSG_PROFILING_SYSTEM_INFO (0xCF01). + * + *

You can have MSG_PROFILING_SYSTEM_INFO inherent its fields directly from an inherited SBP + * object, or construct it inline using a dict of its fields. + * + *

Contains basic information about system resource usage. System is defined in terms of the + * source of this message and may vary from sender to sender. Refer to product documentation to + * understand the exact scope and meaning of this message. + */ +public class MsgProfilingSystemInfo extends SBPMessage { + public static final int TYPE = 0xCF01; + + /** Total cpu time in microseconds consumed by this system */ + public BigInteger total_cpu_time; + + /** Age of the producing system in microseconds */ + public BigInteger age; + + /** Number of threads being tracked by this system */ + public int n_threads; + + /** Number of bytes allocated on the heap */ + public long heap_usage; + + public MsgProfilingSystemInfo(int sender) { + super(sender, TYPE); + } + + public MsgProfilingSystemInfo() { + super(TYPE); + } + + public MsgProfilingSystemInfo(SBPMessage msg) throws SBPBinaryException { + super(msg); + if (msg.type != TYPE) + throw new SBPBinaryException( + "Type mismatch for MsgProfilingSystemInfo, expected 52993, actual " + msg.type); + } + + @Override + protected void parse(Parser parser) throws SBPBinaryException { + /* Parse fields from binary */ + total_cpu_time = parser.getU64(); + age = parser.getU64(); + n_threads = parser.getU8(); + heap_usage = parser.getU32(); + } + + @Override + protected void build(Builder builder) { + builder.putU64(total_cpu_time); + builder.putU64(age); + builder.putU8(n_threads); + builder.putU32(heap_usage); + } + + @Override + public JSONObject toJSON() { + JSONObject obj = super.toJSON(); + obj.put("total_cpu_time", total_cpu_time); + obj.put("age", age); + obj.put("n_threads", n_threads); + obj.put("heap_usage", heap_usage); + return obj; + } + + @Override + public String getFriendlyName() { + return "PROFILING SYSTEM INFO"; + } +} diff --git a/java/src/com/swiftnav/sbp/profiling/MsgProfilingThreadInfo.java b/java/src/com/swiftnav/sbp/profiling/MsgProfilingThreadInfo.java new file mode 100644 index 0000000000..0c6ee2c7dc --- /dev/null +++ b/java/src/com/swiftnav/sbp/profiling/MsgProfilingThreadInfo.java @@ -0,0 +1,104 @@ +/* Copyright (C) 2015-2022 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ +package com.swiftnav.sbp.profiling; + +// This file was auto-generated from yaml/swiftnav/sbp/profiling.yaml by generate.py. +// Do not modify by hand! + + +import com.swiftnav.sbp.SBPBinaryException; +import com.swiftnav.sbp.SBPMessage; +import java.math.BigInteger; +import org.json.JSONObject; + +/** + * SBP class for message MSG_PROFILING_THREAD_INFO (0xCF02). + * + *

You can have MSG_PROFILING_THREAD_INFO inherent its fields directly from an inherited SBP + * object, or construct it inline using a dict of its fields. + * + *

Contains profiling information related to a single thread being tracked by the producing + * system. Refer to product documentation to understand the exact scope and meaning of this message. + */ +public class MsgProfilingThreadInfo extends SBPMessage { + public static final int TYPE = 0xCF02; + + /** Total cpu time in microseconds consumed by this thread */ + public BigInteger total_cpu_time; + + /** Age of the thread in microseconds */ + public BigInteger age; + + /** Thread state */ + public int state; + + /** Stack size in bytes */ + public long stack_size; + + /** Stack highwater usage in bytes */ + public long stack_usage; + + /** Thread name */ + public String name; + + public MsgProfilingThreadInfo(int sender) { + super(sender, TYPE); + } + + public MsgProfilingThreadInfo() { + super(TYPE); + } + + public MsgProfilingThreadInfo(SBPMessage msg) throws SBPBinaryException { + super(msg); + if (msg.type != TYPE) + throw new SBPBinaryException( + "Type mismatch for MsgProfilingThreadInfo, expected 52994, actual " + msg.type); + } + + @Override + protected void parse(Parser parser) throws SBPBinaryException { + /* Parse fields from binary */ + total_cpu_time = parser.getU64(); + age = parser.getU64(); + state = parser.getU8(); + stack_size = parser.getU32(); + stack_usage = parser.getU32(); + name = parser.getString(); + } + + @Override + protected void build(Builder builder) { + builder.putU64(total_cpu_time); + builder.putU64(age); + builder.putU8(state); + builder.putU32(stack_size); + builder.putU32(stack_usage); + builder.putString(name); + } + + @Override + public JSONObject toJSON() { + JSONObject obj = super.toJSON(); + obj.put("total_cpu_time", total_cpu_time); + obj.put("age", age); + obj.put("state", state); + obj.put("stack_size", stack_size); + obj.put("stack_usage", stack_usage); + obj.put("name", name); + return obj; + } + + @Override + public String getFriendlyName() { + return "PROFILING THREAD INFO"; + } +} diff --git a/java/src/com/swiftnav/sbp/profiling/ResourceBucket.java b/java/src/com/swiftnav/sbp/profiling/ResourceBucket.java new file mode 100644 index 0000000000..185c9a808d --- /dev/null +++ b/java/src/com/swiftnav/sbp/profiling/ResourceBucket.java @@ -0,0 +1,96 @@ +/* Copyright (C) 2015-2022 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ +package com.swiftnav.sbp.profiling; + +// This file was auto-generated from yaml/swiftnav/sbp/profiling.yaml by generate.py. +// Do not modify by hand! + + +import com.swiftnav.sbp.SBPBinaryException; +import com.swiftnav.sbp.SBPMessage; +import com.swiftnav.sbp.SBPStruct; +import org.json.JSONObject; + +public class ResourceBucket extends SBPStruct { + + /** Bucket name */ + public String name; + + /** Number of threads */ + public int thread; + + /** Number of mutexes */ + public int mutex; + + /** Number of condition variables */ + public int cv; + + /** Number of IO handles */ + public int io; + + /** Number of bytes allocated on the heap */ + public long heap_bytes_alloc; + + /** Number of bytes freed on the heap */ + public long heap_bytes_free; + + /** Number of bytes written to IO handles */ + public long io_write; + + /** Number of bytes read from IO handles */ + public long io_read; + + public ResourceBucket() {} + + @Override + public ResourceBucket parse(SBPMessage.Parser parser) throws SBPBinaryException { + /* Parse fields from binary */ + name = parser.getString(21); + thread = parser.getU8(); + mutex = parser.getU8(); + cv = parser.getU8(); + io = parser.getU8(); + heap_bytes_alloc = parser.getU32(); + heap_bytes_free = parser.getU32(); + io_write = parser.getU32(); + io_read = parser.getU32(); + return this; + } + + @Override + public void build(SBPMessage.Builder builder) { + /* Build fields into binary */ + builder.putString(name, 21); + builder.putU8(thread); + builder.putU8(mutex); + builder.putU8(cv); + builder.putU8(io); + builder.putU32(heap_bytes_alloc); + builder.putU32(heap_bytes_free); + builder.putU32(io_write); + builder.putU32(io_read); + } + + @Override + public JSONObject toJSON() { + JSONObject obj = new JSONObject(); + obj.put("name", name); + obj.put("thread", thread); + obj.put("mutex", mutex); + obj.put("cv", cv); + obj.put("io", io); + obj.put("heap_bytes_alloc", heap_bytes_alloc); + obj.put("heap_bytes_free", heap_bytes_free); + obj.put("io_write", io_write); + obj.put("io_read", io_read); + return obj; + } +} diff --git a/java/test/auto_check_sbp_profiling_MsgProfilingResourceCounterTest.java b/java/test/auto_check_sbp_profiling_MsgProfilingResourceCounterTest.java new file mode 100644 index 0000000000..21a438bcf6 --- /dev/null +++ b/java/test/auto_check_sbp_profiling_MsgProfilingResourceCounterTest.java @@ -0,0 +1,797 @@ +/* Copyright (C) 2015-2022 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ +package com.swiftnav.sbp.test; + +// This file was auto-generated from +// spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingResourceCounter.yaml by generate.py. Do +// not modify by hand! + + +import com.swiftnav.sbp.SBPMessage; +import com.swiftnav.sbp.profiling.MsgProfilingResourceCounter; +import java.math.BigInteger; +import org.json.JSONObject; +import org.junit.Test; + +public class auto_check_sbp_profiling_MsgProfilingResourceCounterTest { + + public static boolean debug = false; + private static final double DELTA = 1e-15; + + @Test + public void test1() throws Throwable { + if (debug) + System.out.format( + "%n%s%n", "auto_check_sbp_profiling_MsgProfilingResourceCounterTest.test1"); + byte[] payload = + new byte[] { + (byte) 1, + (byte) 3, + (byte) 70, + (byte) 117, + (byte) 115, + (byte) 105, + (byte) 111, + (byte) 110, + (byte) 32, + (byte) 101, + (byte) 110, + (byte) 103, + (byte) 105, + (byte) 110, + (byte) 101, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 1, + (byte) 2, + (byte) 2, + (byte) 0, + (byte) 248, + (byte) 38, + (byte) 14, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 78, + (byte) 84, + (byte) 82, + (byte) 73, + (byte) 80, + (byte) 32, + (byte) 99, + (byte) 108, + (byte) 105, + (byte) 101, + (byte) 110, + (byte) 116, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 1, + (byte) 1, + (byte) 1, + (byte) 1, + (byte) 230, + (byte) 73, + (byte) 1, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 111, + (byte) 3, + (byte) 0, + (byte) 0, + (byte) 64, + (byte) 76, + (byte) 0, + (byte) 0, + (byte) 83, + (byte) 83, + (byte) 82, + (byte) 50, + (byte) 79, + (byte) 83, + (byte) 82, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 1, + (byte) 1, + (byte) 1, + (byte) 0, + (byte) 72, + (byte) 13, + (byte) 66, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 80, + (byte) 101, + (byte) 114, + (byte) 105, + (byte) 111, + (byte) 100, + (byte) 105, + (byte) 99, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 1, + (byte) 2, + (byte) 1, + (byte) 0, + (byte) 72, + (byte) 197, + (byte) 3, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 73, + (byte) 77, + (byte) 85, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 1, + (byte) 1, + (byte) 1, + (byte) 1, + (byte) 129, + (byte) 71, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 95, + (byte) 102, + (byte) 0, + (byte) 0, + (byte) 115, + (byte) 98, + (byte) 112, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 5, + (byte) 2, + (byte) 2, + (byte) 2, + (byte) 243, + (byte) 169, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 187, + (byte) 151, + (byte) 3, + (byte) 0, + (byte) 242, + (byte) 1, + (byte) 0, + (byte) 0, + }; + SBPMessage sbp = new SBPMessage(0x1000, 0xcf03, payload); + MsgProfilingResourceCounter msg = new MsgProfilingResourceCounter(sbp); + JSONObject json = msg.toJSON(); + Number value; + Number expected; + value = msg.buckets[0].cv; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[0].cv + "' != '" + 2 + "'", + value.equals(BigInteger.valueOf(2L))); + } else { + value = value.longValue(); + expected = 2L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[0].heap_bytes_alloc; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[0].heap_bytes_alloc + "' != '" + 927480 + "'", + value.equals(BigInteger.valueOf(927480L))); + } else { + value = value.longValue(); + expected = 927480L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[0].heap_bytes_free; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[0].heap_bytes_free + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[0].io; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[0].io + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[0].io_read; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[0].io_read + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[0].io_write; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[0].io_write + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[0].mutex; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[0].mutex + "' != '" + 2 + "'", + value.equals(BigInteger.valueOf(2L))); + } else { + value = value.longValue(); + expected = 2L; + org.junit.Assert.assertEquals(value, expected); + } + org.junit.Assert.assertEquals(msg.buckets[0].name, "Fusion engine"); + value = msg.buckets[0].thread; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[0].thread + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[1].cv; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[1].cv + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[1].heap_bytes_alloc; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[1].heap_bytes_alloc + "' != '" + 84454 + "'", + value.equals(BigInteger.valueOf(84454L))); + } else { + value = value.longValue(); + expected = 84454L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[1].heap_bytes_free; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[1].heap_bytes_free + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[1].io; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[1].io + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[1].io_read; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[1].io_read + "' != '" + 19520 + "'", + value.equals(BigInteger.valueOf(19520L))); + } else { + value = value.longValue(); + expected = 19520L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[1].io_write; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[1].io_write + "' != '" + 879 + "'", + value.equals(BigInteger.valueOf(879L))); + } else { + value = value.longValue(); + expected = 879L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[1].mutex; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[1].mutex + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + org.junit.Assert.assertEquals(msg.buckets[1].name, "NTRIP client"); + value = msg.buckets[1].thread; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[1].thread + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[2].cv; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[2].cv + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[2].heap_bytes_alloc; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[2].heap_bytes_alloc + "' != '" + 4328776 + "'", + value.equals(BigInteger.valueOf(4328776L))); + } else { + value = value.longValue(); + expected = 4328776L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[2].heap_bytes_free; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[2].heap_bytes_free + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[2].io; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[2].io + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[2].io_read; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[2].io_read + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[2].io_write; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[2].io_write + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[2].mutex; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[2].mutex + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + org.junit.Assert.assertEquals(msg.buckets[2].name, "SSR2OSR"); + value = msg.buckets[2].thread; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[2].thread + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[3].cv; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[3].cv + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[3].heap_bytes_alloc; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[3].heap_bytes_alloc + "' != '" + 247112 + "'", + value.equals(BigInteger.valueOf(247112L))); + } else { + value = value.longValue(); + expected = 247112L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[3].heap_bytes_free; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[3].heap_bytes_free + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[3].io; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[3].io + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[3].io_read; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[3].io_read + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[3].io_write; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[3].io_write + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[3].mutex; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[3].mutex + "' != '" + 2 + "'", + value.equals(BigInteger.valueOf(2L))); + } else { + value = value.longValue(); + expected = 2L; + org.junit.Assert.assertEquals(value, expected); + } + org.junit.Assert.assertEquals(msg.buckets[3].name, "Periodic"); + value = msg.buckets[3].thread; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[3].thread + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[4].cv; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[4].cv + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[4].heap_bytes_alloc; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[4].heap_bytes_alloc + "' != '" + 18305 + "'", + value.equals(BigInteger.valueOf(18305L))); + } else { + value = value.longValue(); + expected = 18305L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[4].heap_bytes_free; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[4].heap_bytes_free + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[4].io; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[4].io + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[4].io_read; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[4].io_read + "' != '" + 26207 + "'", + value.equals(BigInteger.valueOf(26207L))); + } else { + value = value.longValue(); + expected = 26207L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[4].io_write; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[4].io_write + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[4].mutex; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[4].mutex + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + org.junit.Assert.assertEquals(msg.buckets[4].name, "IMU"); + value = msg.buckets[4].thread; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[4].thread + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[5].cv; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[5].cv + "' != '" + 2 + "'", + value.equals(BigInteger.valueOf(2L))); + } else { + value = value.longValue(); + expected = 2L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[5].heap_bytes_alloc; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[5].heap_bytes_alloc + "' != '" + 43507 + "'", + value.equals(BigInteger.valueOf(43507L))); + } else { + value = value.longValue(); + expected = 43507L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[5].heap_bytes_free; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[5].heap_bytes_free + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[5].io; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[5].io + "' != '" + 2 + "'", + value.equals(BigInteger.valueOf(2L))); + } else { + value = value.longValue(); + expected = 2L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[5].io_read; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[5].io_read + "' != '" + 498 + "'", + value.equals(BigInteger.valueOf(498L))); + } else { + value = value.longValue(); + expected = 498L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[5].io_write; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[5].io_write + "' != '" + 235451 + "'", + value.equals(BigInteger.valueOf(235451L))); + } else { + value = value.longValue(); + expected = 235451L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.buckets[5].mutex; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[5].mutex + "' != '" + 2 + "'", + value.equals(BigInteger.valueOf(2L))); + } else { + value = value.longValue(); + expected = 2L; + org.junit.Assert.assertEquals(value, expected); + } + org.junit.Assert.assertEquals(msg.buckets[5].name, "sbp"); + value = msg.buckets[5].thread; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.buckets[5].thread + "' != '" + 5 + "'", + value.equals(BigInteger.valueOf(5L))); + } else { + value = value.longValue(); + expected = 5L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.seq_len; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.seq_len + "' != '" + 3 + "'", value.equals(BigInteger.valueOf(3L))); + } else { + value = value.longValue(); + expected = 3L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.seq_no; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.seq_no + "' != '" + 1 + "'", value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + + org.junit.Assert.assertNotEquals("", msg.getFriendlyName()); + } +} diff --git a/java/test/auto_check_sbp_profiling_MsgProfilingSystemInfoTest.java b/java/test/auto_check_sbp_profiling_MsgProfilingSystemInfoTest.java new file mode 100644 index 0000000000..ea69c129a5 --- /dev/null +++ b/java/test/auto_check_sbp_profiling_MsgProfilingSystemInfoTest.java @@ -0,0 +1,88 @@ +/* Copyright (C) 2015-2022 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ +package com.swiftnav.sbp.test; + +// This file was auto-generated from +// spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingSystemInfo.yaml by generate.py. Do not +// modify by hand! + + +import com.swiftnav.sbp.SBPMessage; +import com.swiftnav.sbp.profiling.MsgProfilingSystemInfo; +import java.math.BigInteger; +import org.json.JSONObject; +import org.junit.Test; + +public class auto_check_sbp_profiling_MsgProfilingSystemInfoTest { + + public static boolean debug = false; + private static final double DELTA = 1e-15; + + @Test + public void test1() throws Throwable { + if (debug) + System.out.format( + "%n%s%n", "auto_check_sbp_profiling_MsgProfilingSystemInfoTest.test1"); + byte[] payload = + new byte[] { + (byte) 98, (byte) 40, (byte) 52, (byte) 0, (byte) 0, (byte) 0, (byte) 0, + (byte) 0, (byte) 114, (byte) 12, (byte) 157, (byte) 0, (byte) 0, (byte) 0, + (byte) 0, (byte) 0, (byte) 27, (byte) 72, (byte) 195, (byte) 226, (byte) 0, + }; + SBPMessage sbp = new SBPMessage(0x1000, 0xcf01, payload); + MsgProfilingSystemInfo msg = new MsgProfilingSystemInfo(sbp); + JSONObject json = msg.toJSON(); + Number value; + Number expected; + value = msg.age; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.age + "' != '" + 10292338 + "'", + value.equals(BigInteger.valueOf(10292338L))); + } else { + value = value.longValue(); + expected = 10292338L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.heap_usage; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.heap_usage + "' != '" + 14861128 + "'", + value.equals(BigInteger.valueOf(14861128L))); + } else { + value = value.longValue(); + expected = 14861128L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.n_threads; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.n_threads + "' != '" + 27 + "'", + value.equals(BigInteger.valueOf(27L))); + } else { + value = value.longValue(); + expected = 27L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.total_cpu_time; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.total_cpu_time + "' != '" + 3418210 + "'", + value.equals(BigInteger.valueOf(3418210L))); + } else { + value = value.longValue(); + expected = 3418210L; + org.junit.Assert.assertEquals(value, expected); + } + + org.junit.Assert.assertNotEquals("", msg.getFriendlyName()); + } +} diff --git a/java/test/auto_check_sbp_profiling_MsgProfilingThreadInfoTest.java b/java/test/auto_check_sbp_profiling_MsgProfilingThreadInfoTest.java new file mode 100644 index 0000000000..89ca33b4a8 Binary files /dev/null and b/java/test/auto_check_sbp_profiling_MsgProfilingThreadInfoTest.java differ diff --git a/javascript/sbp/profiling.js b/javascript/sbp/profiling.js index fd2f5a082f..274edc3b69 100644 --- a/javascript/sbp/profiling.js +++ b/javascript/sbp/profiling.js @@ -76,7 +76,182 @@ MsgMeasurementPoint.prototype.fieldSpec.push(['slice_time', 'writeUInt64LE', 8]) MsgMeasurementPoint.prototype.fieldSpec.push(['line', 'writeUInt16LE', 2]); MsgMeasurementPoint.prototype.fieldSpec.push(['func', 'string', null]); +/** + * SBP class for message MSG_PROFILING_SYSTEM_INFO (0xCF01). + * + * Contains basic information about system resource usage. System is defined in + * terms of the source of this message and may vary from sender to sender. Refer + * to product documentation to understand the exact scope and meaning of this + * message. + * + * Fields in the SBP payload (`sbp.payload`): + * @field total_cpu_time number (unsigned 64-bit int, 8 bytes) Total cpu time in microseconds consumed by this system + * @field age number (unsigned 64-bit int, 8 bytes) Age of the producing system in microseconds + * @field n_threads number (unsigned 8-bit int, 1 byte) Number of threads being tracked by this system + * @field heap_usage number (unsigned 32-bit int, 4 bytes) Number of bytes allocated on the heap + * + * @param sbp An SBP object with a payload to be decoded. + */ +let MsgProfilingSystemInfo = function (sbp, fields) { + SBP.call(this, sbp); + this.messageType = "MSG_PROFILING_SYSTEM_INFO"; + this.fields = (fields || this.parser.parse(sbp.payload)); + + return this; +}; +MsgProfilingSystemInfo.prototype = Object.create(SBP.prototype); +MsgProfilingSystemInfo.prototype.messageType = "MSG_PROFILING_SYSTEM_INFO"; +MsgProfilingSystemInfo.prototype.msg_type = 0xCF01; +MsgProfilingSystemInfo.prototype.constructor = MsgProfilingSystemInfo; +MsgProfilingSystemInfo.prototype.parser = new Parser() + .endianess('little') + .uint64('total_cpu_time') + .uint64('age') + .uint8('n_threads') + .uint32('heap_usage'); +MsgProfilingSystemInfo.prototype.fieldSpec = []; +MsgProfilingSystemInfo.prototype.fieldSpec.push(['total_cpu_time', 'writeUInt64LE', 8]); +MsgProfilingSystemInfo.prototype.fieldSpec.push(['age', 'writeUInt64LE', 8]); +MsgProfilingSystemInfo.prototype.fieldSpec.push(['n_threads', 'writeUInt8', 1]); +MsgProfilingSystemInfo.prototype.fieldSpec.push(['heap_usage', 'writeUInt32LE', 4]); + +/** + * SBP class for message MSG_PROFILING_THREAD_INFO (0xCF02). + * + * Contains profiling information related to a single thread being tracked by the + * producing system. Refer to product documentation to understand the exact scope + * and meaning of this message. + * + * Fields in the SBP payload (`sbp.payload`): + * @field total_cpu_time number (unsigned 64-bit int, 8 bytes) Total cpu time in microseconds consumed by this thread + * @field age number (unsigned 64-bit int, 8 bytes) Age of the thread in microseconds + * @field state number (unsigned 8-bit int, 1 byte) Thread state + * @field stack_size number (unsigned 32-bit int, 4 bytes) Stack size in bytes + * @field stack_usage number (unsigned 32-bit int, 4 bytes) Stack highwater usage in bytes + * @field name string Thread name + * + * @param sbp An SBP object with a payload to be decoded. + */ +let MsgProfilingThreadInfo = function (sbp, fields) { + SBP.call(this, sbp); + this.messageType = "MSG_PROFILING_THREAD_INFO"; + this.fields = (fields || this.parser.parse(sbp.payload)); + + return this; +}; +MsgProfilingThreadInfo.prototype = Object.create(SBP.prototype); +MsgProfilingThreadInfo.prototype.messageType = "MSG_PROFILING_THREAD_INFO"; +MsgProfilingThreadInfo.prototype.msg_type = 0xCF02; +MsgProfilingThreadInfo.prototype.constructor = MsgProfilingThreadInfo; +MsgProfilingThreadInfo.prototype.parser = new Parser() + .endianess('little') + .uint64('total_cpu_time') + .uint64('age') + .uint8('state') + .uint32('stack_size') + .uint32('stack_usage') + .string('name', { greedy: true }); +MsgProfilingThreadInfo.prototype.fieldSpec = []; +MsgProfilingThreadInfo.prototype.fieldSpec.push(['total_cpu_time', 'writeUInt64LE', 8]); +MsgProfilingThreadInfo.prototype.fieldSpec.push(['age', 'writeUInt64LE', 8]); +MsgProfilingThreadInfo.prototype.fieldSpec.push(['state', 'writeUInt8', 1]); +MsgProfilingThreadInfo.prototype.fieldSpec.push(['stack_size', 'writeUInt32LE', 4]); +MsgProfilingThreadInfo.prototype.fieldSpec.push(['stack_usage', 'writeUInt32LE', 4]); +MsgProfilingThreadInfo.prototype.fieldSpec.push(['name', 'string', null]); + +/** + * SBP class for message fragment ResourceBucket + * + * Information about allocation of various resources grouped by buckets. Refer to + * product documentation to understand the meaning and values in this message. + * + * Fields in the SBP payload (`sbp.payload`): + * @field name string Bucket name + * @field thread number (unsigned 8-bit int, 1 byte) Number of threads + * @field mutex number (unsigned 8-bit int, 1 byte) Number of mutexes + * @field cv number (unsigned 8-bit int, 1 byte) Number of condition variables + * @field io number (unsigned 8-bit int, 1 byte) Number of IO handles + * @field heap_bytes_alloc number (unsigned 32-bit int, 4 bytes) Number of bytes allocated on the heap + * @field heap_bytes_free number (unsigned 32-bit int, 4 bytes) Number of bytes freed on the heap + * @field io_write number (unsigned 32-bit int, 4 bytes) Number of bytes written to IO handles + * @field io_read number (unsigned 32-bit int, 4 bytes) Number of bytes read from IO handles + * + * @param sbp An SBP object with a payload to be decoded. + */ +let ResourceBucket = function (sbp, fields) { + SBP.call(this, sbp); + this.messageType = "ResourceBucket"; + this.fields = (fields || this.parser.parse(sbp.payload)); + + return this; +}; +ResourceBucket.prototype = Object.create(SBP.prototype); +ResourceBucket.prototype.messageType = "ResourceBucket"; +ResourceBucket.prototype.constructor = ResourceBucket; +ResourceBucket.prototype.parser = new Parser() + .endianess('little') + .string('name', { length: 21 }) + .uint8('thread') + .uint8('mutex') + .uint8('cv') + .uint8('io') + .uint32('heap_bytes_alloc') + .uint32('heap_bytes_free') + .uint32('io_write') + .uint32('io_read'); +ResourceBucket.prototype.fieldSpec = []; +ResourceBucket.prototype.fieldSpec.push(['name', 'string', 21]); +ResourceBucket.prototype.fieldSpec.push(['thread', 'writeUInt8', 1]); +ResourceBucket.prototype.fieldSpec.push(['mutex', 'writeUInt8', 1]); +ResourceBucket.prototype.fieldSpec.push(['cv', 'writeUInt8', 1]); +ResourceBucket.prototype.fieldSpec.push(['io', 'writeUInt8', 1]); +ResourceBucket.prototype.fieldSpec.push(['heap_bytes_alloc', 'writeUInt32LE', 4]); +ResourceBucket.prototype.fieldSpec.push(['heap_bytes_free', 'writeUInt32LE', 4]); +ResourceBucket.prototype.fieldSpec.push(['io_write', 'writeUInt32LE', 4]); +ResourceBucket.prototype.fieldSpec.push(['io_read', 'writeUInt32LE', 4]); + +/** + * SBP class for message MSG_PROFILING_RESOURCE_COUNTER (0xCF03). + * + * Information about resource buckets. Refer to product documentation to understand + * the meaning and values in this message. + * + * Fields in the SBP payload (`sbp.payload`): + * @field seq_no number (unsigned 8-bit int, 1 byte) Message number in complete sequence + * @field seq_len number (unsigned 8-bit int, 1 byte) Length of message sequence + * @field buckets array List of resource buckets + * + * @param sbp An SBP object with a payload to be decoded. + */ +let MsgProfilingResourceCounter = function (sbp, fields) { + SBP.call(this, sbp); + this.messageType = "MSG_PROFILING_RESOURCE_COUNTER"; + this.fields = (fields || this.parser.parse(sbp.payload)); + + return this; +}; +MsgProfilingResourceCounter.prototype = Object.create(SBP.prototype); +MsgProfilingResourceCounter.prototype.messageType = "MSG_PROFILING_RESOURCE_COUNTER"; +MsgProfilingResourceCounter.prototype.msg_type = 0xCF03; +MsgProfilingResourceCounter.prototype.constructor = MsgProfilingResourceCounter; +MsgProfilingResourceCounter.prototype.parser = new Parser() + .endianess('little') + .uint8('seq_no') + .uint8('seq_len') + .array('buckets', { type: ResourceBucket.prototype.parser, readUntil: 'eof' }); +MsgProfilingResourceCounter.prototype.fieldSpec = []; +MsgProfilingResourceCounter.prototype.fieldSpec.push(['seq_no', 'writeUInt8', 1]); +MsgProfilingResourceCounter.prototype.fieldSpec.push(['seq_len', 'writeUInt8', 1]); +MsgProfilingResourceCounter.prototype.fieldSpec.push(['buckets', 'array', ResourceBucket.prototype.fieldSpec, function () { return this.fields.array.length; }, null]); + module.exports = { 0xCF00: MsgMeasurementPoint, MsgMeasurementPoint: MsgMeasurementPoint, + 0xCF01: MsgProfilingSystemInfo, + MsgProfilingSystemInfo: MsgProfilingSystemInfo, + 0xCF02: MsgProfilingThreadInfo, + MsgProfilingThreadInfo: MsgProfilingThreadInfo, + ResourceBucket: ResourceBucket, + 0xCF03: MsgProfilingResourceCounter, + MsgProfilingResourceCounter: MsgProfilingResourceCounter, } \ No newline at end of file diff --git a/javascript/tests/test_dispatch_decoder.js b/javascript/tests/test_dispatch_decoder.js index d4ab9252af..37821545d9 100644 --- a/javascript/tests/test_dispatch_decoder.js +++ b/javascript/tests/test_dispatch_decoder.js @@ -98,7 +98,8 @@ describe('test packages based on YAML descriptors, through the dispatcher', func if (filename.indexOf('test_MsgFlashDone.yaml') === -1 && filename.indexOf('test_MsgM25FlashWriteStatus.yaml') === -1 && filename.indexOf('test_MsgBootloaderJumptoApp.yaml') === -1 && - filename.indexOf('test_MsgMeasurementPoint.yaml') === -1) { + filename.indexOf('test_MsgMeasurementPoint.yaml') === -1 && + filename.indexOf('test_MsgProfilingResourceCounter.yaml') === -1) { it('should parse binary sbp and payload with leading truncated message', function (done) { var rs = new Readable(); var packetBuf = new Buffer(testSpec['raw_packet'], 'base64'); diff --git a/jsonschema/MsgProfilingResourceCounter.json b/jsonschema/MsgProfilingResourceCounter.json new file mode 100644 index 0000000000..fd091e4191 --- /dev/null +++ b/jsonschema/MsgProfilingResourceCounter.json @@ -0,0 +1,28 @@ +{ + "copyright": [ + "Copyright (C) 2019-2021 Swift Navigation Inc.", + "Contact: https://support.swiftnav.com", + "", + "This source is subject to the license found in the file 'LICENSE' which must", + "be be distributed together with this source. All other rights reserved.", + "", + "THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF ANY KIND,", + "EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED", + "WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE." + ], + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "#MsgProfilingResourceCounter", + "title":"MsgProfilingResourceCounter", + "description":"Information about resource buckets. Refer to product documentation to understand the meaning and values in this message.\n", + "type": "object", + "properties": { + "seq_no": {"type": "integer"}, + "seq_len": {"type": "integer"}, + "buckets": {"type": "array", "items": {"$ref": "ResourceBucket.json"}} + }, + "required": [ + "seq_no", + "seq_len", + "buckets" + ] +} \ No newline at end of file diff --git a/jsonschema/MsgProfilingSystemInfo.json b/jsonschema/MsgProfilingSystemInfo.json new file mode 100644 index 0000000000..2a9ba9a56a --- /dev/null +++ b/jsonschema/MsgProfilingSystemInfo.json @@ -0,0 +1,30 @@ +{ + "copyright": [ + "Copyright (C) 2019-2021 Swift Navigation Inc.", + "Contact: https://support.swiftnav.com", + "", + "This source is subject to the license found in the file 'LICENSE' which must", + "be be distributed together with this source. All other rights reserved.", + "", + "THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF ANY KIND,", + "EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED", + "WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE." + ], + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "#MsgProfilingSystemInfo", + "title":"MsgProfilingSystemInfo", + "description":"Contains basic information about system resource usage. System is defined in terms of the source of this message and may vary from sender to sender. Refer to product documentation to understand the exact scope and meaning of this message.\n", + "type": "object", + "properties": { + "total_cpu_time": {"type": "integer"}, + "age": {"type": "integer"}, + "n_threads": {"type": "integer"}, + "heap_usage": {"type": "integer"} + }, + "required": [ + "total_cpu_time", + "age", + "n_threads", + "heap_usage" + ] +} \ No newline at end of file diff --git a/jsonschema/MsgProfilingThreadInfo.json b/jsonschema/MsgProfilingThreadInfo.json new file mode 100644 index 0000000000..0eced825e4 --- /dev/null +++ b/jsonschema/MsgProfilingThreadInfo.json @@ -0,0 +1,34 @@ +{ + "copyright": [ + "Copyright (C) 2019-2021 Swift Navigation Inc.", + "Contact: https://support.swiftnav.com", + "", + "This source is subject to the license found in the file 'LICENSE' which must", + "be be distributed together with this source. All other rights reserved.", + "", + "THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF ANY KIND,", + "EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED", + "WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE." + ], + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "#MsgProfilingThreadInfo", + "title":"MsgProfilingThreadInfo", + "description":"Contains profiling information related to a single thread being tracked by the producing system. Refer to product documentation to understand the exact scope and meaning of this message.\n", + "type": "object", + "properties": { + "total_cpu_time": {"type": "integer"}, + "age": {"type": "integer"}, + "state": {"type": "integer"}, + "stack_size": {"type": "integer"}, + "stack_usage": {"type": "integer"}, + "name": {"type": "string"} + }, + "required": [ + "total_cpu_time", + "age", + "state", + "stack_size", + "stack_usage", + "name" + ] +} \ No newline at end of file diff --git a/jsonschema/ResourceBucket.json b/jsonschema/ResourceBucket.json new file mode 100644 index 0000000000..40c51a3570 --- /dev/null +++ b/jsonschema/ResourceBucket.json @@ -0,0 +1,40 @@ +{ + "copyright": [ + "Copyright (C) 2019-2021 Swift Navigation Inc.", + "Contact: https://support.swiftnav.com", + "", + "This source is subject to the license found in the file 'LICENSE' which must", + "be be distributed together with this source. All other rights reserved.", + "", + "THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF ANY KIND,", + "EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED", + "WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE." + ], + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "#ResourceBucket", + "title":"ResourceBucket", + "description":"Information about allocation of various resources grouped by buckets. Refer to product documentation to understand the meaning and values in this message.\n", + "type": "object", + "properties": { + "name": {"type": "string"}, + "thread": {"type": "integer"}, + "mutex": {"type": "integer"}, + "cv": {"type": "integer"}, + "io": {"type": "integer"}, + "heap_bytes_alloc": {"type": "integer"}, + "heap_bytes_free": {"type": "integer"}, + "io_write": {"type": "integer"}, + "io_read": {"type": "integer"} + }, + "required": [ + "name", + "thread", + "mutex", + "cv", + "io", + "heap_bytes_alloc", + "heap_bytes_free", + "io_write", + "io_read" + ] +} \ No newline at end of file diff --git a/kaitai/ksy/profiling.ksy b/kaitai/ksy/profiling.ksy index 6acde05f09..15185c6062 100644 --- a/kaitai/ksy/profiling.ksy +++ b/kaitai/ksy/profiling.ksy @@ -64,4 +64,125 @@ types: type: str encoding: ascii size-eos: true + + msg_profiling_system_info: + doc: | + Contains basic information about system resource usage. System is + defined in terms of the source of this message and may vary from sender + to sender. Refer to product documentation to understand the exact scope + and meaning of this message. + seq: + - id: total_cpu_time + doc: | + Total cpu time in microseconds consumed by this system + type: u8 + - id: age + doc: | + Age of the producing system in microseconds + type: u8 + - id: n_threads + doc: | + Number of threads being tracked by this system + type: u1 + - id: heap_usage + doc: | + Number of bytes allocated on the heap + type: u4 + + msg_profiling_thread_info: + doc: | + Contains profiling information related to a single thread being tracked + by the producing system. Refer to product documentation to understand + the exact scope and meaning of this message. + seq: + - id: total_cpu_time + doc: | + Total cpu time in microseconds consumed by this thread + type: u8 + - id: age + doc: | + Age of the thread in microseconds + type: u8 + - id: state + doc: | + Thread state + type: u1 + - id: stack_size + doc: | + Stack size in bytes + type: u4 + - id: stack_usage + doc: | + Stack highwater usage in bytes + type: u4 + - id: name + doc: | + Thread name + type: str + encoding: ascii + size-eos: true + + resource_bucket: + doc: | + Information about allocation of various resources grouped by buckets. + Refer to product documentation to understand the meaning and values in + this message. + seq: + - id: name + doc: | + Bucket name + type: str + encoding: ascii + size: 21 + - id: thread + doc: | + Number of threads + type: u1 + - id: mutex + doc: | + Number of mutexes + type: u1 + - id: cv + doc: | + Number of condition variables + type: u1 + - id: io + doc: | + Number of IO handles + type: u1 + - id: heap_bytes_alloc + doc: | + Number of bytes allocated on the heap + type: u4 + - id: heap_bytes_free + doc: | + Number of bytes freed on the heap + type: u4 + - id: io_write + doc: | + Number of bytes written to IO handles + type: u4 + - id: io_read + doc: | + Number of bytes read from IO handles + type: u4 + + msg_profiling_resource_counter: + doc: | + Information about resource buckets. Refer to product documentation to + understand the meaning and values in this message. + seq: + - id: seq_no + doc: | + Message number in complete sequence + type: u1 + - id: seq_len + doc: | + Length of message sequence + type: u1 + - id: buckets + doc: | + List of resource buckets + type: resource_bucket + repeat: eos \ No newline at end of file diff --git a/kaitai/ksy/sbp.ksy b/kaitai/ksy/sbp.ksy index 2200d6f0a2..7579e5e311 100644 --- a/kaitai/ksy/sbp.ksy +++ b/kaitai/ksy/sbp.ksy @@ -237,6 +237,9 @@ enums: 191: msg_front_end_gain 52992: msg_measurement_point + 52993: msg_profiling_system_info + 52994: msg_profiling_thread_info + 52995: msg_profiling_resource_counter 30583: msg_sbas_raw @@ -516,6 +519,9 @@ types: 191: piksi::msg_front_end_gain 52992: profiling::msg_measurement_point + 52993: profiling::msg_profiling_system_info + 52994: profiling::msg_profiling_thread_info + 52995: profiling::msg_profiling_resource_counter 30583: sbas::msg_sbas_raw diff --git a/kaitai/perl/KaitaiSbp/Profiling.pm b/kaitai/perl/KaitaiSbp/Profiling.pm index 8fb5c72b46..1c569811c2 100644 --- a/kaitai/perl/KaitaiSbp/Profiling.pm +++ b/kaitai/perl/KaitaiSbp/Profiling.pm @@ -37,6 +37,148 @@ sub _read { } +######################################################################## +package Profiling::ResourceBucket; + +our @ISA = 'IO::KaitaiStruct::Struct'; + +sub from_file { + my ($class, $filename) = @_; + my $fd; + + open($fd, '<', $filename) or return undef; + binmode($fd); + return new($class, IO::KaitaiStruct::Stream->new($fd)); +} + +sub new { + my ($class, $_io, $_parent, $_root) = @_; + my $self = IO::KaitaiStruct::Struct->new($_io); + + bless $self, $class; + $self->{_parent} = $_parent; + $self->{_root} = $_root || $self;; + + $self->_read(); + + return $self; +} + +sub _read { + my ($self) = @_; + + $self->{name} = Encode::decode("ascii", $self->{_io}->read_bytes(21)); + $self->{thread} = $self->{_io}->read_u1(); + $self->{mutex} = $self->{_io}->read_u1(); + $self->{cv} = $self->{_io}->read_u1(); + $self->{io} = $self->{_io}->read_u1(); + $self->{heap_bytes_alloc} = $self->{_io}->read_u4le(); + $self->{heap_bytes_free} = $self->{_io}->read_u4le(); + $self->{io_write} = $self->{_io}->read_u4le(); + $self->{io_read} = $self->{_io}->read_u4le(); +} + +sub name { + my ($self) = @_; + return $self->{name}; +} + +sub thread { + my ($self) = @_; + return $self->{thread}; +} + +sub mutex { + my ($self) = @_; + return $self->{mutex}; +} + +sub cv { + my ($self) = @_; + return $self->{cv}; +} + +sub io { + my ($self) = @_; + return $self->{io}; +} + +sub heap_bytes_alloc { + my ($self) = @_; + return $self->{heap_bytes_alloc}; +} + +sub heap_bytes_free { + my ($self) = @_; + return $self->{heap_bytes_free}; +} + +sub io_write { + my ($self) = @_; + return $self->{io_write}; +} + +sub io_read { + my ($self) = @_; + return $self->{io_read}; +} + +######################################################################## +package Profiling::MsgProfilingSystemInfo; + +our @ISA = 'IO::KaitaiStruct::Struct'; + +sub from_file { + my ($class, $filename) = @_; + my $fd; + + open($fd, '<', $filename) or return undef; + binmode($fd); + return new($class, IO::KaitaiStruct::Stream->new($fd)); +} + +sub new { + my ($class, $_io, $_parent, $_root) = @_; + my $self = IO::KaitaiStruct::Struct->new($_io); + + bless $self, $class; + $self->{_parent} = $_parent; + $self->{_root} = $_root || $self;; + + $self->_read(); + + return $self; +} + +sub _read { + my ($self) = @_; + + $self->{total_cpu_time} = $self->{_io}->read_u8le(); + $self->{age} = $self->{_io}->read_u8le(); + $self->{n_threads} = $self->{_io}->read_u1(); + $self->{heap_usage} = $self->{_io}->read_u4le(); +} + +sub total_cpu_time { + my ($self) = @_; + return $self->{total_cpu_time}; +} + +sub age { + my ($self) = @_; + return $self->{age}; +} + +sub n_threads { + my ($self) = @_; + return $self->{n_threads}; +} + +sub heap_usage { + my ($self) = @_; + return $self->{heap_usage}; +} + ######################################################################## package Profiling::MsgMeasurementPoint; @@ -123,4 +265,125 @@ sub func { return $self->{func}; } +######################################################################## +package Profiling::MsgProfilingResourceCounter; + +our @ISA = 'IO::KaitaiStruct::Struct'; + +sub from_file { + my ($class, $filename) = @_; + my $fd; + + open($fd, '<', $filename) or return undef; + binmode($fd); + return new($class, IO::KaitaiStruct::Stream->new($fd)); +} + +sub new { + my ($class, $_io, $_parent, $_root) = @_; + my $self = IO::KaitaiStruct::Struct->new($_io); + + bless $self, $class; + $self->{_parent} = $_parent; + $self->{_root} = $_root || $self;; + + $self->_read(); + + return $self; +} + +sub _read { + my ($self) = @_; + + $self->{seq_no} = $self->{_io}->read_u1(); + $self->{seq_len} = $self->{_io}->read_u1(); + $self->{buckets} = []; + while (!$self->{_io}->is_eof()) { + push @{$self->{buckets}}, Profiling::ResourceBucket->new($self->{_io}, $self, $self->{_root}); + } +} + +sub seq_no { + my ($self) = @_; + return $self->{seq_no}; +} + +sub seq_len { + my ($self) = @_; + return $self->{seq_len}; +} + +sub buckets { + my ($self) = @_; + return $self->{buckets}; +} + +######################################################################## +package Profiling::MsgProfilingThreadInfo; + +our @ISA = 'IO::KaitaiStruct::Struct'; + +sub from_file { + my ($class, $filename) = @_; + my $fd; + + open($fd, '<', $filename) or return undef; + binmode($fd); + return new($class, IO::KaitaiStruct::Stream->new($fd)); +} + +sub new { + my ($class, $_io, $_parent, $_root) = @_; + my $self = IO::KaitaiStruct::Struct->new($_io); + + bless $self, $class; + $self->{_parent} = $_parent; + $self->{_root} = $_root || $self;; + + $self->_read(); + + return $self; +} + +sub _read { + my ($self) = @_; + + $self->{total_cpu_time} = $self->{_io}->read_u8le(); + $self->{age} = $self->{_io}->read_u8le(); + $self->{state} = $self->{_io}->read_u1(); + $self->{stack_size} = $self->{_io}->read_u4le(); + $self->{stack_usage} = $self->{_io}->read_u4le(); + $self->{name} = Encode::decode("ascii", $self->{_io}->read_bytes_full()); +} + +sub total_cpu_time { + my ($self) = @_; + return $self->{total_cpu_time}; +} + +sub age { + my ($self) = @_; + return $self->{age}; +} + +sub state { + my ($self) = @_; + return $self->{state}; +} + +sub stack_size { + my ($self) = @_; + return $self->{stack_size}; +} + +sub stack_usage { + my ($self) = @_; + return $self->{stack_usage}; +} + +sub name { + my ($self) = @_; + return $self->{name}; +} + 1; diff --git a/kaitai/perl/KaitaiSbp/Sbp.pm b/kaitai/perl/KaitaiSbp/Sbp.pm index 15f62cdc37..d15db3734f 100644 --- a/kaitai/perl/KaitaiSbp/Sbp.pm +++ b/kaitai/perl/KaitaiSbp/Sbp.pm @@ -264,6 +264,9 @@ our $MSG_IDS_MSG_LINUX_CPU_STATE = 32520; our $MSG_IDS_MSG_LINUX_MEM_STATE = 32521; our $MSG_IDS_MSG_LINUX_SYS_STATE = 32522; our $MSG_IDS_MSG_MEASUREMENT_POINT = 52992; +our $MSG_IDS_MSG_PROFILING_SYSTEM_INFO = 52993; +our $MSG_IDS_MSG_PROFILING_THREAD_INFO = 52994; +our $MSG_IDS_MSG_PROFILING_RESOURCE_COUNTER = 52995; our $MSG_IDS_MSG_STARTUP = 65280; our $MSG_IDS_MSG_DGNSS_STATUS = 65282; our $MSG_IDS_MSG_INS_STATUS = 65283; @@ -597,6 +600,11 @@ sub _read { my $io__raw_payload = IO::KaitaiStruct::Stream->new($self->{_raw_payload}); $self->{payload} = Logging::MsgFwd->new($io__raw_payload, $self, $self->{_root}); } + elsif ($_on == 52993) { + $self->{_raw_payload} = $self->{_io}->read_bytes($self->length()); + my $io__raw_payload = IO::KaitaiStruct::Stream->new($self->{_raw_payload}); + $self->{payload} = Profiling::MsgProfilingSystemInfo->new($io__raw_payload, $self, $self->{_root}); + } elsif ($_on == 65286) { $self->{_raw_payload} = $self->{_io}->read_bytes($self->length()); my $io__raw_payload = IO::KaitaiStruct::Stream->new($self->{_raw_payload}); @@ -987,6 +995,11 @@ sub _read { my $io__raw_payload = IO::KaitaiStruct::Stream->new($self->{_raw_payload}); $self->{payload} = Piksi::MsgDeviceMonitor->new($io__raw_payload, $self, $self->{_root}); } + elsif ($_on == 52995) { + $self->{_raw_payload} = $self->{_io}->read_bytes($self->length()); + my $io__raw_payload = IO::KaitaiStruct::Stream->new($self->{_raw_payload}); + $self->{payload} = Profiling::MsgProfilingResourceCounter->new($io__raw_payload, $self, $self->{_root}); + } elsif ($_on == 521) { $self->{_raw_payload} = $self->{_io}->read_bytes($self->length()); my $io__raw_payload = IO::KaitaiStruct::Stream->new($self->{_raw_payload}); @@ -1167,6 +1180,11 @@ sub _read { my $io__raw_payload = IO::KaitaiStruct::Stream->new($self->{_raw_payload}); $self->{payload} = Navigation::MsgDopsDepA->new($io__raw_payload, $self, $self->{_root}); } + elsif ($_on == 52994) { + $self->{_raw_payload} = $self->{_io}->read_bytes($self->length()); + my $io__raw_payload = IO::KaitaiStruct::Stream->new($self->{_raw_payload}); + $self->{payload} = Profiling::MsgProfilingThreadInfo->new($io__raw_payload, $self, $self->{_root}); + } elsif ($_on == 553) { $self->{_raw_payload} = $self->{_io}->read_bytes($self->length()); my $io__raw_payload = IO::KaitaiStruct::Stream->new($self->{_raw_payload}); diff --git a/kaitai/perl/KaitaiSbp/Table.pm b/kaitai/perl/KaitaiSbp/Table.pm index 1d892ec392..55e3d4c837 100644 --- a/kaitai/perl/KaitaiSbp/Table.pm +++ b/kaitai/perl/KaitaiSbp/Table.pm @@ -231,6 +231,9 @@ our %TABLE = ( 191 => sub{Piksi::MsgFrontEndGain->new(@_)}, 52992 => sub{Profiling::MsgMeasurementPoint->new(@_)}, + 52993 => sub{Profiling::MsgProfilingSystemInfo->new(@_)}, + 52994 => sub{Profiling::MsgProfilingThreadInfo->new(@_)}, + 52995 => sub{Profiling::MsgProfilingResourceCounter->new(@_)}, 30583 => sub{Sbas::MsgSbasRaw->new(@_)}, diff --git a/kaitai/perl/KaitaiSbp/t/auto_check_sbp_profiling_MsgProfilingResourceCounter.t b/kaitai/perl/KaitaiSbp/t/auto_check_sbp_profiling_MsgProfilingResourceCounter.t new file mode 100644 index 0000000000..b562c186c2 --- /dev/null +++ b/kaitai/perl/KaitaiSbp/t/auto_check_sbp_profiling_MsgProfilingResourceCounter.t @@ -0,0 +1,60 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2015-2023 Swift Navigation Inc. +# Contact: https://support.swiftnav.com +# +# This source is subject to the license found in the file 'LICENSE' which must +# be be distributed together with this source. All other rights reserved. +# +# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +# EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +# +# Test cases automatically generated from spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingResourceCounter.yaml +# with generate.py. Do not modify by hand! + +use strict; + +BEGIN { + # add grandparent directory to include path + use Cwd qw(realpath); + use File::Basename; + unshift @INC, realpath(dirname($0))."/../../"; +} + +use KaitaiSbp::Sbp; +use KaitaiSbp::ParseUtils; +use IO::KaitaiStruct; +use Test::More; +use JSON::PP; +use MIME::Base64; +sub test_auto_check_sbp_profiling_msg_profiling_resource_counter_1() { + my $buf = decode_base64("VQPPABD4AQNGdXNpb24gZW5naW5lAAAAAAAAAAABAgIA+CYOAAAAAAAAAAAAAAAAAE5UUklQIGNsaWVudAAAAAAAAAAAAAEBAQHmSQEAAAAAAG8DAABATAAAU1NSMk9TUgAAAAAAAAAAAAAAAAAAAQEBAEgNQgAAAAAAAAAAAAAAAABQZXJpb2RpYwAAAAAAAAAAAAAAAAABAgEASMUDAAAAAAAAAAAAAAAAAElNVQAAAAAAAAAAAAAAAAAAAAAAAAEBAQGBRwAAAAAAAAAAAABfZgAAc2JwAAAAAAAAAAAAAAAAAAAAAAAABQICAvOpAAAAAAAAu5cDAPIBAAC1mQ=="); + my $stream = IO::KaitaiStruct::Stream->new($buf); + my $msg = ParseUtils::get_flattened_msg(Sbp::SbpMessage->new($stream)); + + is($msg->{'crc'}, 0x99b5, "crc"); + + is($msg->{'length'}, 248, "length"); + + is($msg->{'msg_type'}, 0xcf03, "msg_type"); + + is($msg->{'payload'}, "AQNGdXNpb24gZW5naW5lAAAAAAAAAAABAgIA+CYOAAAAAAAAAAAAAAAAAE5UUklQIGNsaWVudAAAAAAAAAAAAAEBAQHmSQEAAAAAAG8DAABATAAAU1NSMk9TUgAAAAAAAAAAAAAAAAAAAQEBAEgNQgAAAAAAAAAAAAAAAABQZXJpb2RpYwAAAAAAAAAAAAAAAAABAgEASMUDAAAAAAAAAAAAAAAAAElNVQAAAAAAAAAAAAAAAAAAAAAAAAEBAQGBRwAAAAAAAAAAAABfZgAAc2JwAAAAAAAAAAAAAAAAAAAAAAAABQICAvOpAAAAAAAAu5cDAPIBAAA=", "payload"); + + is($msg->{'preamble'}, 0x55, "preamble"); + + is($msg->{'sender'}, 0x1000, "sender"); + + my $json = JSON::PP->new->convert_blessed->canonical; + + is($json->encode($msg->buckets()), $json->encode($json->decode(q{[{"cv":2,"heap_bytes_alloc":927480,"heap_bytes_free":0,"io":0,"io_read":0,"io_write":0,"mutex":2,"name":"Fusion engine\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","thread":1},{"cv":1,"heap_bytes_alloc":84454,"heap_bytes_free":0,"io":1,"io_read":19520,"io_write":879,"mutex":1,"name":"NTRIP client\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","thread":1},{"cv":1,"heap_bytes_alloc":4328776,"heap_bytes_free":0,"io":0,"io_read":0,"io_write":0,"mutex":1,"name":"SSR2OSR\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","thread":1},{"cv":1,"heap_bytes_alloc":247112,"heap_bytes_free":0,"io":0,"io_read":0,"io_write":0,"mutex":2,"name":"Periodic\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","thread":1},{"cv":1,"heap_bytes_alloc":18305,"heap_bytes_free":0,"io":1,"io_read":26207,"io_write":0,"mutex":1,"name":"IMU\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","thread":1},{"cv":2,"heap_bytes_alloc":43507,"heap_bytes_free":0,"io":2,"io_read":498,"io_write":235451,"mutex":2,"name":"sbp\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","thread":5}]})), "buckets"); + + is($msg->seq_len(), 3, "seq_len"); + + is($msg->seq_no(), 1, "seq_no"); + + is($json->encode($msg), $json->encode($json->decode(q{{"buckets":[{"cv":2,"heap_bytes_alloc":927480,"heap_bytes_free":0,"io":0,"io_read":0,"io_write":0,"mutex":2,"name":"Fusion engine\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","thread":1},{"cv":1,"heap_bytes_alloc":84454,"heap_bytes_free":0,"io":1,"io_read":19520,"io_write":879,"mutex":1,"name":"NTRIP client\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","thread":1},{"cv":1,"heap_bytes_alloc":4328776,"heap_bytes_free":0,"io":0,"io_read":0,"io_write":0,"mutex":1,"name":"SSR2OSR\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","thread":1},{"cv":1,"heap_bytes_alloc":247112,"heap_bytes_free":0,"io":0,"io_read":0,"io_write":0,"mutex":2,"name":"Periodic\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","thread":1},{"cv":1,"heap_bytes_alloc":18305,"heap_bytes_free":0,"io":1,"io_read":26207,"io_write":0,"mutex":1,"name":"IMU\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","thread":1},{"cv":2,"heap_bytes_alloc":43507,"heap_bytes_free":0,"io":2,"io_read":498,"io_write":235451,"mutex":2,"name":"sbp\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000","thread":5}],"crc":39349,"length":248,"msg_type":52995,"payload":"AQNGdXNpb24gZW5naW5lAAAAAAAAAAABAgIA+CYOAAAAAAAAAAAAAAAAAE5UUklQIGNsaWVudAAAAAAAAAAAAAEBAQHmSQEAAAAAAG8DAABATAAAU1NSMk9TUgAAAAAAAAAAAAAAAAAAAQEBAEgNQgAAAAAAAAAAAAAAAABQZXJpb2RpYwAAAAAAAAAAAAAAAAABAgEASMUDAAAAAAAAAAAAAAAAAElNVQAAAAAAAAAAAAAAAAAAAAAAAAEBAQGBRwAAAAAAAAAAAABfZgAAc2JwAAAAAAAAAAAAAAAAAAAAAAAABQICAvOpAAAAAAAAu5cDAPIBAAA=","preamble":85,"sender":4096,"seq_len":3,"seq_no":1}})), "raw_json"); +} +test_auto_check_sbp_profiling_msg_profiling_resource_counter_1(); + +done_testing(); \ No newline at end of file diff --git a/kaitai/perl/KaitaiSbp/t/auto_check_sbp_profiling_MsgProfilingSystemInfo.t b/kaitai/perl/KaitaiSbp/t/auto_check_sbp_profiling_MsgProfilingSystemInfo.t new file mode 100644 index 0000000000..14c9614792 --- /dev/null +++ b/kaitai/perl/KaitaiSbp/t/auto_check_sbp_profiling_MsgProfilingSystemInfo.t @@ -0,0 +1,62 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2015-2023 Swift Navigation Inc. +# Contact: https://support.swiftnav.com +# +# This source is subject to the license found in the file 'LICENSE' which must +# be be distributed together with this source. All other rights reserved. +# +# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +# EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +# +# Test cases automatically generated from spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingSystemInfo.yaml +# with generate.py. Do not modify by hand! + +use strict; + +BEGIN { + # add grandparent directory to include path + use Cwd qw(realpath); + use File::Basename; + unshift @INC, realpath(dirname($0))."/../../"; +} + +use KaitaiSbp::Sbp; +use KaitaiSbp::ParseUtils; +use IO::KaitaiStruct; +use Test::More; +use JSON::PP; +use MIME::Base64; +sub test_auto_check_sbp_profiling_msg_profiling_system_info_1() { + my $buf = decode_base64("VQHPABAVYig0AAAAAAByDJ0AAAAAABtIw+IA/EE="); + my $stream = IO::KaitaiStruct::Stream->new($buf); + my $msg = ParseUtils::get_flattened_msg(Sbp::SbpMessage->new($stream)); + + is($msg->{'crc'}, 0x41fc, "crc"); + + is($msg->{'length'}, 21, "length"); + + is($msg->{'msg_type'}, 0xcf01, "msg_type"); + + is($msg->{'payload'}, "Yig0AAAAAAByDJ0AAAAAABtIw+IA", "payload"); + + is($msg->{'preamble'}, 0x55, "preamble"); + + is($msg->{'sender'}, 0x1000, "sender"); + + my $json = JSON::PP->new->convert_blessed->canonical; + + is($msg->age(), 10292338, "age"); + + is($msg->heap_usage(), 14861128, "heap_usage"); + + is($msg->n_threads(), 27, "n_threads"); + + is($msg->total_cpu_time(), 3418210, "total_cpu_time"); + + is($json->encode($msg), $json->encode($json->decode(q{{"age":10292338,"crc":16892,"heap_usage":14861128,"length":21,"msg_type":52993,"n_threads":27,"payload":"Yig0AAAAAAByDJ0AAAAAABtIw+IA","preamble":85,"sender":4096,"total_cpu_time":3418210}})), "raw_json"); +} +test_auto_check_sbp_profiling_msg_profiling_system_info_1(); + +done_testing(); \ No newline at end of file diff --git a/kaitai/perl/KaitaiSbp/t/auto_check_sbp_profiling_MsgProfilingThreadInfo.t b/kaitai/perl/KaitaiSbp/t/auto_check_sbp_profiling_MsgProfilingThreadInfo.t new file mode 100644 index 0000000000..f0e3f24d0f --- /dev/null +++ b/kaitai/perl/KaitaiSbp/t/auto_check_sbp_profiling_MsgProfilingThreadInfo.t @@ -0,0 +1,66 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2015-2023 Swift Navigation Inc. +# Contact: https://support.swiftnav.com +# +# This source is subject to the license found in the file 'LICENSE' which must +# be be distributed together with this source. All other rights reserved. +# +# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +# EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +# +# Test cases automatically generated from spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingThreadInfo.yaml +# with generate.py. Do not modify by hand! + +use strict; + +BEGIN { + # add grandparent directory to include path + use Cwd qw(realpath); + use File::Basename; + unshift @INC, realpath(dirname($0))."/../../"; +} + +use KaitaiSbp::Sbp; +use KaitaiSbp::ParseUtils; +use IO::KaitaiStruct; +use Test::More; +use JSON::PP; +use MIME::Base64; +sub test_auto_check_sbp_profiling_msg_profiling_thread_info_1() { + my $buf = decode_base64("VQLPABAnd1sKAAAAAABuBZsAAAAAAAEAAIAA0DUEAEZ1c2lvbiBlbmdpbmUA8qo="); + my $stream = IO::KaitaiStruct::Stream->new($buf); + my $msg = ParseUtils::get_flattened_msg(Sbp::SbpMessage->new($stream)); + + is($msg->{'crc'}, 0xaaf2, "crc"); + + is($msg->{'length'}, 39, "length"); + + is($msg->{'msg_type'}, 0xcf02, "msg_type"); + + is($msg->{'payload'}, "d1sKAAAAAABuBZsAAAAAAAEAAIAA0DUEAEZ1c2lvbiBlbmdpbmUA", "payload"); + + is($msg->{'preamble'}, 0x55, "preamble"); + + is($msg->{'sender'}, 0x1000, "sender"); + + my $json = JSON::PP->new->convert_blessed->canonical; + + is($msg->age(), 10159470, "age"); + + is($msg->name(), "Fusion engine\x00", "name"); + + is($msg->stack_size(), 8388608, "stack_size"); + + is($msg->stack_usage(), 275920, "stack_usage"); + + is($msg->state(), 1, "state"); + + is($msg->total_cpu_time(), 678775, "total_cpu_time"); + + is($json->encode($msg), $json->encode($json->decode(q{{"age":10159470,"crc":43762,"length":39,"msg_type":52994,"name":"Fusion engine\u0000","payload":"d1sKAAAAAABuBZsAAAAAAAEAAIAA0DUEAEZ1c2lvbiBlbmdpbmUA","preamble":85,"sender":4096,"stack_size":8388608,"stack_usage":275920,"state":1,"total_cpu_time":678775}})), "raw_json"); +} +test_auto_check_sbp_profiling_msg_profiling_thread_info_1(); + +done_testing(); \ No newline at end of file diff --git a/kaitai/python/kaitai_sbp/profiling.py b/kaitai/python/kaitai_sbp/profiling.py index a8bef316d4..91f3098e12 100644 --- a/kaitai/python/kaitai_sbp/profiling.py +++ b/kaitai/python/kaitai_sbp/profiling.py @@ -17,6 +17,48 @@ def __init__(self, _io, _parent=None, _root=None): def _read(self): pass + class ResourceBucket(KaitaiStruct): + """Information about allocation of various resources grouped by buckets. + Refer to product documentation to understand the meaning and values in + this message. + """ + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.name = (self._io.read_bytes(21)).decode(u"ascii") + self.thread = self._io.read_u1() + self.mutex = self._io.read_u1() + self.cv = self._io.read_u1() + self.io = self._io.read_u1() + self.heap_bytes_alloc = self._io.read_u4le() + self.heap_bytes_free = self._io.read_u4le() + self.io_write = self._io.read_u4le() + self.io_read = self._io.read_u4le() + + + class MsgProfilingSystemInfo(KaitaiStruct): + """Contains basic information about system resource usage. System is + defined in terms of the source of this message and may vary from sender + to sender. Refer to product documentation to understand the exact scope + and meaning of this message. + """ + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.total_cpu_time = self._io.read_u8le() + self.age = self._io.read_u8le() + self.n_threads = self._io.read_u1() + self.heap_usage = self._io.read_u4le() + + class MsgMeasurementPoint(KaitaiStruct): """Tracks execution time of certain code paths in specially built products. This message should only be expected and processed on the direction of @@ -40,4 +82,45 @@ def _read(self): self.func = (self._io.read_bytes_full()).decode(u"ascii") + class MsgProfilingResourceCounter(KaitaiStruct): + """Information about resource buckets. Refer to product documentation to + understand the meaning and values in this message. + """ + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.seq_no = self._io.read_u1() + self.seq_len = self._io.read_u1() + self.buckets = [] + i = 0 + while not self._io.is_eof(): + self.buckets.append(Profiling.ResourceBucket(self._io, self, self._root)) + i += 1 + + + + class MsgProfilingThreadInfo(KaitaiStruct): + """Contains profiling information related to a single thread being tracked + by the producing system. Refer to product documentation to understand + the exact scope and meaning of this message. + """ + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.total_cpu_time = self._io.read_u8le() + self.age = self._io.read_u8le() + self.state = self._io.read_u1() + self.stack_size = self._io.read_u4le() + self.stack_usage = self._io.read_u4le() + self.name = (self._io.read_bytes_full()).decode(u"ascii") + + diff --git a/kaitai/python/kaitai_sbp/sbp.py b/kaitai/python/kaitai_sbp/sbp.py index 589c93831b..a1ad08f349 100644 --- a/kaitai/python/kaitai_sbp/sbp.py +++ b/kaitai/python/kaitai_sbp/sbp.py @@ -257,6 +257,9 @@ class MsgIds(Enum): msg_linux_mem_state = 32521 msg_linux_sys_state = 32522 msg_measurement_point = 52992 + msg_profiling_system_info = 52993 + msg_profiling_thread_info = 52994 + msg_profiling_resource_counter = 52995 msg_startup = 65280 msg_dgnss_status = 65282 msg_ins_status = 65283 @@ -505,6 +508,10 @@ def _read(self): self._raw_payload = self._io.read_bytes(self.length) _io__raw_payload = KaitaiStream(BytesIO(self._raw_payload)) self.payload = Logging.MsgFwd(_io__raw_payload, self, self._root) + elif _on == 52993: + self._raw_payload = self._io.read_bytes(self.length) + _io__raw_payload = KaitaiStream(BytesIO(self._raw_payload)) + self.payload = Profiling.MsgProfilingSystemInfo(_io__raw_payload, self, self._root) elif _on == 65286: self._raw_payload = self._io.read_bytes(self.length) _io__raw_payload = KaitaiStream(BytesIO(self._raw_payload)) @@ -817,6 +824,10 @@ def _read(self): self._raw_payload = self._io.read_bytes(self.length) _io__raw_payload = KaitaiStream(BytesIO(self._raw_payload)) self.payload = Piksi.MsgDeviceMonitor(_io__raw_payload, self, self._root) + elif _on == 52995: + self._raw_payload = self._io.read_bytes(self.length) + _io__raw_payload = KaitaiStream(BytesIO(self._raw_payload)) + self.payload = Profiling.MsgProfilingResourceCounter(_io__raw_payload, self, self._root) elif _on == 521: self._raw_payload = self._io.read_bytes(self.length) _io__raw_payload = KaitaiStream(BytesIO(self._raw_payload)) @@ -961,6 +972,10 @@ def _read(self): self._raw_payload = self._io.read_bytes(self.length) _io__raw_payload = KaitaiStream(BytesIO(self._raw_payload)) self.payload = Navigation.MsgDopsDepA(_io__raw_payload, self, self._root) + elif _on == 52994: + self._raw_payload = self._io.read_bytes(self.length) + _io__raw_payload = KaitaiStream(BytesIO(self._raw_payload)) + self.payload = Profiling.MsgProfilingThreadInfo(_io__raw_payload, self, self._root) elif _on == 553: self._raw_payload = self._io.read_bytes(self.length) _io__raw_payload = KaitaiStream(BytesIO(self._raw_payload)) diff --git a/kaitai/python/kaitai_sbp/table.py b/kaitai/python/kaitai_sbp/table.py index f1a9a37c5e..4f9bbf5583 100644 --- a/kaitai/python/kaitai_sbp/table.py +++ b/kaitai/python/kaitai_sbp/table.py @@ -225,6 +225,9 @@ 191: Piksi.MsgFrontEndGain, 52992: Profiling.MsgMeasurementPoint, + 52993: Profiling.MsgProfilingSystemInfo, + 52994: Profiling.MsgProfilingThreadInfo, + 52995: Profiling.MsgProfilingResourceCounter, 30583: Sbas.MsgSbasRaw, diff --git a/kaitai/python/kaitai_sbp/tests/test_auto_check_sbp_profiling_MsgProfilingResourceCounter.py b/kaitai/python/kaitai_sbp/tests/test_auto_check_sbp_profiling_MsgProfilingResourceCounter.py new file mode 100644 index 0000000000..d92997e711 --- /dev/null +++ b/kaitai/python/kaitai_sbp/tests/test_auto_check_sbp_profiling_MsgProfilingResourceCounter.py @@ -0,0 +1,45 @@ +# Copyright (C) 2015-2023 Swift Navigation Inc. +# Contact: https://support.swiftnav.com +# +# This source is subject to the license found in the file 'LICENSE' which must +# be be distributed together with this source. All other rights reserved. +# +# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +# EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +# +# Test cases automatically generated from spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingResourceCounter.yaml +# with generate.py. Do not modify by hand! + +import kaitai_sbp.sbp as sbp +from kaitai_sbp.parse_utils import get_flattened_msg +from kaitai_sbp.tests.utils import dictify +from kaitaistruct import KaitaiStream +import io +import base64 + +def test_auto_check_sbp_profiling_msg_profiling_resource_counter_1(): + buf = base64.standard_b64decode("VQPPABD4AQNGdXNpb24gZW5naW5lAAAAAAAAAAABAgIA+CYOAAAAAAAAAAAAAAAAAE5UUklQIGNsaWVudAAAAAAAAAAAAAEBAQHmSQEAAAAAAG8DAABATAAAU1NSMk9TUgAAAAAAAAAAAAAAAAAAAQEBAEgNQgAAAAAAAAAAAAAAAABQZXJpb2RpYwAAAAAAAAAAAAAAAAABAgEASMUDAAAAAAAAAAAAAAAAAElNVQAAAAAAAAAAAAAAAAAAAAAAAAEBAQGBRwAAAAAAAAAAAABfZgAAc2JwAAAAAAAAAAAAAAAAAAAAAAAABQICAvOpAAAAAAAAu5cDAPIBAAC1mQ==") + + stream = KaitaiStream(io.BytesIO(buf)) + msg = get_flattened_msg(sbp.Sbp.SbpMessage(stream)) + + assert msg.crc == 0x99b5 + + assert msg.length == 248 + + assert msg.msg_type == 0xcf03 + + assert msg.payload == "AQNGdXNpb24gZW5naW5lAAAAAAAAAAABAgIA+CYOAAAAAAAAAAAAAAAAAE5UUklQIGNsaWVudAAAAAAAAAAAAAEBAQHmSQEAAAAAAG8DAABATAAAU1NSMk9TUgAAAAAAAAAAAAAAAAAAAQEBAEgNQgAAAAAAAAAAAAAAAABQZXJpb2RpYwAAAAAAAAAAAAAAAAABAgEASMUDAAAAAAAAAAAAAAAAAElNVQAAAAAAAAAAAAAAAAAAAAAAAAEBAQGBRwAAAAAAAAAAAABfZgAAc2JwAAAAAAAAAAAAAAAAAAAAAAAABQICAvOpAAAAAAAAu5cDAPIBAAA=" + + assert msg.preamble == 0x55 + + assert msg.sender == 0x1000 + + assert dictify(msg.buckets) == [{'name': 'Fusion engine\x00\x00\x00\x00\x00\x00\x00\x00', 'thread': 1, 'mutex': 2, 'cv': 2, 'io': 0, 'heap_bytes_alloc': 927480, 'heap_bytes_free': 0, 'io_write': 0, 'io_read': 0}, {'name': 'NTRIP client\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'thread': 1, 'mutex': 1, 'cv': 1, 'io': 1, 'heap_bytes_alloc': 84454, 'heap_bytes_free': 0, 'io_write': 879, 'io_read': 19520}, {'name': 'SSR2OSR\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'thread': 1, 'mutex': 1, 'cv': 1, 'io': 0, 'heap_bytes_alloc': 4328776, 'heap_bytes_free': 0, 'io_write': 0, 'io_read': 0}, {'name': 'Periodic\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'thread': 1, 'mutex': 2, 'cv': 1, 'io': 0, 'heap_bytes_alloc': 247112, 'heap_bytes_free': 0, 'io_write': 0, 'io_read': 0}, {'name': 'IMU\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'thread': 1, 'mutex': 1, 'cv': 1, 'io': 1, 'heap_bytes_alloc': 18305, 'heap_bytes_free': 0, 'io_write': 0, 'io_read': 26207}, {'name': 'sbp\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'thread': 5, 'mutex': 2, 'cv': 2, 'io': 2, 'heap_bytes_alloc': 43507, 'heap_bytes_free': 0, 'io_write': 235451, 'io_read': 498}] + + assert dictify(msg.seq_len) == 3 + + assert dictify(msg.seq_no) == 1 + + assert dictify(msg) == {'crc': 39349, 'preamble': 85, 'sender': 4096, 'length': 248, 'msg_type': 52995, 'seq_no': 1, 'seq_len': 3, 'buckets': [{'name': 'Fusion engine\x00\x00\x00\x00\x00\x00\x00\x00', 'thread': 1, 'mutex': 2, 'cv': 2, 'io': 0, 'heap_bytes_alloc': 927480, 'heap_bytes_free': 0, 'io_write': 0, 'io_read': 0}, {'name': 'NTRIP client\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'thread': 1, 'mutex': 1, 'cv': 1, 'io': 1, 'heap_bytes_alloc': 84454, 'heap_bytes_free': 0, 'io_write': 879, 'io_read': 19520}, {'name': 'SSR2OSR\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'thread': 1, 'mutex': 1, 'cv': 1, 'io': 0, 'heap_bytes_alloc': 4328776, 'heap_bytes_free': 0, 'io_write': 0, 'io_read': 0}, {'name': 'Periodic\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'thread': 1, 'mutex': 2, 'cv': 1, 'io': 0, 'heap_bytes_alloc': 247112, 'heap_bytes_free': 0, 'io_write': 0, 'io_read': 0}, {'name': 'IMU\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'thread': 1, 'mutex': 1, 'cv': 1, 'io': 1, 'heap_bytes_alloc': 18305, 'heap_bytes_free': 0, 'io_write': 0, 'io_read': 26207}, {'name': 'sbp\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'thread': 5, 'mutex': 2, 'cv': 2, 'io': 2, 'heap_bytes_alloc': 43507, 'heap_bytes_free': 0, 'io_write': 235451, 'io_read': 498}], 'payload': 'AQNGdXNpb24gZW5naW5lAAAAAAAAAAABAgIA+CYOAAAAAAAAAAAAAAAAAE5UUklQIGNsaWVudAAAAAAAAAAAAAEBAQHmSQEAAAAAAG8DAABATAAAU1NSMk9TUgAAAAAAAAAAAAAAAAAAAQEBAEgNQgAAAAAAAAAAAAAAAABQZXJpb2RpYwAAAAAAAAAAAAAAAAABAgEASMUDAAAAAAAAAAAAAAAAAElNVQAAAAAAAAAAAAAAAAAAAAAAAAEBAQGBRwAAAAAAAAAAAABfZgAAc2JwAAAAAAAAAAAAAAAAAAAAAAAABQICAvOpAAAAAAAAu5cDAPIBAAA='} \ No newline at end of file diff --git a/kaitai/python/kaitai_sbp/tests/test_auto_check_sbp_profiling_MsgProfilingSystemInfo.py b/kaitai/python/kaitai_sbp/tests/test_auto_check_sbp_profiling_MsgProfilingSystemInfo.py new file mode 100644 index 0000000000..069821efa6 --- /dev/null +++ b/kaitai/python/kaitai_sbp/tests/test_auto_check_sbp_profiling_MsgProfilingSystemInfo.py @@ -0,0 +1,47 @@ +# Copyright (C) 2015-2023 Swift Navigation Inc. +# Contact: https://support.swiftnav.com +# +# This source is subject to the license found in the file 'LICENSE' which must +# be be distributed together with this source. All other rights reserved. +# +# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +# EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +# +# Test cases automatically generated from spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingSystemInfo.yaml +# with generate.py. Do not modify by hand! + +import kaitai_sbp.sbp as sbp +from kaitai_sbp.parse_utils import get_flattened_msg +from kaitai_sbp.tests.utils import dictify +from kaitaistruct import KaitaiStream +import io +import base64 + +def test_auto_check_sbp_profiling_msg_profiling_system_info_1(): + buf = base64.standard_b64decode("VQHPABAVYig0AAAAAAByDJ0AAAAAABtIw+IA/EE=") + + stream = KaitaiStream(io.BytesIO(buf)) + msg = get_flattened_msg(sbp.Sbp.SbpMessage(stream)) + + assert msg.crc == 0x41fc + + assert msg.length == 21 + + assert msg.msg_type == 0xcf01 + + assert msg.payload == "Yig0AAAAAAByDJ0AAAAAABtIw+IA" + + assert msg.preamble == 0x55 + + assert msg.sender == 0x1000 + + assert dictify(msg.age) == 10292338 + + assert dictify(msg.heap_usage) == 14861128 + + assert dictify(msg.n_threads) == 27 + + assert dictify(msg.total_cpu_time) == 3418210 + + assert dictify(msg) == {'crc': 16892, 'preamble': 85, 'sender': 4096, 'length': 21, 'msg_type': 52993, 'total_cpu_time': 3418210, 'age': 10292338, 'n_threads': 27, 'heap_usage': 14861128, 'payload': 'Yig0AAAAAAByDJ0AAAAAABtIw+IA'} \ No newline at end of file diff --git a/kaitai/python/kaitai_sbp/tests/test_auto_check_sbp_profiling_MsgProfilingThreadInfo.py b/kaitai/python/kaitai_sbp/tests/test_auto_check_sbp_profiling_MsgProfilingThreadInfo.py new file mode 100644 index 0000000000..3ec28ac800 --- /dev/null +++ b/kaitai/python/kaitai_sbp/tests/test_auto_check_sbp_profiling_MsgProfilingThreadInfo.py @@ -0,0 +1,51 @@ +# Copyright (C) 2015-2023 Swift Navigation Inc. +# Contact: https://support.swiftnav.com +# +# This source is subject to the license found in the file 'LICENSE' which must +# be be distributed together with this source. All other rights reserved. +# +# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +# EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +# +# Test cases automatically generated from spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingThreadInfo.yaml +# with generate.py. Do not modify by hand! + +import kaitai_sbp.sbp as sbp +from kaitai_sbp.parse_utils import get_flattened_msg +from kaitai_sbp.tests.utils import dictify +from kaitaistruct import KaitaiStream +import io +import base64 + +def test_auto_check_sbp_profiling_msg_profiling_thread_info_1(): + buf = base64.standard_b64decode("VQLPABAnd1sKAAAAAABuBZsAAAAAAAEAAIAA0DUEAEZ1c2lvbiBlbmdpbmUA8qo=") + + stream = KaitaiStream(io.BytesIO(buf)) + msg = get_flattened_msg(sbp.Sbp.SbpMessage(stream)) + + assert msg.crc == 0xaaf2 + + assert msg.length == 39 + + assert msg.msg_type == 0xcf02 + + assert msg.payload == "d1sKAAAAAABuBZsAAAAAAAEAAIAA0DUEAEZ1c2lvbiBlbmdpbmUA" + + assert msg.preamble == 0x55 + + assert msg.sender == 0x1000 + + assert dictify(msg.age) == 10159470 + + assert dictify(msg.name) == "Fusion engine\x00" + + assert dictify(msg.stack_size) == 8388608 + + assert dictify(msg.stack_usage) == 275920 + + assert dictify(msg.state) == 1 + + assert dictify(msg.total_cpu_time) == 678775 + + assert dictify(msg) == {'crc': 43762, 'preamble': 85, 'sender': 4096, 'length': 39, 'msg_type': 52994, 'total_cpu_time': 678775, 'age': 10159470, 'state': 1, 'stack_size': 8388608, 'stack_usage': 275920, 'name': 'Fusion engine\x00', 'payload': 'd1sKAAAAAABuBZsAAAAAAAEAAIAA0DUEAEZ1c2lvbiBlbmdpbmUA'} \ No newline at end of file diff --git a/proto/profiling.proto b/proto/profiling.proto index fba91fde3d..26a28950a1 100644 --- a/proto/profiling.proto +++ b/proto/profiling.proto @@ -36,4 +36,62 @@ message MsgMeasurementPoint { uint64 slice_time = 7; uint32 line = 8; string func = 9; +} + +/** System Profiling Information + * + * Contains basic information about system resource usage. System is defined + * in terms of the source of this message and may vary from sender to sender. + * Refer to product documentation to understand the exact scope and meaning of + * this message. + */ +message MsgProfilingSystemInfo { + uint64 total_cpu_time = 1; + uint64 age = 2; + uint32 n_threads = 3; + uint32 heap_usage = 4; +} + +/** Thread Profiling Information + * + * Contains profiling information related to a single thread being tracked by + * the producing system. Refer to product documentation to understand the + * exact scope and meaning of this message. + */ +message MsgProfilingThreadInfo { + uint64 total_cpu_time = 1; + uint64 age = 2; + uint32 state = 3; + uint32 stack_size = 4; + uint32 stack_usage = 5; + string name = 6; +} + +/** A bucket containing various resources + * + * Information about allocation of various resources grouped by buckets. Refer + * to product documentation to understand the meaning and values in this + * message. + */ +message ResourceBucket { + string name = 1; + uint32 thread = 2; + uint32 mutex = 3; + uint32 cv = 4; + uint32 io = 5; + uint32 heap_bytes_alloc = 6; + uint32 heap_bytes_free = 7; + uint32 io_write = 8; + uint32 io_read = 9; +} + +/** Information about resource buckets + * + * Information about resource buckets. Refer to product documentation to + * understand the meaning and values in this message. + */ +message MsgProfilingResourceCounter { + uint32 seq_no = 1; + uint32 seq_len = 2; + repeated ResourceBucket buckets = 3; } \ No newline at end of file diff --git a/python/sbp/profiling.py b/python/sbp/profiling.py index e097f99471..6d80016057 100644 --- a/python/sbp/profiling.py +++ b/python/sbp/profiling.py @@ -25,6 +25,79 @@ # Please do not hand edit! +class ResourceBucket(object): + """ResourceBucket. + + Information about allocation of various resources grouped by buckets. Refer + to product documentation to understand the meaning and values in this + message. + + Parameters + ---------- + name : string + Bucket name + thread : int + Number of threads + mutex : int + Number of mutexes + cv : int + Number of condition variables + io : int + Number of IO handles + heap_bytes_alloc : int + Number of bytes allocated on the heap + heap_bytes_free : int + Number of bytes freed on the heap + io_write : int + Number of bytes written to IO handles + io_read : int + Number of bytes read from IO handles + + """ + _parser = construct.Struct( + 'name'/ construct.Bytes(21), + 'thread' / construct.Int8ul, + 'mutex' / construct.Int8ul, + 'cv' / construct.Int8ul, + 'io' / construct.Int8ul, + 'heap_bytes_alloc' / construct.Int32ul, + 'heap_bytes_free' / construct.Int32ul, + 'io_write' / construct.Int32ul, + 'io_read' / construct.Int32ul,) + __slots__ = [ + 'name', + 'thread', + 'mutex', + 'cv', + 'io', + 'heap_bytes_alloc', + 'heap_bytes_free', + 'io_write', + 'io_read', + ] + + def __init__(self, payload=None, **kwargs): + if payload: + self.from_binary(payload) + else: + self.name = kwargs.pop('name') + self.thread = kwargs.pop('thread') + self.mutex = kwargs.pop('mutex') + self.cv = kwargs.pop('cv') + self.io = kwargs.pop('io') + self.heap_bytes_alloc = kwargs.pop('heap_bytes_alloc') + self.heap_bytes_free = kwargs.pop('heap_bytes_free') + self.io_write = kwargs.pop('io_write') + self.io_read = kwargs.pop('io_read') + + def __repr__(self): + return fmt_repr(self) + + def from_binary(self, d): + p = ResourceBucket._parser.parse(d) + for n in self.__class__.__slots__: + setattr(self, n, getattr(p, n)) + SBP_MSG_MEASUREMENT_POINT = 0xCF00 class MsgMeasurementPoint(SBP): """SBP class for message MSG_MEASUREMENT_POINT (0xCF00). @@ -162,7 +235,351 @@ def to_json_dict(self): d.update(j) return d +SBP_MSG_PROFILING_SYSTEM_INFO = 0xCF01 +class MsgProfilingSystemInfo(SBP): + """SBP class for message MSG_PROFILING_SYSTEM_INFO (0xCF01). + + You can have MSG_PROFILING_SYSTEM_INFO inherit its fields directly + from an inherited SBP object, or construct it inline using a dict + of its fields. + + + Contains basic information about system resource usage. System is defined in + terms of the source of this message and may vary from sender to sender. + Refer to product documentation to understand the exact scope and meaning of + this message. + + Parameters + ---------- + sbp : SBP + SBP parent object to inherit from. + total_cpu_time : int + Total cpu time in microseconds consumed by this system + age : int + Age of the producing system in microseconds + n_threads : int + Number of threads being tracked by this system + heap_usage : int + Number of bytes allocated on the heap + sender : int + Optional sender ID, defaults to SENDER_ID (see sbp/msg.py). + + """ + _parser = construct.Struct( + 'total_cpu_time' / construct.Int64ul, + 'age' / construct.Int64ul, + 'n_threads' / construct.Int8ul, + 'heap_usage' / construct.Int32ul,) + __slots__ = [ + 'total_cpu_time', + 'age', + 'n_threads', + 'heap_usage', + ] + + def __init__(self, sbp=None, **kwargs): + if sbp: + super( MsgProfilingSystemInfo, + self).__init__(sbp.msg_type, sbp.sender, sbp.length, + sbp.payload, sbp.crc) + self.from_binary(sbp.payload) + else: + super( MsgProfilingSystemInfo, self).__init__() + self.msg_type = SBP_MSG_PROFILING_SYSTEM_INFO + self.sender = kwargs.pop('sender', SENDER_ID) + self.total_cpu_time = kwargs.pop('total_cpu_time') + self.age = kwargs.pop('age') + self.n_threads = kwargs.pop('n_threads') + self.heap_usage = kwargs.pop('heap_usage') + + def __repr__(self): + return fmt_repr(self) + + @staticmethod + def from_json(s): + """Given a JSON-encoded string s, build a message object. + + """ + d = json.loads(s) + return MsgProfilingSystemInfo.from_json_dict(d) + + @staticmethod + def from_json_dict(d): + sbp = SBP.from_json_dict(d) + return MsgProfilingSystemInfo(sbp, **d) + + + def from_binary(self, d): + """Given a binary payload d, update the appropriate payload fields of + the message. + + """ + p = MsgProfilingSystemInfo._parser.parse(d) + for n in self.__class__.__slots__: + setattr(self, n, getattr(p, n)) + + def to_binary(self): + """Produce a framed/packed SBP message. + + """ + c = containerize(exclude_fields(self)) + self.payload = MsgProfilingSystemInfo._parser.build(c) + return self.pack() + + def friendly_name(self): + """Produces friendly human-readable name for this message + + """ + return "PROFILING SYSTEM INFO" + + def into_buffer(self, buf, offset): + """Produce a framed/packed SBP message into the provided buffer and offset. + + """ + self.payload = containerize(exclude_fields(self)) + self.parser = MsgProfilingSystemInfo._parser + self.stream_payload.reset(buf, offset) + return self.pack_into(buf, offset, self._build_payload) + + def to_json_dict(self): + self.to_binary() + d = super( MsgProfilingSystemInfo, self).to_json_dict() + j = walk_json_dict(exclude_fields(self)) + d.update(j) + return d + +SBP_MSG_PROFILING_THREAD_INFO = 0xCF02 +class MsgProfilingThreadInfo(SBP): + """SBP class for message MSG_PROFILING_THREAD_INFO (0xCF02). + + You can have MSG_PROFILING_THREAD_INFO inherit its fields directly + from an inherited SBP object, or construct it inline using a dict + of its fields. + + + Contains profiling information related to a single thread being tracked by + the producing system. Refer to product documentation to understand the exact + scope and meaning of this message. + + Parameters + ---------- + sbp : SBP + SBP parent object to inherit from. + total_cpu_time : int + Total cpu time in microseconds consumed by this thread + age : int + Age of the thread in microseconds + state : int + Thread state + stack_size : int + Stack size in bytes + stack_usage : int + Stack highwater usage in bytes + name : string + Thread name + sender : int + Optional sender ID, defaults to SENDER_ID (see sbp/msg.py). + + """ + _parser = construct.Struct( + 'total_cpu_time' / construct.Int64ul, + 'age' / construct.Int64ul, + 'state' / construct.Int8ul, + 'stack_size' / construct.Int32ul, + 'stack_usage' / construct.Int32ul, + 'name' / construct.GreedyBytes,) + __slots__ = [ + 'total_cpu_time', + 'age', + 'state', + 'stack_size', + 'stack_usage', + 'name', + ] + + def __init__(self, sbp=None, **kwargs): + if sbp: + super( MsgProfilingThreadInfo, + self).__init__(sbp.msg_type, sbp.sender, sbp.length, + sbp.payload, sbp.crc) + self.from_binary(sbp.payload) + else: + super( MsgProfilingThreadInfo, self).__init__() + self.msg_type = SBP_MSG_PROFILING_THREAD_INFO + self.sender = kwargs.pop('sender', SENDER_ID) + self.total_cpu_time = kwargs.pop('total_cpu_time') + self.age = kwargs.pop('age') + self.state = kwargs.pop('state') + self.stack_size = kwargs.pop('stack_size') + self.stack_usage = kwargs.pop('stack_usage') + self.name = kwargs.pop('name') + + def __repr__(self): + return fmt_repr(self) + + @staticmethod + def from_json(s): + """Given a JSON-encoded string s, build a message object. + + """ + d = json.loads(s) + return MsgProfilingThreadInfo.from_json_dict(d) + + @staticmethod + def from_json_dict(d): + sbp = SBP.from_json_dict(d) + return MsgProfilingThreadInfo(sbp, **d) + + + def from_binary(self, d): + """Given a binary payload d, update the appropriate payload fields of + the message. + + """ + p = MsgProfilingThreadInfo._parser.parse(d) + for n in self.__class__.__slots__: + setattr(self, n, getattr(p, n)) + + def to_binary(self): + """Produce a framed/packed SBP message. + + """ + c = containerize(exclude_fields(self)) + self.payload = MsgProfilingThreadInfo._parser.build(c) + return self.pack() + + def friendly_name(self): + """Produces friendly human-readable name for this message + + """ + return "PROFILING THREAD INFO" + + def into_buffer(self, buf, offset): + """Produce a framed/packed SBP message into the provided buffer and offset. + + """ + self.payload = containerize(exclude_fields(self)) + self.parser = MsgProfilingThreadInfo._parser + self.stream_payload.reset(buf, offset) + return self.pack_into(buf, offset, self._build_payload) + + def to_json_dict(self): + self.to_binary() + d = super( MsgProfilingThreadInfo, self).to_json_dict() + j = walk_json_dict(exclude_fields(self)) + d.update(j) + return d + +SBP_MSG_PROFILING_RESOURCE_COUNTER = 0xCF03 +class MsgProfilingResourceCounter(SBP): + """SBP class for message MSG_PROFILING_RESOURCE_COUNTER (0xCF03). + + You can have MSG_PROFILING_RESOURCE_COUNTER inherit its fields directly + from an inherited SBP object, or construct it inline using a dict + of its fields. + + + Information about resource buckets. Refer to product documentation to + understand the meaning and values in this message. + + Parameters + ---------- + sbp : SBP + SBP parent object to inherit from. + seq_no : int + Message number in complete sequence + seq_len : int + Length of message sequence + buckets : array + List of resource buckets + sender : int + Optional sender ID, defaults to SENDER_ID (see sbp/msg.py). + + """ + _parser = construct.Struct( + 'seq_no' / construct.Int8ul, + 'seq_len' / construct.Int8ul, + 'buckets' / construct.GreedyRange(ResourceBucket._parser),) + __slots__ = [ + 'seq_no', + 'seq_len', + 'buckets', + ] + + def __init__(self, sbp=None, **kwargs): + if sbp: + super( MsgProfilingResourceCounter, + self).__init__(sbp.msg_type, sbp.sender, sbp.length, + sbp.payload, sbp.crc) + self.from_binary(sbp.payload) + else: + super( MsgProfilingResourceCounter, self).__init__() + self.msg_type = SBP_MSG_PROFILING_RESOURCE_COUNTER + self.sender = kwargs.pop('sender', SENDER_ID) + self.seq_no = kwargs.pop('seq_no') + self.seq_len = kwargs.pop('seq_len') + self.buckets = kwargs.pop('buckets') + + def __repr__(self): + return fmt_repr(self) + + @staticmethod + def from_json(s): + """Given a JSON-encoded string s, build a message object. + + """ + d = json.loads(s) + return MsgProfilingResourceCounter.from_json_dict(d) + + @staticmethod + def from_json_dict(d): + sbp = SBP.from_json_dict(d) + return MsgProfilingResourceCounter(sbp, **d) + + + def from_binary(self, d): + """Given a binary payload d, update the appropriate payload fields of + the message. + + """ + p = MsgProfilingResourceCounter._parser.parse(d) + for n in self.__class__.__slots__: + setattr(self, n, getattr(p, n)) + + def to_binary(self): + """Produce a framed/packed SBP message. + + """ + c = containerize(exclude_fields(self)) + self.payload = MsgProfilingResourceCounter._parser.build(c) + return self.pack() + + def friendly_name(self): + """Produces friendly human-readable name for this message + + """ + return "PROFILING RESOURCE COUNTER" + + def into_buffer(self, buf, offset): + """Produce a framed/packed SBP message into the provided buffer and offset. + + """ + self.payload = containerize(exclude_fields(self)) + self.parser = MsgProfilingResourceCounter._parser + self.stream_payload.reset(buf, offset) + return self.pack_into(buf, offset, self._build_payload) + + def to_json_dict(self): + self.to_binary() + d = super( MsgProfilingResourceCounter, self).to_json_dict() + j = walk_json_dict(exclude_fields(self)) + d.update(j) + return d + msg_classes = { 0xCF00: MsgMeasurementPoint, + 0xCF01: MsgProfilingSystemInfo, + 0xCF02: MsgProfilingThreadInfo, + 0xCF03: MsgProfilingResourceCounter, } \ No newline at end of file diff --git a/python/tests/sbp/test_table.py b/python/tests/sbp/test_table.py index 636bdae92b..d0597e6af7 100644 --- a/python/tests/sbp/test_table.py +++ b/python/tests/sbp/test_table.py @@ -44,7 +44,7 @@ def test_table_count(): Test number of available messages to deserialize. """ - number_of_messages = 234 + number_of_messages = 237 assert len(_SBP_TABLE) == number_of_messages def test_table_unqiue_count(): diff --git a/rust/sbp/src/messages/mod.rs b/rust/sbp/src/messages/mod.rs index d0bf93f024..8d4dbc8cbe 100644 --- a/rust/sbp/src/messages/mod.rs +++ b/rust/sbp/src/messages/mod.rs @@ -211,6 +211,9 @@ use self::piksi::msg_thread_state::MsgThreadState; use self::piksi::msg_uart_state::MsgUartState; use self::piksi::msg_uart_state_depa::MsgUartStateDepa; use self::profiling::msg_measurement_point::MsgMeasurementPoint; +use self::profiling::msg_profiling_resource_counter::MsgProfilingResourceCounter; +use self::profiling::msg_profiling_system_info::MsgProfilingSystemInfo; +use self::profiling::msg_profiling_thread_info::MsgProfilingThreadInfo; use self::sbas::msg_sbas_raw::MsgSbasRaw; use self::settings::msg_settings_read_by_index_done::MsgSettingsReadByIndexDone; use self::settings::msg_settings_read_by_index_req::MsgSettingsReadByIndexReq; @@ -824,6 +827,12 @@ pub enum Sbp { MsgLinuxSysState(MsgLinuxSysState), /// Profiling Measurement Point MsgMeasurementPoint(MsgMeasurementPoint), + /// System Profiling Information + MsgProfilingSystemInfo(MsgProfilingSystemInfo), + /// Thread Profiling Information + MsgProfilingThreadInfo(MsgProfilingThreadInfo), + /// Information about resource buckets + MsgProfilingResourceCounter(MsgProfilingResourceCounter), /// System start-up message MsgStartup(MsgStartup), /// Status of received corrections @@ -1566,6 +1575,18 @@ impl<'de> serde::Deserialize<'de> for Sbp { Some(MsgMeasurementPoint::MESSAGE_TYPE) => { serde_json::from_value::(value).map(Sbp::MsgMeasurementPoint) } + Some(MsgProfilingSystemInfo::MESSAGE_TYPE) => { + serde_json::from_value::(value) + .map(Sbp::MsgProfilingSystemInfo) + } + Some(MsgProfilingThreadInfo::MESSAGE_TYPE) => { + serde_json::from_value::(value) + .map(Sbp::MsgProfilingThreadInfo) + } + Some(MsgProfilingResourceCounter::MESSAGE_TYPE) => { + serde_json::from_value::(value) + .map(Sbp::MsgProfilingResourceCounter) + } Some(MsgStartup::MESSAGE_TYPE) => { serde_json::from_value::(value).map(Sbp::MsgStartup) } @@ -2254,6 +2275,16 @@ impl Sbp { MsgMeasurementPoint::MESSAGE_TYPE => { MsgMeasurementPoint::parse(&mut payload).map(Sbp::MsgMeasurementPoint) } + MsgProfilingSystemInfo::MESSAGE_TYPE => { + MsgProfilingSystemInfo::parse(&mut payload).map(Sbp::MsgProfilingSystemInfo) + } + MsgProfilingThreadInfo::MESSAGE_TYPE => { + MsgProfilingThreadInfo::parse(&mut payload).map(Sbp::MsgProfilingThreadInfo) + } + MsgProfilingResourceCounter::MESSAGE_TYPE => { + MsgProfilingResourceCounter::parse(&mut payload) + .map(Sbp::MsgProfilingResourceCounter) + } MsgStartup::MESSAGE_TYPE => MsgStartup::parse(&mut payload).map(Sbp::MsgStartup), MsgDgnssStatus::MESSAGE_TYPE => { MsgDgnssStatus::parse(&mut payload).map(Sbp::MsgDgnssStatus) @@ -2534,6 +2565,9 @@ impl SbpMessage for Sbp { Sbp::MsgLinuxMemState(msg) => msg.message_name(), Sbp::MsgLinuxSysState(msg) => msg.message_name(), Sbp::MsgMeasurementPoint(msg) => msg.message_name(), + Sbp::MsgProfilingSystemInfo(msg) => msg.message_name(), + Sbp::MsgProfilingThreadInfo(msg) => msg.message_name(), + Sbp::MsgProfilingResourceCounter(msg) => msg.message_name(), Sbp::MsgStartup(msg) => msg.message_name(), Sbp::MsgDgnssStatus(msg) => msg.message_name(), Sbp::MsgInsStatus(msg) => msg.message_name(), @@ -2775,6 +2809,9 @@ impl SbpMessage for Sbp { Sbp::MsgLinuxMemState(msg) => msg.message_type(), Sbp::MsgLinuxSysState(msg) => msg.message_type(), Sbp::MsgMeasurementPoint(msg) => msg.message_type(), + Sbp::MsgProfilingSystemInfo(msg) => msg.message_type(), + Sbp::MsgProfilingThreadInfo(msg) => msg.message_type(), + Sbp::MsgProfilingResourceCounter(msg) => msg.message_type(), Sbp::MsgStartup(msg) => msg.message_type(), Sbp::MsgDgnssStatus(msg) => msg.message_type(), Sbp::MsgInsStatus(msg) => msg.message_type(), @@ -3016,6 +3053,9 @@ impl SbpMessage for Sbp { Sbp::MsgLinuxMemState(msg) => msg.sender_id(), Sbp::MsgLinuxSysState(msg) => msg.sender_id(), Sbp::MsgMeasurementPoint(msg) => msg.sender_id(), + Sbp::MsgProfilingSystemInfo(msg) => msg.sender_id(), + Sbp::MsgProfilingThreadInfo(msg) => msg.sender_id(), + Sbp::MsgProfilingResourceCounter(msg) => msg.sender_id(), Sbp::MsgStartup(msg) => msg.sender_id(), Sbp::MsgDgnssStatus(msg) => msg.sender_id(), Sbp::MsgInsStatus(msg) => msg.sender_id(), @@ -3257,6 +3297,9 @@ impl SbpMessage for Sbp { Sbp::MsgLinuxMemState(msg) => msg.set_sender_id(new_id), Sbp::MsgLinuxSysState(msg) => msg.set_sender_id(new_id), Sbp::MsgMeasurementPoint(msg) => msg.set_sender_id(new_id), + Sbp::MsgProfilingSystemInfo(msg) => msg.set_sender_id(new_id), + Sbp::MsgProfilingThreadInfo(msg) => msg.set_sender_id(new_id), + Sbp::MsgProfilingResourceCounter(msg) => msg.set_sender_id(new_id), Sbp::MsgStartup(msg) => msg.set_sender_id(new_id), Sbp::MsgDgnssStatus(msg) => msg.set_sender_id(new_id), Sbp::MsgInsStatus(msg) => msg.set_sender_id(new_id), @@ -3498,6 +3541,9 @@ impl SbpMessage for Sbp { Sbp::MsgLinuxMemState(msg) => msg.encoded_len(), Sbp::MsgLinuxSysState(msg) => msg.encoded_len(), Sbp::MsgMeasurementPoint(msg) => msg.encoded_len(), + Sbp::MsgProfilingSystemInfo(msg) => msg.encoded_len(), + Sbp::MsgProfilingThreadInfo(msg) => msg.encoded_len(), + Sbp::MsgProfilingResourceCounter(msg) => msg.encoded_len(), Sbp::MsgStartup(msg) => msg.encoded_len(), Sbp::MsgDgnssStatus(msg) => msg.encoded_len(), Sbp::MsgInsStatus(msg) => msg.encoded_len(), @@ -3742,6 +3788,9 @@ impl SbpMessage for Sbp { Sbp::MsgLinuxMemState(msg) => msg.gps_time(), Sbp::MsgLinuxSysState(msg) => msg.gps_time(), Sbp::MsgMeasurementPoint(msg) => msg.gps_time(), + Sbp::MsgProfilingSystemInfo(msg) => msg.gps_time(), + Sbp::MsgProfilingThreadInfo(msg) => msg.gps_time(), + Sbp::MsgProfilingResourceCounter(msg) => msg.gps_time(), Sbp::MsgStartup(msg) => msg.gps_time(), Sbp::MsgDgnssStatus(msg) => msg.gps_time(), Sbp::MsgInsStatus(msg) => msg.gps_time(), @@ -3983,6 +4032,9 @@ impl SbpMessage for Sbp { Sbp::MsgLinuxMemState(msg) => msg.friendly_name(), Sbp::MsgLinuxSysState(msg) => msg.friendly_name(), Sbp::MsgMeasurementPoint(msg) => msg.friendly_name(), + Sbp::MsgProfilingSystemInfo(msg) => msg.friendly_name(), + Sbp::MsgProfilingThreadInfo(msg) => msg.friendly_name(), + Sbp::MsgProfilingResourceCounter(msg) => msg.friendly_name(), Sbp::MsgStartup(msg) => msg.friendly_name(), Sbp::MsgDgnssStatus(msg) => msg.friendly_name(), Sbp::MsgInsStatus(msg) => msg.friendly_name(), @@ -4224,6 +4276,9 @@ impl SbpMessage for Sbp { Sbp::MsgLinuxMemState(msg) => msg.is_valid(), Sbp::MsgLinuxSysState(msg) => msg.is_valid(), Sbp::MsgMeasurementPoint(msg) => msg.is_valid(), + Sbp::MsgProfilingSystemInfo(msg) => msg.is_valid(), + Sbp::MsgProfilingThreadInfo(msg) => msg.is_valid(), + Sbp::MsgProfilingResourceCounter(msg) => msg.is_valid(), Sbp::MsgStartup(msg) => msg.is_valid(), Sbp::MsgDgnssStatus(msg) => msg.is_valid(), Sbp::MsgInsStatus(msg) => msg.is_valid(), @@ -4554,6 +4609,15 @@ impl SbpMessage for Sbp { Sbp::MsgLinuxMemState(msg) => Ok(Sbp::MsgLinuxMemState(msg.into_valid_msg()?)), Sbp::MsgLinuxSysState(msg) => Ok(Sbp::MsgLinuxSysState(msg.into_valid_msg()?)), Sbp::MsgMeasurementPoint(msg) => Ok(Sbp::MsgMeasurementPoint(msg.into_valid_msg()?)), + Sbp::MsgProfilingSystemInfo(msg) => { + Ok(Sbp::MsgProfilingSystemInfo(msg.into_valid_msg()?)) + } + Sbp::MsgProfilingThreadInfo(msg) => { + Ok(Sbp::MsgProfilingThreadInfo(msg.into_valid_msg()?)) + } + Sbp::MsgProfilingResourceCounter(msg) => { + Ok(Sbp::MsgProfilingResourceCounter(msg.into_valid_msg()?)) + } Sbp::MsgStartup(msg) => Ok(Sbp::MsgStartup(msg.into_valid_msg()?)), Sbp::MsgDgnssStatus(msg) => Ok(Sbp::MsgDgnssStatus(msg.into_valid_msg()?)), Sbp::MsgInsStatus(msg) => Ok(Sbp::MsgInsStatus(msg.into_valid_msg()?)), @@ -4810,6 +4874,9 @@ impl WireFormat for Sbp { Sbp::MsgLinuxMemState(msg) => WireFormat::write(msg, buf), Sbp::MsgLinuxSysState(msg) => WireFormat::write(msg, buf), Sbp::MsgMeasurementPoint(msg) => WireFormat::write(msg, buf), + Sbp::MsgProfilingSystemInfo(msg) => WireFormat::write(msg, buf), + Sbp::MsgProfilingThreadInfo(msg) => WireFormat::write(msg, buf), + Sbp::MsgProfilingResourceCounter(msg) => WireFormat::write(msg, buf), Sbp::MsgStartup(msg) => WireFormat::write(msg, buf), Sbp::MsgDgnssStatus(msg) => WireFormat::write(msg, buf), Sbp::MsgInsStatus(msg) => WireFormat::write(msg, buf), @@ -5051,6 +5118,9 @@ impl WireFormat for Sbp { Sbp::MsgLinuxMemState(msg) => WireFormat::len(msg), Sbp::MsgLinuxSysState(msg) => WireFormat::len(msg), Sbp::MsgMeasurementPoint(msg) => WireFormat::len(msg), + Sbp::MsgProfilingSystemInfo(msg) => WireFormat::len(msg), + Sbp::MsgProfilingThreadInfo(msg) => WireFormat::len(msg), + Sbp::MsgProfilingResourceCounter(msg) => WireFormat::len(msg), Sbp::MsgStartup(msg) => WireFormat::len(msg), Sbp::MsgDgnssStatus(msg) => WireFormat::len(msg), Sbp::MsgInsStatus(msg) => WireFormat::len(msg), @@ -6386,6 +6456,24 @@ impl From for Sbp { } } +impl From for Sbp { + fn from(msg: MsgProfilingSystemInfo) -> Self { + Sbp::MsgProfilingSystemInfo(msg) + } +} + +impl From for Sbp { + fn from(msg: MsgProfilingThreadInfo) -> Self { + Sbp::MsgProfilingThreadInfo(msg) + } +} + +impl From for Sbp { + fn from(msg: MsgProfilingResourceCounter) -> Self { + Sbp::MsgProfilingResourceCounter(msg) + } +} + impl From for Sbp { fn from(msg: MsgStartup) -> Self { Sbp::MsgStartup(msg) diff --git a/rust/sbp/src/messages/profiling.rs b/rust/sbp/src/messages/profiling.rs index bba31cb7d4..d122079f1c 100644 --- a/rust/sbp/src/messages/profiling.rs +++ b/rust/sbp/src/messages/profiling.rs @@ -14,6 +14,10 @@ //****************************************************************************/ //! Standardized profiling messages from Swift Navigation devices. pub use msg_measurement_point::MsgMeasurementPoint; +pub use msg_profiling_resource_counter::MsgProfilingResourceCounter; +pub use msg_profiling_system_info::MsgProfilingSystemInfo; +pub use msg_profiling_thread_info::MsgProfilingThreadInfo; +pub use resource_bucket::ResourceBucket; pub mod msg_measurement_point { #![allow(unused_imports)] @@ -156,3 +160,475 @@ pub mod msg_measurement_point { } } } + +pub mod msg_profiling_resource_counter { + #![allow(unused_imports)] + + use super::*; + use crate::messages::lib::*; + + /// Information about resource buckets + /// + /// Information about resource buckets. Refer to product documentation to + /// understand the meaning and values in this message. + /// + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Debug, PartialEq, Clone)] + pub struct MsgProfilingResourceCounter { + /// The message sender_id + #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))] + pub sender_id: Option, + /// Message number in complete sequence + #[cfg_attr(feature = "serde", serde(rename = "seq_no"))] + pub seq_no: u8, + /// Length of message sequence + #[cfg_attr(feature = "serde", serde(rename = "seq_len"))] + pub seq_len: u8, + /// List of resource buckets + #[cfg_attr(feature = "serde", serde(rename = "buckets"))] + pub buckets: Vec, + } + + impl ConcreteMessage for MsgProfilingResourceCounter { + const MESSAGE_TYPE: u16 = 52995; + const MESSAGE_NAME: &'static str = "MSG_PROFILING_RESOURCE_COUNTER"; + } + + impl SbpMessage for MsgProfilingResourceCounter { + fn message_name(&self) -> &'static str { + ::MESSAGE_NAME + } + fn message_type(&self) -> Option { + Some(::MESSAGE_TYPE) + } + fn sender_id(&self) -> Option { + self.sender_id + } + fn set_sender_id(&mut self, new_id: u16) { + self.sender_id = Some(new_id); + } + fn encoded_len(&self) -> usize { + WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN + } + fn is_valid(&self) -> bool { + true + } + fn into_valid_msg(self) -> Result { + Ok(self) + } + } + + impl FriendlyName for MsgProfilingResourceCounter { + fn friendly_name() -> &'static str { + "PROFILING RESOURCE COUNTER" + } + } + + impl TryFrom for MsgProfilingResourceCounter { + type Error = TryFromSbpError; + fn try_from(msg: Sbp) -> Result { + match msg { + Sbp::MsgProfilingResourceCounter(m) => Ok(m), + _ => Err(TryFromSbpError(msg)), + } + } + } + + impl WireFormat for MsgProfilingResourceCounter { + const MIN_LEN: usize = ::MIN_LEN + + ::MIN_LEN + + as WireFormat>::MIN_LEN; + fn len(&self) -> usize { + WireFormat::len(&self.seq_no) + + WireFormat::len(&self.seq_len) + + WireFormat::len(&self.buckets) + } + fn write(&self, buf: &mut B) { + WireFormat::write(&self.seq_no, buf); + WireFormat::write(&self.seq_len, buf); + WireFormat::write(&self.buckets, buf); + } + fn parse_unchecked(buf: &mut B) -> Self { + MsgProfilingResourceCounter { + sender_id: None, + seq_no: WireFormat::parse_unchecked(buf), + seq_len: WireFormat::parse_unchecked(buf), + buckets: WireFormat::parse_unchecked(buf), + } + } + } +} + +pub mod msg_profiling_system_info { + #![allow(unused_imports)] + + use super::*; + use crate::messages::lib::*; + + /// System Profiling Information + /// + /// Contains basic information about system resource usage. System is defined + /// in terms of the source of this message and may vary from sender to + /// sender. Refer to product documentation to understand the exact scope and + /// meaning of this message. + /// + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Debug, PartialEq, Clone)] + pub struct MsgProfilingSystemInfo { + /// The message sender_id + #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))] + pub sender_id: Option, + /// Total cpu time in microseconds consumed by this system + #[cfg_attr(feature = "serde", serde(rename = "total_cpu_time"))] + pub total_cpu_time: u64, + /// Age of the producing system in microseconds + #[cfg_attr(feature = "serde", serde(rename = "age"))] + pub age: u64, + /// Number of threads being tracked by this system + #[cfg_attr(feature = "serde", serde(rename = "n_threads"))] + pub n_threads: u8, + /// Number of bytes allocated on the heap + #[cfg_attr(feature = "serde", serde(rename = "heap_usage"))] + pub heap_usage: u32, + } + + impl ConcreteMessage for MsgProfilingSystemInfo { + const MESSAGE_TYPE: u16 = 52993; + const MESSAGE_NAME: &'static str = "MSG_PROFILING_SYSTEM_INFO"; + } + + impl SbpMessage for MsgProfilingSystemInfo { + fn message_name(&self) -> &'static str { + ::MESSAGE_NAME + } + fn message_type(&self) -> Option { + Some(::MESSAGE_TYPE) + } + fn sender_id(&self) -> Option { + self.sender_id + } + fn set_sender_id(&mut self, new_id: u16) { + self.sender_id = Some(new_id); + } + fn encoded_len(&self) -> usize { + WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN + } + fn is_valid(&self) -> bool { + true + } + fn into_valid_msg(self) -> Result { + Ok(self) + } + } + + impl FriendlyName for MsgProfilingSystemInfo { + fn friendly_name() -> &'static str { + "PROFILING SYSTEM INFO" + } + } + + impl TryFrom for MsgProfilingSystemInfo { + type Error = TryFromSbpError; + fn try_from(msg: Sbp) -> Result { + match msg { + Sbp::MsgProfilingSystemInfo(m) => Ok(m), + _ => Err(TryFromSbpError(msg)), + } + } + } + + impl WireFormat for MsgProfilingSystemInfo { + const MIN_LEN: usize = ::MIN_LEN + + ::MIN_LEN + + ::MIN_LEN + + ::MIN_LEN; + fn len(&self) -> usize { + WireFormat::len(&self.total_cpu_time) + + WireFormat::len(&self.age) + + WireFormat::len(&self.n_threads) + + WireFormat::len(&self.heap_usage) + } + fn write(&self, buf: &mut B) { + WireFormat::write(&self.total_cpu_time, buf); + WireFormat::write(&self.age, buf); + WireFormat::write(&self.n_threads, buf); + WireFormat::write(&self.heap_usage, buf); + } + fn parse_unchecked(buf: &mut B) -> Self { + MsgProfilingSystemInfo { + sender_id: None, + total_cpu_time: WireFormat::parse_unchecked(buf), + age: WireFormat::parse_unchecked(buf), + n_threads: WireFormat::parse_unchecked(buf), + heap_usage: WireFormat::parse_unchecked(buf), + } + } + } +} + +pub mod msg_profiling_thread_info { + #![allow(unused_imports)] + + use super::*; + use crate::messages::lib::*; + + /// Thread Profiling Information + /// + /// Contains profiling information related to a single thread being tracked by + /// the producing system. Refer to product documentation to understand the + /// exact scope and meaning of this message. + /// + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Debug, PartialEq, Clone)] + pub struct MsgProfilingThreadInfo { + /// The message sender_id + #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))] + pub sender_id: Option, + /// Total cpu time in microseconds consumed by this thread + #[cfg_attr(feature = "serde", serde(rename = "total_cpu_time"))] + pub total_cpu_time: u64, + /// Age of the thread in microseconds + #[cfg_attr(feature = "serde", serde(rename = "age"))] + pub age: u64, + /// Thread state + #[cfg_attr(feature = "serde", serde(rename = "state"))] + pub state: u8, + /// Stack size in bytes + #[cfg_attr(feature = "serde", serde(rename = "stack_size"))] + pub stack_size: u32, + /// Stack highwater usage in bytes + #[cfg_attr(feature = "serde", serde(rename = "stack_usage"))] + pub stack_usage: u32, + /// Thread name + #[cfg_attr(feature = "serde", serde(rename = "name"))] + pub name: SbpString, NullTerminated>, + } + + impl MsgProfilingThreadInfo { + /// Gets the [ThreadState][self::ThreadState] stored in the `state` bitfield. + /// + /// Returns `Ok` if the bitrange contains a known `ThreadState` variant. + /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message, + /// or because new variants of `ThreadState` were added. + pub fn thread_state(&self) -> Result { + get_bit_range!(self.state, u8, u8, 1, 0).try_into() + } + + /// Set the bitrange corresponding to the [ThreadState][ThreadState] of the `state` bitfield. + pub fn set_thread_state(&mut self, thread_state: ThreadState) { + set_bit_range!(&mut self.state, thread_state, u8, u8, 1, 0); + } + } + + impl ConcreteMessage for MsgProfilingThreadInfo { + const MESSAGE_TYPE: u16 = 52994; + const MESSAGE_NAME: &'static str = "MSG_PROFILING_THREAD_INFO"; + } + + impl SbpMessage for MsgProfilingThreadInfo { + fn message_name(&self) -> &'static str { + ::MESSAGE_NAME + } + fn message_type(&self) -> Option { + Some(::MESSAGE_TYPE) + } + fn sender_id(&self) -> Option { + self.sender_id + } + fn set_sender_id(&mut self, new_id: u16) { + self.sender_id = Some(new_id); + } + fn encoded_len(&self) -> usize { + WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN + } + fn is_valid(&self) -> bool { + true + } + fn into_valid_msg(self) -> Result { + Ok(self) + } + } + + impl FriendlyName for MsgProfilingThreadInfo { + fn friendly_name() -> &'static str { + "PROFILING THREAD INFO" + } + } + + impl TryFrom for MsgProfilingThreadInfo { + type Error = TryFromSbpError; + fn try_from(msg: Sbp) -> Result { + match msg { + Sbp::MsgProfilingThreadInfo(m) => Ok(m), + _ => Err(TryFromSbpError(msg)), + } + } + } + + impl WireFormat for MsgProfilingThreadInfo { + const MIN_LEN: usize = ::MIN_LEN + + ::MIN_LEN + + ::MIN_LEN + + ::MIN_LEN + + ::MIN_LEN + + , NullTerminated> as WireFormat>::MIN_LEN; + fn len(&self) -> usize { + WireFormat::len(&self.total_cpu_time) + + WireFormat::len(&self.age) + + WireFormat::len(&self.state) + + WireFormat::len(&self.stack_size) + + WireFormat::len(&self.stack_usage) + + WireFormat::len(&self.name) + } + fn write(&self, buf: &mut B) { + WireFormat::write(&self.total_cpu_time, buf); + WireFormat::write(&self.age, buf); + WireFormat::write(&self.state, buf); + WireFormat::write(&self.stack_size, buf); + WireFormat::write(&self.stack_usage, buf); + WireFormat::write(&self.name, buf); + } + fn parse_unchecked(buf: &mut B) -> Self { + MsgProfilingThreadInfo { + sender_id: None, + total_cpu_time: WireFormat::parse_unchecked(buf), + age: WireFormat::parse_unchecked(buf), + state: WireFormat::parse_unchecked(buf), + stack_size: WireFormat::parse_unchecked(buf), + stack_usage: WireFormat::parse_unchecked(buf), + name: WireFormat::parse_unchecked(buf), + } + } + } + + /// Thread state + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + pub enum ThreadState { + /// External + External = 0, + + /// Running + Running = 1, + + /// Stopped + Stopped = 2, + } + + impl std::fmt::Display for ThreadState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ThreadState::External => f.write_str("External"), + ThreadState::Running => f.write_str("Running"), + ThreadState::Stopped => f.write_str("Stopped"), + } + } + } + + impl TryFrom for ThreadState { + type Error = u8; + fn try_from(i: u8) -> Result { + match i { + 0 => Ok(ThreadState::External), + 1 => Ok(ThreadState::Running), + 2 => Ok(ThreadState::Stopped), + i => Err(i), + } + } + } +} + +pub mod resource_bucket { + #![allow(unused_imports)] + + use super::*; + use crate::messages::lib::*; + + /// A bucket containing various resources + /// + /// Information about allocation of various resources grouped by buckets. + /// Refer to product documentation to understand the meaning and values in + /// this message. + /// + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Debug, PartialEq, Clone)] + pub struct ResourceBucket { + /// Bucket name + #[cfg_attr(feature = "serde", serde(rename = "name"))] + pub name: SbpString<[u8; 21], NullTerminated>, + /// Number of threads + #[cfg_attr(feature = "serde", serde(rename = "thread"))] + pub thread: u8, + /// Number of mutexes + #[cfg_attr(feature = "serde", serde(rename = "mutex"))] + pub mutex: u8, + /// Number of condition variables + #[cfg_attr(feature = "serde", serde(rename = "cv"))] + pub cv: u8, + /// Number of IO handles + #[cfg_attr(feature = "serde", serde(rename = "io"))] + pub io: u8, + /// Number of bytes allocated on the heap + #[cfg_attr(feature = "serde", serde(rename = "heap_bytes_alloc"))] + pub heap_bytes_alloc: u32, + /// Number of bytes freed on the heap + #[cfg_attr(feature = "serde", serde(rename = "heap_bytes_free"))] + pub heap_bytes_free: u32, + /// Number of bytes written to IO handles + #[cfg_attr(feature = "serde", serde(rename = "io_write"))] + pub io_write: u32, + /// Number of bytes read from IO handles + #[cfg_attr(feature = "serde", serde(rename = "io_read"))] + pub io_read: u32, + } + + impl WireFormat for ResourceBucket { + const MIN_LEN: usize = as WireFormat>::MIN_LEN + + ::MIN_LEN + + ::MIN_LEN + + ::MIN_LEN + + ::MIN_LEN + + ::MIN_LEN + + ::MIN_LEN + + ::MIN_LEN + + ::MIN_LEN; + fn len(&self) -> usize { + WireFormat::len(&self.name) + + WireFormat::len(&self.thread) + + WireFormat::len(&self.mutex) + + WireFormat::len(&self.cv) + + WireFormat::len(&self.io) + + WireFormat::len(&self.heap_bytes_alloc) + + WireFormat::len(&self.heap_bytes_free) + + WireFormat::len(&self.io_write) + + WireFormat::len(&self.io_read) + } + fn write(&self, buf: &mut B) { + WireFormat::write(&self.name, buf); + WireFormat::write(&self.thread, buf); + WireFormat::write(&self.mutex, buf); + WireFormat::write(&self.cv, buf); + WireFormat::write(&self.io, buf); + WireFormat::write(&self.heap_bytes_alloc, buf); + WireFormat::write(&self.heap_bytes_free, buf); + WireFormat::write(&self.io_write, buf); + WireFormat::write(&self.io_read, buf); + } + fn parse_unchecked(buf: &mut B) -> Self { + ResourceBucket { + name: WireFormat::parse_unchecked(buf), + thread: WireFormat::parse_unchecked(buf), + mutex: WireFormat::parse_unchecked(buf), + cv: WireFormat::parse_unchecked(buf), + io: WireFormat::parse_unchecked(buf), + heap_bytes_alloc: WireFormat::parse_unchecked(buf), + heap_bytes_free: WireFormat::parse_unchecked(buf), + io_write: WireFormat::parse_unchecked(buf), + io_read: WireFormat::parse_unchecked(buf), + } + } + } +} diff --git a/rust/sbp/tests/integration/auto_check_sbp_profiling_msg_profiling_resource_counter.rs b/rust/sbp/tests/integration/auto_check_sbp_profiling_msg_profiling_resource_counter.rs new file mode 100644 index 0000000000..03ed3b391d --- /dev/null +++ b/rust/sbp/tests/integration/auto_check_sbp_profiling_msg_profiling_resource_counter.rs @@ -0,0 +1,1100 @@ +// +// Copyright (C) 2019-2021 Swift Navigation Inc. +// Contact: https://support.swiftnav.com +// +// This source is subject to the license found in the file 'LICENSE' which must +// be be distributed together with this source. All other rights reserved. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + +// This file was auto-generated from spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingResourceCounter.yaml by generate.py. Do not modify by hand! + +use crate::*; + +/// Tests [`sbp::iter_messages`], from payload into SBP messages +/// +/// Asserts: +/// - SBP fields equates to that of the field +/// - Payload is identical +#[test] +fn test_auto_check_sbp_profiling_msg_profiling_resource_counter() { + { + let mut payload = Cursor::new(vec![ + 85, 3, 207, 0, 16, 248, 1, 3, 70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, + 101, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 248, 38, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 78, 84, 82, 73, 80, 32, 99, 108, 105, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 230, 73, 1, 0, 0, 0, 0, 0, 111, 3, 0, 0, 64, 76, 0, 0, 83, 83, 82, 50, 79, + 83, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 72, 13, 66, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 101, 114, 105, 111, 100, 105, 99, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 72, 197, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, + 77, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 129, 71, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 102, 0, 0, 115, 98, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 2, 2, 2, 243, 169, 0, 0, 0, 0, 0, 0, 187, 151, 3, 0, 242, 1, + 0, 0, 181, 153, + ]); + + // Test the round trip payload parsing + let sbp_msg = { + let mut msgs = iter_messages(&mut payload); + msgs.next() + .expect("no message found") + .expect("failed to parse message") + }; + match &sbp_msg { + sbp::messages::Sbp::MsgProfilingResourceCounter(msg) => { + let msg_type = msg.message_type().unwrap(); + assert_eq!( + msg_type, 0xcf03, + "Incorrect message type, expected 0xcf03, is {}", + msg_type + ); + let sender_id = msg.sender_id().unwrap(); + assert_eq!( + sender_id, 0x1000, + "incorrect sender id, expected 0x1000, is {sender_id}" + ); + assert_eq!( + msg.buckets[0].cv, 2, + "incorrect value for buckets[0].cv, expected 2, is {}", + msg.buckets[0].cv + ); + assert_eq!( + msg.buckets[0].heap_bytes_alloc, 927480, + "incorrect value for buckets[0].heap_bytes_alloc, expected 927480, is {}", + msg.buckets[0].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[0].heap_bytes_free, 0, + "incorrect value for buckets[0].heap_bytes_free, expected 0, is {}", + msg.buckets[0].heap_bytes_free + ); + assert_eq!( + msg.buckets[0].io, 0, + "incorrect value for buckets[0].io, expected 0, is {}", + msg.buckets[0].io + ); + assert_eq!( + msg.buckets[0].io_read, 0, + "incorrect value for buckets[0].io_read, expected 0, is {}", + msg.buckets[0].io_read + ); + assert_eq!( + msg.buckets[0].io_write, 0, + "incorrect value for buckets[0].io_write, expected 0, is {}", + msg.buckets[0].io_write + ); + assert_eq!( + msg.buckets[0].mutex, 2, + "incorrect value for buckets[0].mutex, expected 2, is {}", + msg.buckets[0].mutex + ); + assert_eq!( + msg.buckets[0].name.as_bytes(), + &[ + 70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, 0, 0, 0, 0, + 0, 0, 0, 0 + ], + "incorrect value for msg.buckets[0].name, expected string '{:?}', is '{:?}'", + &[ + 70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, 0, 0, 0, 0, + 0, 0, 0, 0 + ], + msg.buckets[0].name.as_bytes() + ); + assert_eq!( + msg.buckets[0].thread, 1, + "incorrect value for buckets[0].thread, expected 1, is {}", + msg.buckets[0].thread + ); + assert_eq!( + msg.buckets[1].cv, 1, + "incorrect value for buckets[1].cv, expected 1, is {}", + msg.buckets[1].cv + ); + assert_eq!( + msg.buckets[1].heap_bytes_alloc, 84454, + "incorrect value for buckets[1].heap_bytes_alloc, expected 84454, is {}", + msg.buckets[1].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[1].heap_bytes_free, 0, + "incorrect value for buckets[1].heap_bytes_free, expected 0, is {}", + msg.buckets[1].heap_bytes_free + ); + assert_eq!( + msg.buckets[1].io, 1, + "incorrect value for buckets[1].io, expected 1, is {}", + msg.buckets[1].io + ); + assert_eq!( + msg.buckets[1].io_read, 19520, + "incorrect value for buckets[1].io_read, expected 19520, is {}", + msg.buckets[1].io_read + ); + assert_eq!( + msg.buckets[1].io_write, 879, + "incorrect value for buckets[1].io_write, expected 879, is {}", + msg.buckets[1].io_write + ); + assert_eq!( + msg.buckets[1].mutex, 1, + "incorrect value for buckets[1].mutex, expected 1, is {}", + msg.buckets[1].mutex + ); + assert_eq!( + msg.buckets[1].name.as_bytes(), + &[ + 78, 84, 82, 73, 80, 32, 99, 108, 105, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, + 0, 0 + ], + "incorrect value for msg.buckets[1].name, expected string '{:?}', is '{:?}'", + &[ + 78, 84, 82, 73, 80, 32, 99, 108, 105, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, + 0, 0 + ], + msg.buckets[1].name.as_bytes() + ); + assert_eq!( + msg.buckets[1].thread, 1, + "incorrect value for buckets[1].thread, expected 1, is {}", + msg.buckets[1].thread + ); + assert_eq!( + msg.buckets[2].cv, 1, + "incorrect value for buckets[2].cv, expected 1, is {}", + msg.buckets[2].cv + ); + assert_eq!( + msg.buckets[2].heap_bytes_alloc, 4328776, + "incorrect value for buckets[2].heap_bytes_alloc, expected 4328776, is {}", + msg.buckets[2].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[2].heap_bytes_free, 0, + "incorrect value for buckets[2].heap_bytes_free, expected 0, is {}", + msg.buckets[2].heap_bytes_free + ); + assert_eq!( + msg.buckets[2].io, 0, + "incorrect value for buckets[2].io, expected 0, is {}", + msg.buckets[2].io + ); + assert_eq!( + msg.buckets[2].io_read, 0, + "incorrect value for buckets[2].io_read, expected 0, is {}", + msg.buckets[2].io_read + ); + assert_eq!( + msg.buckets[2].io_write, 0, + "incorrect value for buckets[2].io_write, expected 0, is {}", + msg.buckets[2].io_write + ); + assert_eq!( + msg.buckets[2].mutex, 1, + "incorrect value for buckets[2].mutex, expected 1, is {}", + msg.buckets[2].mutex + ); + assert_eq!( + msg.buckets[2].name.as_bytes(), + &[83, 83, 82, 50, 79, 83, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "incorrect value for msg.buckets[2].name, expected string '{:?}', is '{:?}'", + &[83, 83, 82, 50, 79, 83, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + msg.buckets[2].name.as_bytes() + ); + assert_eq!( + msg.buckets[2].thread, 1, + "incorrect value for buckets[2].thread, expected 1, is {}", + msg.buckets[2].thread + ); + assert_eq!( + msg.buckets[3].cv, 1, + "incorrect value for buckets[3].cv, expected 1, is {}", + msg.buckets[3].cv + ); + assert_eq!( + msg.buckets[3].heap_bytes_alloc, 247112, + "incorrect value for buckets[3].heap_bytes_alloc, expected 247112, is {}", + msg.buckets[3].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[3].heap_bytes_free, 0, + "incorrect value for buckets[3].heap_bytes_free, expected 0, is {}", + msg.buckets[3].heap_bytes_free + ); + assert_eq!( + msg.buckets[3].io, 0, + "incorrect value for buckets[3].io, expected 0, is {}", + msg.buckets[3].io + ); + assert_eq!( + msg.buckets[3].io_read, 0, + "incorrect value for buckets[3].io_read, expected 0, is {}", + msg.buckets[3].io_read + ); + assert_eq!( + msg.buckets[3].io_write, 0, + "incorrect value for buckets[3].io_write, expected 0, is {}", + msg.buckets[3].io_write + ); + assert_eq!( + msg.buckets[3].mutex, 2, + "incorrect value for buckets[3].mutex, expected 2, is {}", + msg.buckets[3].mutex + ); + assert_eq!( + msg.buckets[3].name.as_bytes(), + &[80, 101, 114, 105, 111, 100, 105, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "incorrect value for msg.buckets[3].name, expected string '{:?}', is '{:?}'", + &[80, 101, 114, 105, 111, 100, 105, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + msg.buckets[3].name.as_bytes() + ); + assert_eq!( + msg.buckets[3].thread, 1, + "incorrect value for buckets[3].thread, expected 1, is {}", + msg.buckets[3].thread + ); + assert_eq!( + msg.buckets[4].cv, 1, + "incorrect value for buckets[4].cv, expected 1, is {}", + msg.buckets[4].cv + ); + assert_eq!( + msg.buckets[4].heap_bytes_alloc, 18305, + "incorrect value for buckets[4].heap_bytes_alloc, expected 18305, is {}", + msg.buckets[4].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[4].heap_bytes_free, 0, + "incorrect value for buckets[4].heap_bytes_free, expected 0, is {}", + msg.buckets[4].heap_bytes_free + ); + assert_eq!( + msg.buckets[4].io, 1, + "incorrect value for buckets[4].io, expected 1, is {}", + msg.buckets[4].io + ); + assert_eq!( + msg.buckets[4].io_read, 26207, + "incorrect value for buckets[4].io_read, expected 26207, is {}", + msg.buckets[4].io_read + ); + assert_eq!( + msg.buckets[4].io_write, 0, + "incorrect value for buckets[4].io_write, expected 0, is {}", + msg.buckets[4].io_write + ); + assert_eq!( + msg.buckets[4].mutex, 1, + "incorrect value for buckets[4].mutex, expected 1, is {}", + msg.buckets[4].mutex + ); + assert_eq!( + msg.buckets[4].name.as_bytes(), + &[73, 77, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "incorrect value for msg.buckets[4].name, expected string '{:?}', is '{:?}'", + &[73, 77, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + msg.buckets[4].name.as_bytes() + ); + assert_eq!( + msg.buckets[4].thread, 1, + "incorrect value for buckets[4].thread, expected 1, is {}", + msg.buckets[4].thread + ); + assert_eq!( + msg.buckets[5].cv, 2, + "incorrect value for buckets[5].cv, expected 2, is {}", + msg.buckets[5].cv + ); + assert_eq!( + msg.buckets[5].heap_bytes_alloc, 43507, + "incorrect value for buckets[5].heap_bytes_alloc, expected 43507, is {}", + msg.buckets[5].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[5].heap_bytes_free, 0, + "incorrect value for buckets[5].heap_bytes_free, expected 0, is {}", + msg.buckets[5].heap_bytes_free + ); + assert_eq!( + msg.buckets[5].io, 2, + "incorrect value for buckets[5].io, expected 2, is {}", + msg.buckets[5].io + ); + assert_eq!( + msg.buckets[5].io_read, 498, + "incorrect value for buckets[5].io_read, expected 498, is {}", + msg.buckets[5].io_read + ); + assert_eq!( + msg.buckets[5].io_write, 235451, + "incorrect value for buckets[5].io_write, expected 235451, is {}", + msg.buckets[5].io_write + ); + assert_eq!( + msg.buckets[5].mutex, 2, + "incorrect value for buckets[5].mutex, expected 2, is {}", + msg.buckets[5].mutex + ); + assert_eq!( + msg.buckets[5].name.as_bytes(), + &[115, 98, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "incorrect value for msg.buckets[5].name, expected string '{:?}', is '{:?}'", + &[115, 98, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + msg.buckets[5].name.as_bytes() + ); + assert_eq!( + msg.buckets[5].thread, 5, + "incorrect value for buckets[5].thread, expected 5, is {}", + msg.buckets[5].thread + ); + assert_eq!( + msg.seq_len, 3, + "incorrect value for seq_len, expected 3, is {}", + msg.seq_len + ); + assert_eq!( + msg.seq_no, 1, + "incorrect value for seq_no, expected 1, is {}", + msg.seq_no + ); + } + _ => panic!("Invalid message type! Expected a MsgProfilingResourceCounter"), + }; + let frame = sbp::to_vec(&sbp_msg).unwrap(); + assert_eq!(frame, payload.into_inner()); + } +} + +/// Tests [`sbp::json::iter_messages`] for JSON payload -> SBP message +/// and [`sbp::json::iter_messages_from_fields`] for JSON fields -> SBP message. +/// +/// Asserts: +/// - SBP message constructed via payload is identical to from fields +/// - SBP fields equates to that of the field +/// - Payload is identical +#[test] +#[cfg(feature = "json")] +fn test_json2sbp_auto_check_sbp_profiling_msg_profiling_resource_counter() { + { + let json_input = r#"{"crc": 39349, "preamble": 85, "sender": 4096, "length": 248, "msg_type": 52995, "seq_no": 1, "seq_len": 3, "buckets": [ {"name": "Fusion engine\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "thread": 1, "mutex": 2, "cv": 2, "io": 0, "heap_bytes_alloc": 927480, "heap_bytes_free": 0, "io_write": 0, "io_read": 0}, {"name": "NTRIP client\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "thread": 1, "mutex": 1, "cv": 1, "io": 1, "heap_bytes_alloc": 84454, "heap_bytes_free": 0, "io_write": 879, "io_read": 19520}, {"name": "SSR2OSR\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "thread": 1, "mutex": 1, "cv": 1, "io": 0, "heap_bytes_alloc": 4328776, "heap_bytes_free": 0, "io_write": 0, "io_read": 0}, {"name": "Periodic\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "thread": 1, "mutex": 2, "cv": 1, "io": 0, "heap_bytes_alloc": 247112, "heap_bytes_free": 0, "io_write": 0, "io_read": 0}, {"name": "IMU\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "thread": 1, "mutex": 1, "cv": 1, "io": 1, "heap_bytes_alloc": 18305, "heap_bytes_free": 0, "io_write": 0, "io_read": 26207}, {"name": "sbp\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "thread": 5, "mutex": 2, "cv": 2, "io": 2, "heap_bytes_alloc": 43507, "heap_bytes_free": 0, "io_write": 235451, "io_read": 498}], "payload": "AQNGdXNpb24gZW5naW5lAAAAAAAAAAABAgIA+CYOAAAAAAAAAAAAAAAAAE5UUklQIGNsaWVudAAAAAAAAAAAAAEBAQHmSQEAAAAAAG8DAABATAAAU1NSMk9TUgAAAAAAAAAAAAAAAAAAAQEBAEgNQgAAAAAAAAAAAAAAAABQZXJpb2RpYwAAAAAAAAAAAAAAAAABAgEASMUDAAAAAAAAAAAAAAAAAElNVQAAAAAAAAAAAAAAAAAAAAAAAAEBAQGBRwAAAAAAAAAAAABfZgAAc2JwAAAAAAAAAAAAAAAAAAAAAAAABQICAvOpAAAAAAAAu5cDAPIBAAA="} +"#.as_bytes(); + + let sbp_msg = { + // JSON to SBP message from payload + let mut iter = json2sbp_iter_msg(json_input); + let from_payload = iter + .next() + .expect("no message found") + .expect("failed to parse message"); + + // JSON to SBP message from fields + let mut iter = iter_messages_from_fields(json_input); + let from_fields = iter + .next() + .expect("no message found") + .expect("failed to parse message"); + + assert_eq!(from_fields, from_payload); + from_fields + }; + match &sbp_msg { + sbp::messages::Sbp::MsgProfilingResourceCounter(msg) => { + let msg_type = msg.message_type().unwrap(); + assert_eq!( + msg_type, 0xcf03, + "Incorrect message type, expected 0xcf03, is {}", + msg_type + ); + let sender_id = msg.sender_id().unwrap(); + assert_eq!( + sender_id, 0x1000, + "incorrect sender id, expected 0x1000, is {sender_id}" + ); + assert_eq!( + msg.buckets[0].cv, 2, + "incorrect value for buckets[0].cv, expected 2, is {}", + msg.buckets[0].cv + ); + assert_eq!( + msg.buckets[0].heap_bytes_alloc, 927480, + "incorrect value for buckets[0].heap_bytes_alloc, expected 927480, is {}", + msg.buckets[0].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[0].heap_bytes_free, 0, + "incorrect value for buckets[0].heap_bytes_free, expected 0, is {}", + msg.buckets[0].heap_bytes_free + ); + assert_eq!( + msg.buckets[0].io, 0, + "incorrect value for buckets[0].io, expected 0, is {}", + msg.buckets[0].io + ); + assert_eq!( + msg.buckets[0].io_read, 0, + "incorrect value for buckets[0].io_read, expected 0, is {}", + msg.buckets[0].io_read + ); + assert_eq!( + msg.buckets[0].io_write, 0, + "incorrect value for buckets[0].io_write, expected 0, is {}", + msg.buckets[0].io_write + ); + assert_eq!( + msg.buckets[0].mutex, 2, + "incorrect value for buckets[0].mutex, expected 2, is {}", + msg.buckets[0].mutex + ); + assert_eq!( + msg.buckets[0].name.as_bytes(), + &[ + 70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, 0, 0, 0, 0, + 0, 0, 0, 0 + ], + "incorrect value for msg.buckets[0].name, expected string '{:?}', is '{:?}'", + &[ + 70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, 0, 0, 0, 0, + 0, 0, 0, 0 + ], + msg.buckets[0].name.as_bytes() + ); + assert_eq!( + msg.buckets[0].thread, 1, + "incorrect value for buckets[0].thread, expected 1, is {}", + msg.buckets[0].thread + ); + assert_eq!( + msg.buckets[1].cv, 1, + "incorrect value for buckets[1].cv, expected 1, is {}", + msg.buckets[1].cv + ); + assert_eq!( + msg.buckets[1].heap_bytes_alloc, 84454, + "incorrect value for buckets[1].heap_bytes_alloc, expected 84454, is {}", + msg.buckets[1].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[1].heap_bytes_free, 0, + "incorrect value for buckets[1].heap_bytes_free, expected 0, is {}", + msg.buckets[1].heap_bytes_free + ); + assert_eq!( + msg.buckets[1].io, 1, + "incorrect value for buckets[1].io, expected 1, is {}", + msg.buckets[1].io + ); + assert_eq!( + msg.buckets[1].io_read, 19520, + "incorrect value for buckets[1].io_read, expected 19520, is {}", + msg.buckets[1].io_read + ); + assert_eq!( + msg.buckets[1].io_write, 879, + "incorrect value for buckets[1].io_write, expected 879, is {}", + msg.buckets[1].io_write + ); + assert_eq!( + msg.buckets[1].mutex, 1, + "incorrect value for buckets[1].mutex, expected 1, is {}", + msg.buckets[1].mutex + ); + assert_eq!( + msg.buckets[1].name.as_bytes(), + &[ + 78, 84, 82, 73, 80, 32, 99, 108, 105, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, + 0, 0 + ], + "incorrect value for msg.buckets[1].name, expected string '{:?}', is '{:?}'", + &[ + 78, 84, 82, 73, 80, 32, 99, 108, 105, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, + 0, 0 + ], + msg.buckets[1].name.as_bytes() + ); + assert_eq!( + msg.buckets[1].thread, 1, + "incorrect value for buckets[1].thread, expected 1, is {}", + msg.buckets[1].thread + ); + assert_eq!( + msg.buckets[2].cv, 1, + "incorrect value for buckets[2].cv, expected 1, is {}", + msg.buckets[2].cv + ); + assert_eq!( + msg.buckets[2].heap_bytes_alloc, 4328776, + "incorrect value for buckets[2].heap_bytes_alloc, expected 4328776, is {}", + msg.buckets[2].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[2].heap_bytes_free, 0, + "incorrect value for buckets[2].heap_bytes_free, expected 0, is {}", + msg.buckets[2].heap_bytes_free + ); + assert_eq!( + msg.buckets[2].io, 0, + "incorrect value for buckets[2].io, expected 0, is {}", + msg.buckets[2].io + ); + assert_eq!( + msg.buckets[2].io_read, 0, + "incorrect value for buckets[2].io_read, expected 0, is {}", + msg.buckets[2].io_read + ); + assert_eq!( + msg.buckets[2].io_write, 0, + "incorrect value for buckets[2].io_write, expected 0, is {}", + msg.buckets[2].io_write + ); + assert_eq!( + msg.buckets[2].mutex, 1, + "incorrect value for buckets[2].mutex, expected 1, is {}", + msg.buckets[2].mutex + ); + assert_eq!( + msg.buckets[2].name.as_bytes(), + &[83, 83, 82, 50, 79, 83, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "incorrect value for msg.buckets[2].name, expected string '{:?}', is '{:?}'", + &[83, 83, 82, 50, 79, 83, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + msg.buckets[2].name.as_bytes() + ); + assert_eq!( + msg.buckets[2].thread, 1, + "incorrect value for buckets[2].thread, expected 1, is {}", + msg.buckets[2].thread + ); + assert_eq!( + msg.buckets[3].cv, 1, + "incorrect value for buckets[3].cv, expected 1, is {}", + msg.buckets[3].cv + ); + assert_eq!( + msg.buckets[3].heap_bytes_alloc, 247112, + "incorrect value for buckets[3].heap_bytes_alloc, expected 247112, is {}", + msg.buckets[3].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[3].heap_bytes_free, 0, + "incorrect value for buckets[3].heap_bytes_free, expected 0, is {}", + msg.buckets[3].heap_bytes_free + ); + assert_eq!( + msg.buckets[3].io, 0, + "incorrect value for buckets[3].io, expected 0, is {}", + msg.buckets[3].io + ); + assert_eq!( + msg.buckets[3].io_read, 0, + "incorrect value for buckets[3].io_read, expected 0, is {}", + msg.buckets[3].io_read + ); + assert_eq!( + msg.buckets[3].io_write, 0, + "incorrect value for buckets[3].io_write, expected 0, is {}", + msg.buckets[3].io_write + ); + assert_eq!( + msg.buckets[3].mutex, 2, + "incorrect value for buckets[3].mutex, expected 2, is {}", + msg.buckets[3].mutex + ); + assert_eq!( + msg.buckets[3].name.as_bytes(), + &[80, 101, 114, 105, 111, 100, 105, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "incorrect value for msg.buckets[3].name, expected string '{:?}', is '{:?}'", + &[80, 101, 114, 105, 111, 100, 105, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + msg.buckets[3].name.as_bytes() + ); + assert_eq!( + msg.buckets[3].thread, 1, + "incorrect value for buckets[3].thread, expected 1, is {}", + msg.buckets[3].thread + ); + assert_eq!( + msg.buckets[4].cv, 1, + "incorrect value for buckets[4].cv, expected 1, is {}", + msg.buckets[4].cv + ); + assert_eq!( + msg.buckets[4].heap_bytes_alloc, 18305, + "incorrect value for buckets[4].heap_bytes_alloc, expected 18305, is {}", + msg.buckets[4].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[4].heap_bytes_free, 0, + "incorrect value for buckets[4].heap_bytes_free, expected 0, is {}", + msg.buckets[4].heap_bytes_free + ); + assert_eq!( + msg.buckets[4].io, 1, + "incorrect value for buckets[4].io, expected 1, is {}", + msg.buckets[4].io + ); + assert_eq!( + msg.buckets[4].io_read, 26207, + "incorrect value for buckets[4].io_read, expected 26207, is {}", + msg.buckets[4].io_read + ); + assert_eq!( + msg.buckets[4].io_write, 0, + "incorrect value for buckets[4].io_write, expected 0, is {}", + msg.buckets[4].io_write + ); + assert_eq!( + msg.buckets[4].mutex, 1, + "incorrect value for buckets[4].mutex, expected 1, is {}", + msg.buckets[4].mutex + ); + assert_eq!( + msg.buckets[4].name.as_bytes(), + &[73, 77, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "incorrect value for msg.buckets[4].name, expected string '{:?}', is '{:?}'", + &[73, 77, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + msg.buckets[4].name.as_bytes() + ); + assert_eq!( + msg.buckets[4].thread, 1, + "incorrect value for buckets[4].thread, expected 1, is {}", + msg.buckets[4].thread + ); + assert_eq!( + msg.buckets[5].cv, 2, + "incorrect value for buckets[5].cv, expected 2, is {}", + msg.buckets[5].cv + ); + assert_eq!( + msg.buckets[5].heap_bytes_alloc, 43507, + "incorrect value for buckets[5].heap_bytes_alloc, expected 43507, is {}", + msg.buckets[5].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[5].heap_bytes_free, 0, + "incorrect value for buckets[5].heap_bytes_free, expected 0, is {}", + msg.buckets[5].heap_bytes_free + ); + assert_eq!( + msg.buckets[5].io, 2, + "incorrect value for buckets[5].io, expected 2, is {}", + msg.buckets[5].io + ); + assert_eq!( + msg.buckets[5].io_read, 498, + "incorrect value for buckets[5].io_read, expected 498, is {}", + msg.buckets[5].io_read + ); + assert_eq!( + msg.buckets[5].io_write, 235451, + "incorrect value for buckets[5].io_write, expected 235451, is {}", + msg.buckets[5].io_write + ); + assert_eq!( + msg.buckets[5].mutex, 2, + "incorrect value for buckets[5].mutex, expected 2, is {}", + msg.buckets[5].mutex + ); + assert_eq!( + msg.buckets[5].name.as_bytes(), + &[115, 98, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "incorrect value for msg.buckets[5].name, expected string '{:?}', is '{:?}'", + &[115, 98, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + msg.buckets[5].name.as_bytes() + ); + assert_eq!( + msg.buckets[5].thread, 5, + "incorrect value for buckets[5].thread, expected 5, is {}", + msg.buckets[5].thread + ); + assert_eq!( + msg.seq_len, 3, + "incorrect value for seq_len, expected 3, is {}", + msg.seq_len + ); + assert_eq!( + msg.seq_no, 1, + "incorrect value for seq_no, expected 1, is {}", + msg.seq_no + ); + } + _ => panic!("Invalid message type! Expected a MsgProfilingResourceCounter"), + }; + } +} + +/// Tests [`sbp::json::JsonEncoder`] for roundtrip SBP message -> JSON +/// +/// Assumes: +/// - [`self::test_auto_check_sbp_profiling_msg_profiling_resource_counter`] passes +/// +/// Asserts: +/// - SBP fields equates to that of the field +/// - Payload is identical +#[test] +#[cfg(feature = "json")] +fn test_sbp2json_auto_check_sbp_profiling_msg_profiling_resource_counter() { + { + let mut payload = Cursor::new(vec![ + 85, 3, 207, 0, 16, 248, 1, 3, 70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, + 101, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 248, 38, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 78, 84, 82, 73, 80, 32, 99, 108, 105, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 230, 73, 1, 0, 0, 0, 0, 0, 111, 3, 0, 0, 64, 76, 0, 0, 83, 83, 82, 50, 79, + 83, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 72, 13, 66, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 101, 114, 105, 111, 100, 105, 99, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 72, 197, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, + 77, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 129, 71, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 102, 0, 0, 115, 98, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 2, 2, 2, 243, 169, 0, 0, 0, 0, 0, 0, 187, 151, 3, 0, 242, 1, + 0, 0, 181, 153, + ]); + + // Construct sbp message + let sbp_msg = { + let mut msgs = iter_messages(&mut payload); + msgs.next() + .expect("no message found") + .expect("failed to parse message") + }; + + let mut json_buffer = vec![]; + // Populate json buffer, CompactFormatter + sbp::json::JsonEncoder::new(&mut json_buffer, sbp::json::CompactFormatter {}) + .send(&sbp_msg) + .unwrap(); + + // Reconstruct Sbp message from json fields, roundtrip + let sbp_msg = sbp::messages::Sbp::MsgProfilingResourceCounter( + serde_json::from_str( + std::str::from_utf8(json_buffer.as_slice()) + .unwrap() + .to_string() + .as_str(), + ) + .unwrap(), + ); + match &sbp_msg { + sbp::messages::Sbp::MsgProfilingResourceCounter(msg) => { + let msg_type = msg.message_type().unwrap(); + assert_eq!( + msg_type, 0xcf03, + "Incorrect message type, expected 0xcf03, is {}", + msg_type + ); + let sender_id = msg.sender_id().unwrap(); + assert_eq!( + sender_id, 0x1000, + "incorrect sender id, expected 0x1000, is {sender_id}" + ); + assert_eq!( + msg.buckets[0].cv, 2, + "incorrect value for buckets[0].cv, expected 2, is {}", + msg.buckets[0].cv + ); + assert_eq!( + msg.buckets[0].heap_bytes_alloc, 927480, + "incorrect value for buckets[0].heap_bytes_alloc, expected 927480, is {}", + msg.buckets[0].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[0].heap_bytes_free, 0, + "incorrect value for buckets[0].heap_bytes_free, expected 0, is {}", + msg.buckets[0].heap_bytes_free + ); + assert_eq!( + msg.buckets[0].io, 0, + "incorrect value for buckets[0].io, expected 0, is {}", + msg.buckets[0].io + ); + assert_eq!( + msg.buckets[0].io_read, 0, + "incorrect value for buckets[0].io_read, expected 0, is {}", + msg.buckets[0].io_read + ); + assert_eq!( + msg.buckets[0].io_write, 0, + "incorrect value for buckets[0].io_write, expected 0, is {}", + msg.buckets[0].io_write + ); + assert_eq!( + msg.buckets[0].mutex, 2, + "incorrect value for buckets[0].mutex, expected 2, is {}", + msg.buckets[0].mutex + ); + assert_eq!( + msg.buckets[0].name.as_bytes(), + &[ + 70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, 0, 0, 0, 0, + 0, 0, 0, 0 + ], + "incorrect value for msg.buckets[0].name, expected string '{:?}', is '{:?}'", + &[ + 70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, 0, 0, 0, 0, + 0, 0, 0, 0 + ], + msg.buckets[0].name.as_bytes() + ); + assert_eq!( + msg.buckets[0].thread, 1, + "incorrect value for buckets[0].thread, expected 1, is {}", + msg.buckets[0].thread + ); + assert_eq!( + msg.buckets[1].cv, 1, + "incorrect value for buckets[1].cv, expected 1, is {}", + msg.buckets[1].cv + ); + assert_eq!( + msg.buckets[1].heap_bytes_alloc, 84454, + "incorrect value for buckets[1].heap_bytes_alloc, expected 84454, is {}", + msg.buckets[1].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[1].heap_bytes_free, 0, + "incorrect value for buckets[1].heap_bytes_free, expected 0, is {}", + msg.buckets[1].heap_bytes_free + ); + assert_eq!( + msg.buckets[1].io, 1, + "incorrect value for buckets[1].io, expected 1, is {}", + msg.buckets[1].io + ); + assert_eq!( + msg.buckets[1].io_read, 19520, + "incorrect value for buckets[1].io_read, expected 19520, is {}", + msg.buckets[1].io_read + ); + assert_eq!( + msg.buckets[1].io_write, 879, + "incorrect value for buckets[1].io_write, expected 879, is {}", + msg.buckets[1].io_write + ); + assert_eq!( + msg.buckets[1].mutex, 1, + "incorrect value for buckets[1].mutex, expected 1, is {}", + msg.buckets[1].mutex + ); + assert_eq!( + msg.buckets[1].name.as_bytes(), + &[ + 78, 84, 82, 73, 80, 32, 99, 108, 105, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, + 0, 0 + ], + "incorrect value for msg.buckets[1].name, expected string '{:?}', is '{:?}'", + &[ + 78, 84, 82, 73, 80, 32, 99, 108, 105, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, + 0, 0 + ], + msg.buckets[1].name.as_bytes() + ); + assert_eq!( + msg.buckets[1].thread, 1, + "incorrect value for buckets[1].thread, expected 1, is {}", + msg.buckets[1].thread + ); + assert_eq!( + msg.buckets[2].cv, 1, + "incorrect value for buckets[2].cv, expected 1, is {}", + msg.buckets[2].cv + ); + assert_eq!( + msg.buckets[2].heap_bytes_alloc, 4328776, + "incorrect value for buckets[2].heap_bytes_alloc, expected 4328776, is {}", + msg.buckets[2].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[2].heap_bytes_free, 0, + "incorrect value for buckets[2].heap_bytes_free, expected 0, is {}", + msg.buckets[2].heap_bytes_free + ); + assert_eq!( + msg.buckets[2].io, 0, + "incorrect value for buckets[2].io, expected 0, is {}", + msg.buckets[2].io + ); + assert_eq!( + msg.buckets[2].io_read, 0, + "incorrect value for buckets[2].io_read, expected 0, is {}", + msg.buckets[2].io_read + ); + assert_eq!( + msg.buckets[2].io_write, 0, + "incorrect value for buckets[2].io_write, expected 0, is {}", + msg.buckets[2].io_write + ); + assert_eq!( + msg.buckets[2].mutex, 1, + "incorrect value for buckets[2].mutex, expected 1, is {}", + msg.buckets[2].mutex + ); + assert_eq!( + msg.buckets[2].name.as_bytes(), + &[83, 83, 82, 50, 79, 83, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "incorrect value for msg.buckets[2].name, expected string '{:?}', is '{:?}'", + &[83, 83, 82, 50, 79, 83, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + msg.buckets[2].name.as_bytes() + ); + assert_eq!( + msg.buckets[2].thread, 1, + "incorrect value for buckets[2].thread, expected 1, is {}", + msg.buckets[2].thread + ); + assert_eq!( + msg.buckets[3].cv, 1, + "incorrect value for buckets[3].cv, expected 1, is {}", + msg.buckets[3].cv + ); + assert_eq!( + msg.buckets[3].heap_bytes_alloc, 247112, + "incorrect value for buckets[3].heap_bytes_alloc, expected 247112, is {}", + msg.buckets[3].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[3].heap_bytes_free, 0, + "incorrect value for buckets[3].heap_bytes_free, expected 0, is {}", + msg.buckets[3].heap_bytes_free + ); + assert_eq!( + msg.buckets[3].io, 0, + "incorrect value for buckets[3].io, expected 0, is {}", + msg.buckets[3].io + ); + assert_eq!( + msg.buckets[3].io_read, 0, + "incorrect value for buckets[3].io_read, expected 0, is {}", + msg.buckets[3].io_read + ); + assert_eq!( + msg.buckets[3].io_write, 0, + "incorrect value for buckets[3].io_write, expected 0, is {}", + msg.buckets[3].io_write + ); + assert_eq!( + msg.buckets[3].mutex, 2, + "incorrect value for buckets[3].mutex, expected 2, is {}", + msg.buckets[3].mutex + ); + assert_eq!( + msg.buckets[3].name.as_bytes(), + &[80, 101, 114, 105, 111, 100, 105, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "incorrect value for msg.buckets[3].name, expected string '{:?}', is '{:?}'", + &[80, 101, 114, 105, 111, 100, 105, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + msg.buckets[3].name.as_bytes() + ); + assert_eq!( + msg.buckets[3].thread, 1, + "incorrect value for buckets[3].thread, expected 1, is {}", + msg.buckets[3].thread + ); + assert_eq!( + msg.buckets[4].cv, 1, + "incorrect value for buckets[4].cv, expected 1, is {}", + msg.buckets[4].cv + ); + assert_eq!( + msg.buckets[4].heap_bytes_alloc, 18305, + "incorrect value for buckets[4].heap_bytes_alloc, expected 18305, is {}", + msg.buckets[4].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[4].heap_bytes_free, 0, + "incorrect value for buckets[4].heap_bytes_free, expected 0, is {}", + msg.buckets[4].heap_bytes_free + ); + assert_eq!( + msg.buckets[4].io, 1, + "incorrect value for buckets[4].io, expected 1, is {}", + msg.buckets[4].io + ); + assert_eq!( + msg.buckets[4].io_read, 26207, + "incorrect value for buckets[4].io_read, expected 26207, is {}", + msg.buckets[4].io_read + ); + assert_eq!( + msg.buckets[4].io_write, 0, + "incorrect value for buckets[4].io_write, expected 0, is {}", + msg.buckets[4].io_write + ); + assert_eq!( + msg.buckets[4].mutex, 1, + "incorrect value for buckets[4].mutex, expected 1, is {}", + msg.buckets[4].mutex + ); + assert_eq!( + msg.buckets[4].name.as_bytes(), + &[73, 77, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "incorrect value for msg.buckets[4].name, expected string '{:?}', is '{:?}'", + &[73, 77, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + msg.buckets[4].name.as_bytes() + ); + assert_eq!( + msg.buckets[4].thread, 1, + "incorrect value for buckets[4].thread, expected 1, is {}", + msg.buckets[4].thread + ); + assert_eq!( + msg.buckets[5].cv, 2, + "incorrect value for buckets[5].cv, expected 2, is {}", + msg.buckets[5].cv + ); + assert_eq!( + msg.buckets[5].heap_bytes_alloc, 43507, + "incorrect value for buckets[5].heap_bytes_alloc, expected 43507, is {}", + msg.buckets[5].heap_bytes_alloc + ); + assert_eq!( + msg.buckets[5].heap_bytes_free, 0, + "incorrect value for buckets[5].heap_bytes_free, expected 0, is {}", + msg.buckets[5].heap_bytes_free + ); + assert_eq!( + msg.buckets[5].io, 2, + "incorrect value for buckets[5].io, expected 2, is {}", + msg.buckets[5].io + ); + assert_eq!( + msg.buckets[5].io_read, 498, + "incorrect value for buckets[5].io_read, expected 498, is {}", + msg.buckets[5].io_read + ); + assert_eq!( + msg.buckets[5].io_write, 235451, + "incorrect value for buckets[5].io_write, expected 235451, is {}", + msg.buckets[5].io_write + ); + assert_eq!( + msg.buckets[5].mutex, 2, + "incorrect value for buckets[5].mutex, expected 2, is {}", + msg.buckets[5].mutex + ); + assert_eq!( + msg.buckets[5].name.as_bytes(), + &[115, 98, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "incorrect value for msg.buckets[5].name, expected string '{:?}', is '{:?}'", + &[115, 98, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + msg.buckets[5].name.as_bytes() + ); + assert_eq!( + msg.buckets[5].thread, 5, + "incorrect value for buckets[5].thread, expected 5, is {}", + msg.buckets[5].thread + ); + assert_eq!( + msg.seq_len, 3, + "incorrect value for seq_len, expected 3, is {}", + msg.seq_len + ); + assert_eq!( + msg.seq_no, 1, + "incorrect value for seq_no, expected 1, is {}", + msg.seq_no + ); + } + _ => panic!("Invalid message type! Expected a MsgProfilingResourceCounter"), + }; + + // Check payload is still identical + let frame = sbp::to_vec(&sbp_msg).unwrap(); + assert_eq!(frame, payload.into_inner()); + } +} diff --git a/rust/sbp/tests/integration/auto_check_sbp_profiling_msg_profiling_system_info.rs b/rust/sbp/tests/integration/auto_check_sbp_profiling_msg_profiling_system_info.rs new file mode 100644 index 0000000000..46be0173a5 --- /dev/null +++ b/rust/sbp/tests/integration/auto_check_sbp_profiling_msg_profiling_system_info.rs @@ -0,0 +1,230 @@ +// +// Copyright (C) 2019-2021 Swift Navigation Inc. +// Contact: https://support.swiftnav.com +// +// This source is subject to the license found in the file 'LICENSE' which must +// be be distributed together with this source. All other rights reserved. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + +// This file was auto-generated from spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingSystemInfo.yaml by generate.py. Do not modify by hand! + +use crate::*; + +/// Tests [`sbp::iter_messages`], from payload into SBP messages +/// +/// Asserts: +/// - SBP fields equates to that of the field +/// - Payload is identical +#[test] +fn test_auto_check_sbp_profiling_msg_profiling_system_info() { + { + let mut payload = Cursor::new(vec![ + 85, 1, 207, 0, 16, 21, 98, 40, 52, 0, 0, 0, 0, 0, 114, 12, 157, 0, 0, 0, 0, 0, 27, 72, + 195, 226, 0, 252, 65, + ]); + + // Test the round trip payload parsing + let sbp_msg = { + let mut msgs = iter_messages(&mut payload); + msgs.next() + .expect("no message found") + .expect("failed to parse message") + }; + match &sbp_msg { + sbp::messages::Sbp::MsgProfilingSystemInfo(msg) => { + let msg_type = msg.message_type().unwrap(); + assert_eq!( + msg_type, 0xcf01, + "Incorrect message type, expected 0xcf01, is {}", + msg_type + ); + let sender_id = msg.sender_id().unwrap(); + assert_eq!( + sender_id, 0x1000, + "incorrect sender id, expected 0x1000, is {sender_id}" + ); + assert_eq!( + msg.age, 10292338, + "incorrect value for age, expected 10292338, is {}", + msg.age + ); + assert_eq!( + msg.heap_usage, 14861128, + "incorrect value for heap_usage, expected 14861128, is {}", + msg.heap_usage + ); + assert_eq!( + msg.n_threads, 27, + "incorrect value for n_threads, expected 27, is {}", + msg.n_threads + ); + assert_eq!( + msg.total_cpu_time, 3418210, + "incorrect value for total_cpu_time, expected 3418210, is {}", + msg.total_cpu_time + ); + } + _ => panic!("Invalid message type! Expected a MsgProfilingSystemInfo"), + }; + let frame = sbp::to_vec(&sbp_msg).unwrap(); + assert_eq!(frame, payload.into_inner()); + } +} + +/// Tests [`sbp::json::iter_messages`] for JSON payload -> SBP message +/// and [`sbp::json::iter_messages_from_fields`] for JSON fields -> SBP message. +/// +/// Asserts: +/// - SBP message constructed via payload is identical to from fields +/// - SBP fields equates to that of the field +/// - Payload is identical +#[test] +#[cfg(feature = "json")] +fn test_json2sbp_auto_check_sbp_profiling_msg_profiling_system_info() { + { + let json_input = r#"{"crc": 16892, "preamble": 85, "sender": 4096, "length": 21, "msg_type": 52993, "total_cpu_time": 3418210, "age": 10292338, "n_threads": 27, "heap_usage": 14861128, "payload": "Yig0AAAAAAByDJ0AAAAAABtIw+IA"} +"#.as_bytes(); + + let sbp_msg = { + // JSON to SBP message from payload + let mut iter = json2sbp_iter_msg(json_input); + let from_payload = iter + .next() + .expect("no message found") + .expect("failed to parse message"); + + // JSON to SBP message from fields + let mut iter = iter_messages_from_fields(json_input); + let from_fields = iter + .next() + .expect("no message found") + .expect("failed to parse message"); + + assert_eq!(from_fields, from_payload); + from_fields + }; + match &sbp_msg { + sbp::messages::Sbp::MsgProfilingSystemInfo(msg) => { + let msg_type = msg.message_type().unwrap(); + assert_eq!( + msg_type, 0xcf01, + "Incorrect message type, expected 0xcf01, is {}", + msg_type + ); + let sender_id = msg.sender_id().unwrap(); + assert_eq!( + sender_id, 0x1000, + "incorrect sender id, expected 0x1000, is {sender_id}" + ); + assert_eq!( + msg.age, 10292338, + "incorrect value for age, expected 10292338, is {}", + msg.age + ); + assert_eq!( + msg.heap_usage, 14861128, + "incorrect value for heap_usage, expected 14861128, is {}", + msg.heap_usage + ); + assert_eq!( + msg.n_threads, 27, + "incorrect value for n_threads, expected 27, is {}", + msg.n_threads + ); + assert_eq!( + msg.total_cpu_time, 3418210, + "incorrect value for total_cpu_time, expected 3418210, is {}", + msg.total_cpu_time + ); + } + _ => panic!("Invalid message type! Expected a MsgProfilingSystemInfo"), + }; + } +} + +/// Tests [`sbp::json::JsonEncoder`] for roundtrip SBP message -> JSON +/// +/// Assumes: +/// - [`self::test_auto_check_sbp_profiling_msg_profiling_system_info`] passes +/// +/// Asserts: +/// - SBP fields equates to that of the field +/// - Payload is identical +#[test] +#[cfg(feature = "json")] +fn test_sbp2json_auto_check_sbp_profiling_msg_profiling_system_info() { + { + let mut payload = Cursor::new(vec![ + 85, 1, 207, 0, 16, 21, 98, 40, 52, 0, 0, 0, 0, 0, 114, 12, 157, 0, 0, 0, 0, 0, 27, 72, + 195, 226, 0, 252, 65, + ]); + + // Construct sbp message + let sbp_msg = { + let mut msgs = iter_messages(&mut payload); + msgs.next() + .expect("no message found") + .expect("failed to parse message") + }; + + let mut json_buffer = vec![]; + // Populate json buffer, CompactFormatter + sbp::json::JsonEncoder::new(&mut json_buffer, sbp::json::CompactFormatter {}) + .send(&sbp_msg) + .unwrap(); + + // Reconstruct Sbp message from json fields, roundtrip + let sbp_msg = sbp::messages::Sbp::MsgProfilingSystemInfo( + serde_json::from_str( + std::str::from_utf8(json_buffer.as_slice()) + .unwrap() + .to_string() + .as_str(), + ) + .unwrap(), + ); + match &sbp_msg { + sbp::messages::Sbp::MsgProfilingSystemInfo(msg) => { + let msg_type = msg.message_type().unwrap(); + assert_eq!( + msg_type, 0xcf01, + "Incorrect message type, expected 0xcf01, is {}", + msg_type + ); + let sender_id = msg.sender_id().unwrap(); + assert_eq!( + sender_id, 0x1000, + "incorrect sender id, expected 0x1000, is {sender_id}" + ); + assert_eq!( + msg.age, 10292338, + "incorrect value for age, expected 10292338, is {}", + msg.age + ); + assert_eq!( + msg.heap_usage, 14861128, + "incorrect value for heap_usage, expected 14861128, is {}", + msg.heap_usage + ); + assert_eq!( + msg.n_threads, 27, + "incorrect value for n_threads, expected 27, is {}", + msg.n_threads + ); + assert_eq!( + msg.total_cpu_time, 3418210, + "incorrect value for total_cpu_time, expected 3418210, is {}", + msg.total_cpu_time + ); + } + _ => panic!("Invalid message type! Expected a MsgProfilingSystemInfo"), + }; + + // Check payload is still identical + let frame = sbp::to_vec(&sbp_msg).unwrap(); + assert_eq!(frame, payload.into_inner()); + } +} diff --git a/rust/sbp/tests/integration/auto_check_sbp_profiling_msg_profiling_thread_info.rs b/rust/sbp/tests/integration/auto_check_sbp_profiling_msg_profiling_thread_info.rs new file mode 100644 index 0000000000..019aa7426c --- /dev/null +++ b/rust/sbp/tests/integration/auto_check_sbp_profiling_msg_profiling_thread_info.rs @@ -0,0 +1,268 @@ +// +// Copyright (C) 2019-2021 Swift Navigation Inc. +// Contact: https://support.swiftnav.com +// +// This source is subject to the license found in the file 'LICENSE' which must +// be be distributed together with this source. All other rights reserved. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + +// This file was auto-generated from spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingThreadInfo.yaml by generate.py. Do not modify by hand! + +use crate::*; + +/// Tests [`sbp::iter_messages`], from payload into SBP messages +/// +/// Asserts: +/// - SBP fields equates to that of the field +/// - Payload is identical +#[test] +fn test_auto_check_sbp_profiling_msg_profiling_thread_info() { + { + let mut payload = Cursor::new(vec![ + 85, 2, 207, 0, 16, 39, 119, 91, 10, 0, 0, 0, 0, 0, 110, 5, 155, 0, 0, 0, 0, 0, 1, 0, 0, + 128, 0, 208, 53, 4, 0, 70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, + 0, 242, 170, + ]); + + // Test the round trip payload parsing + let sbp_msg = { + let mut msgs = iter_messages(&mut payload); + msgs.next() + .expect("no message found") + .expect("failed to parse message") + }; + match &sbp_msg { + sbp::messages::Sbp::MsgProfilingThreadInfo(msg) => { + let msg_type = msg.message_type().unwrap(); + assert_eq!( + msg_type, 0xcf02, + "Incorrect message type, expected 0xcf02, is {}", + msg_type + ); + let sender_id = msg.sender_id().unwrap(); + assert_eq!( + sender_id, 0x1000, + "incorrect sender id, expected 0x1000, is {sender_id}" + ); + assert_eq!( + msg.age, 10159470, + "incorrect value for age, expected 10159470, is {}", + msg.age + ); + assert_eq!( + msg.name.as_bytes(), + &[70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, 0], + "incorrect value for msg.name, expected string '{:?}', is '{:?}'", + &[70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, 0], + msg.name.as_bytes() + ); + assert_eq!( + msg.stack_size, 8388608, + "incorrect value for stack_size, expected 8388608, is {}", + msg.stack_size + ); + assert_eq!( + msg.stack_usage, 275920, + "incorrect value for stack_usage, expected 275920, is {}", + msg.stack_usage + ); + assert_eq!( + msg.state, 1, + "incorrect value for state, expected 1, is {}", + msg.state + ); + assert_eq!( + msg.total_cpu_time, 678775, + "incorrect value for total_cpu_time, expected 678775, is {}", + msg.total_cpu_time + ); + } + _ => panic!("Invalid message type! Expected a MsgProfilingThreadInfo"), + }; + let frame = sbp::to_vec(&sbp_msg).unwrap(); + assert_eq!(frame, payload.into_inner()); + } +} + +/// Tests [`sbp::json::iter_messages`] for JSON payload -> SBP message +/// and [`sbp::json::iter_messages_from_fields`] for JSON fields -> SBP message. +/// +/// Asserts: +/// - SBP message constructed via payload is identical to from fields +/// - SBP fields equates to that of the field +/// - Payload is identical +#[test] +#[cfg(feature = "json")] +fn test_json2sbp_auto_check_sbp_profiling_msg_profiling_thread_info() { + { + let json_input = r#"{"crc": 43762, "preamble": 85, "sender": 4096, "length": 39, "msg_type": 52994, "total_cpu_time": 678775, "age": 10159470, "state": 1, "stack_size": 8388608, "stack_usage": 275920, "name": "Fusion engine\u0000", "payload": "d1sKAAAAAABuBZsAAAAAAAEAAIAA0DUEAEZ1c2lvbiBlbmdpbmUA"} +"#.as_bytes(); + + let sbp_msg = { + // JSON to SBP message from payload + let mut iter = json2sbp_iter_msg(json_input); + let from_payload = iter + .next() + .expect("no message found") + .expect("failed to parse message"); + + // JSON to SBP message from fields + let mut iter = iter_messages_from_fields(json_input); + let from_fields = iter + .next() + .expect("no message found") + .expect("failed to parse message"); + + assert_eq!(from_fields, from_payload); + from_fields + }; + match &sbp_msg { + sbp::messages::Sbp::MsgProfilingThreadInfo(msg) => { + let msg_type = msg.message_type().unwrap(); + assert_eq!( + msg_type, 0xcf02, + "Incorrect message type, expected 0xcf02, is {}", + msg_type + ); + let sender_id = msg.sender_id().unwrap(); + assert_eq!( + sender_id, 0x1000, + "incorrect sender id, expected 0x1000, is {sender_id}" + ); + assert_eq!( + msg.age, 10159470, + "incorrect value for age, expected 10159470, is {}", + msg.age + ); + assert_eq!( + msg.name.as_bytes(), + &[70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, 0], + "incorrect value for msg.name, expected string '{:?}', is '{:?}'", + &[70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, 0], + msg.name.as_bytes() + ); + assert_eq!( + msg.stack_size, 8388608, + "incorrect value for stack_size, expected 8388608, is {}", + msg.stack_size + ); + assert_eq!( + msg.stack_usage, 275920, + "incorrect value for stack_usage, expected 275920, is {}", + msg.stack_usage + ); + assert_eq!( + msg.state, 1, + "incorrect value for state, expected 1, is {}", + msg.state + ); + assert_eq!( + msg.total_cpu_time, 678775, + "incorrect value for total_cpu_time, expected 678775, is {}", + msg.total_cpu_time + ); + } + _ => panic!("Invalid message type! Expected a MsgProfilingThreadInfo"), + }; + } +} + +/// Tests [`sbp::json::JsonEncoder`] for roundtrip SBP message -> JSON +/// +/// Assumes: +/// - [`self::test_auto_check_sbp_profiling_msg_profiling_thread_info`] passes +/// +/// Asserts: +/// - SBP fields equates to that of the field +/// - Payload is identical +#[test] +#[cfg(feature = "json")] +fn test_sbp2json_auto_check_sbp_profiling_msg_profiling_thread_info() { + { + let mut payload = Cursor::new(vec![ + 85, 2, 207, 0, 16, 39, 119, 91, 10, 0, 0, 0, 0, 0, 110, 5, 155, 0, 0, 0, 0, 0, 1, 0, 0, + 128, 0, 208, 53, 4, 0, 70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, + 0, 242, 170, + ]); + + // Construct sbp message + let sbp_msg = { + let mut msgs = iter_messages(&mut payload); + msgs.next() + .expect("no message found") + .expect("failed to parse message") + }; + + let mut json_buffer = vec![]; + // Populate json buffer, CompactFormatter + sbp::json::JsonEncoder::new(&mut json_buffer, sbp::json::CompactFormatter {}) + .send(&sbp_msg) + .unwrap(); + + // Reconstruct Sbp message from json fields, roundtrip + let sbp_msg = sbp::messages::Sbp::MsgProfilingThreadInfo( + serde_json::from_str( + std::str::from_utf8(json_buffer.as_slice()) + .unwrap() + .to_string() + .as_str(), + ) + .unwrap(), + ); + match &sbp_msg { + sbp::messages::Sbp::MsgProfilingThreadInfo(msg) => { + let msg_type = msg.message_type().unwrap(); + assert_eq!( + msg_type, 0xcf02, + "Incorrect message type, expected 0xcf02, is {}", + msg_type + ); + let sender_id = msg.sender_id().unwrap(); + assert_eq!( + sender_id, 0x1000, + "incorrect sender id, expected 0x1000, is {sender_id}" + ); + assert_eq!( + msg.age, 10159470, + "incorrect value for age, expected 10159470, is {}", + msg.age + ); + assert_eq!( + msg.name.as_bytes(), + &[70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, 0], + "incorrect value for msg.name, expected string '{:?}', is '{:?}'", + &[70, 117, 115, 105, 111, 110, 32, 101, 110, 103, 105, 110, 101, 0], + msg.name.as_bytes() + ); + assert_eq!( + msg.stack_size, 8388608, + "incorrect value for stack_size, expected 8388608, is {}", + msg.stack_size + ); + assert_eq!( + msg.stack_usage, 275920, + "incorrect value for stack_usage, expected 275920, is {}", + msg.stack_usage + ); + assert_eq!( + msg.state, 1, + "incorrect value for state, expected 1, is {}", + msg.state + ); + assert_eq!( + msg.total_cpu_time, 678775, + "incorrect value for total_cpu_time, expected 678775, is {}", + msg.total_cpu_time + ); + } + _ => panic!("Invalid message type! Expected a MsgProfilingThreadInfo"), + }; + + // Check payload is still identical + let frame = sbp::to_vec(&sbp_msg).unwrap(); + assert_eq!(frame, payload.into_inner()); + } +} diff --git a/rust/sbp/tests/integration/main.rs b/rust/sbp/tests/integration/main.rs index c2d30cb5d6..ea7b11878c 100644 --- a/rust/sbp/tests/integration/main.rs +++ b/rust/sbp/tests/integration/main.rs @@ -12,6 +12,7 @@ // This file was auto-generated. Do not modify by hand! #![allow(clippy::excessive_precision)] +#![allow(clippy::legacy_numeric_constants)] mod auto_check_sbp_acquisition_msg_acq_result; mod auto_check_sbp_acquisition_msg_acq_result_dep_a; mod auto_check_sbp_acquisition_msg_acq_result_dep_b; @@ -176,6 +177,9 @@ mod auto_check_sbp_piksi_msg_thread_state; mod auto_check_sbp_piksi_msg_uart_state; mod auto_check_sbp_piksi_msg_uart_state_dep_a; mod auto_check_sbp_profiling_msg_measurement_point; +mod auto_check_sbp_profiling_msg_profiling_resource_counter; +mod auto_check_sbp_profiling_msg_profiling_system_info; +mod auto_check_sbp_profiling_msg_profiling_thread_info; mod auto_check_sbp_sbas_msg_sbas_raw; mod auto_check_sbp_settings_msg_settings_read_by_index_done; mod auto_check_sbp_settings_msg_settings_read_by_index_req; diff --git a/sbpjson/elm/SbpJson.elm b/sbpjson/elm/SbpJson.elm index db6b665b0b..b0de21236d 100644 --- a/sbpjson/elm/SbpJson.elm +++ b/sbpjson/elm/SbpJson.elm @@ -5,7 +5,7 @@ -- add these imports -- -- import Json.Decode exposing (decodeString)`); --- import SbpJson exposing (acqSvProfile, almanacCommonContent, boundsHeader, carrierPhase, codeBiasesContent, codePhaseBiasesSatSig, doppler, ecdsaSignature, ephemerisCommonContent, estimatedHorizontalErrorEllipse, gnssInputType, gnssCapb, gnssSignal, gpsTime, gpsTimeSEC, gridElement, gridElementNoStd, griddedCorrectionHeader, imuInputType, integritySSRHeader, latency, measurementState, msgAcknowledge, msgAcqResult, msgAcqSvProfile, msgAgeCorrections, msgAlmanac, msgAlmanacGPS, msgAlmanacGlo, msgAngularRate, msgBasePosECEF, msgBasePosLLH, msgBaselineECEF, msgBaselineHeading, msgBaselineNED, msgBootloaderHandshakeReq, msgBootloaderHandshakeResp, msgBootloaderJumpToApp, msgCellModemStatus, msgCertificateChain, msgCommandOutput, msgCommandReq, msgCommandResp, msgCsacTelemetry, msgCsacTelemetryLabels, msgCwResults, msgCwStart, msgDeviceMonitor, msgDgnssStatus, msgDops, msgEcdsaCertificate, msgEcdsaSignature, msgEphemerisBds, msgEphemerisGPS, msgEphemerisGal, msgEphemerisGlo, msgEphemerisQzss, msgEphemerisSbas, msgEXTEvent, msgFileioConfigReq, msgFileioConfigResp, msgFileioReadDirReq, msgFileioReadDirResp, msgFileioReadReq, msgFileioReadResp, msgFileioRemove, msgFileioWriteReq, msgFileioWriteResp, msgFlashDone, msgFlashErase, msgFlashProgram, msgFlashReadReq, msgFlashReadResp, msgFrontEndGain, msgFwd, msgGPSTime, msgGPSTimeGnss, msgGloBiases, msgGnssCapb, msgGnssTimeOffset, msgGroupDelay, msgGroupMeta, msgHeartbeat, msgIarState, msgImuAux, msgImuRaw, msgInsStatus, msgInsUpdates, msgIono, msgLinuxCPUState, msgLinuxMemState, msgLinuxProcessFdCount, msgLinuxProcessFdSummary, msgLinuxProcessSocketCounts, msgLinuxProcessSocketQueues, msgLinuxSocketUsage, msgLinuxSysState, msgLog, msgM25FlashWriteStatus, msgMagRaw, msgMaskSatellite, msgMeasurementPoint, msgMeasurementState, msgNapDeviceDnaReq, msgNapDeviceDnaResp, msgNdbEvent, msgNetworkBandwidthUsage, msgNetworkStateReq, msgNetworkStateResp, msgObs, msgOdometry, msgOrientEuler, msgOrientQuat, msgOsr, msgPosECEF, msgPosECEFCov, msgPosECEFCovGnss, msgPosECEFGnss, msgPosLLH, msgPosLLHAcc, msgPosLLHCov, msgPosLLHCovGnss, msgPosLLHGnss, msgPoseRelative, msgPpsTime, msgProtectionLevel, msgReferenceFrameParam, msgReset, msgResetFilters, msgSbasRaw, msgSensorAidEvent, msgSetTime, msgSettingsReadByIndexDone, msgSettingsReadByIndexReq, msgSettingsReadByIndexResp, msgSettingsReadReq, msgSettingsReadResp, msgSettingsRegister, msgSettingsRegisterResp, msgSettingsSave, msgSettingsWrite, msgSettingsWriteResp, msgSolnMeta, msgSpecan, msgSsrCodeBiases, msgSsrCodePhaseBiasesBounds, msgSsrFlagHighLevel, msgSsrFlagIonoGridPointSatLos, msgSsrFlagIonoGridPoints, msgSsrFlagIonoTileSatLos, msgSsrFlagSatellites, msgSsrFlagTropoGridPoints, msgSsrGriddedCorrection, msgSsrGriddedCorrectionBounds, msgSsrOrbitClock, msgSsrOrbitClockBounds, msgSsrOrbitClockBoundsDegradation, msgSsrPhaseBiases, msgSsrSatelliteApc, msgSsrStecCorrection, msgSsrTileDefinition, msgStartup, msgStatusJournal, msgStatusReport, msgStmFlashLockSector, msgStmFlashUnlockSector, msgStmUniqueIDReq, msgStmUniqueIDResp, msgSvAzEl, msgTelSv, msgThreadState, msgTrackingIq, msgTrackingState, msgUARTState, msgUserData, msgUTCLeapSecond, msgUTCTime, msgUTCTimeGnss, msgVelBody, msgVelCog, msgVelECEF, msgVelECEFCov, msgVelECEFCovGnss, msgVelECEFGnss, msgVelNED, msgVelNEDCov, msgVelNEDCovGnss, msgVelNEDGnss, msgWheeltick, networkUsage, observationHeader, odoInputType, orbitClockBound, orbitClockBoundDegradation, packedObsContent, packedOsrContent, period, phaseBiasesContent, stecHeader, stecResidual, stecResidualNoStd, stecSatElement, stecSatElementIntegrity, satelliteAPC, solutionInputType, statusJournalItem, subSystemReport, svAzEl, svID, telemetrySV, trackingChannelCorrelation, trackingChannelState, troposphericDelayCorrection, troposphericDelayCorrectionNoStd, uartChannel, utcTime) +-- import SbpJson exposing (acqSvProfile, almanacCommonContent, boundsHeader, carrierPhase, codeBiasesContent, codePhaseBiasesSatSig, doppler, ecdsaSignature, ephemerisCommonContent, estimatedHorizontalErrorEllipse, gnssInputType, gnssCapb, gnssSignal, gpsTime, gpsTimeSEC, gridElement, gridElementNoStd, griddedCorrectionHeader, imuInputType, integritySSRHeader, latency, measurementState, msgAcknowledge, msgAcqResult, msgAcqSvProfile, msgAgeCorrections, msgAlmanac, msgAlmanacGPS, msgAlmanacGlo, msgAngularRate, msgBasePosECEF, msgBasePosLLH, msgBaselineECEF, msgBaselineHeading, msgBaselineNED, msgBootloaderHandshakeReq, msgBootloaderHandshakeResp, msgBootloaderJumpToApp, msgCellModemStatus, msgCertificateChain, msgCommandOutput, msgCommandReq, msgCommandResp, msgCsacTelemetry, msgCsacTelemetryLabels, msgCwResults, msgCwStart, msgDeviceMonitor, msgDgnssStatus, msgDops, msgEcdsaCertificate, msgEcdsaSignature, msgEphemerisBds, msgEphemerisGPS, msgEphemerisGal, msgEphemerisGlo, msgEphemerisQzss, msgEphemerisSbas, msgEXTEvent, msgFileioConfigReq, msgFileioConfigResp, msgFileioReadDirReq, msgFileioReadDirResp, msgFileioReadReq, msgFileioReadResp, msgFileioRemove, msgFileioWriteReq, msgFileioWriteResp, msgFlashDone, msgFlashErase, msgFlashProgram, msgFlashReadReq, msgFlashReadResp, msgFrontEndGain, msgFwd, msgGPSTime, msgGPSTimeGnss, msgGloBiases, msgGnssCapb, msgGnssTimeOffset, msgGroupDelay, msgGroupMeta, msgHeartbeat, msgIarState, msgImuAux, msgImuRaw, msgInsStatus, msgInsUpdates, msgIono, msgLinuxCPUState, msgLinuxMemState, msgLinuxProcessFdCount, msgLinuxProcessFdSummary, msgLinuxProcessSocketCounts, msgLinuxProcessSocketQueues, msgLinuxSocketUsage, msgLinuxSysState, msgLog, msgM25FlashWriteStatus, msgMagRaw, msgMaskSatellite, msgMeasurementPoint, msgMeasurementState, msgNapDeviceDnaReq, msgNapDeviceDnaResp, msgNdbEvent, msgNetworkBandwidthUsage, msgNetworkStateReq, msgNetworkStateResp, msgObs, msgOdometry, msgOrientEuler, msgOrientQuat, msgOsr, msgPosECEF, msgPosECEFCov, msgPosECEFCovGnss, msgPosECEFGnss, msgPosLLH, msgPosLLHAcc, msgPosLLHCov, msgPosLLHCovGnss, msgPosLLHGnss, msgPoseRelative, msgPpsTime, msgProfilingResourceCounter, msgProfilingSystemInfo, msgProfilingThreadInfo, msgProtectionLevel, msgReferenceFrameParam, msgReset, msgResetFilters, msgSbasRaw, msgSensorAidEvent, msgSetTime, msgSettingsReadByIndexDone, msgSettingsReadByIndexReq, msgSettingsReadByIndexResp, msgSettingsReadReq, msgSettingsReadResp, msgSettingsRegister, msgSettingsRegisterResp, msgSettingsSave, msgSettingsWrite, msgSettingsWriteResp, msgSolnMeta, msgSpecan, msgSsrCodeBiases, msgSsrCodePhaseBiasesBounds, msgSsrFlagHighLevel, msgSsrFlagIonoGridPointSatLos, msgSsrFlagIonoGridPoints, msgSsrFlagIonoTileSatLos, msgSsrFlagSatellites, msgSsrFlagTropoGridPoints, msgSsrGriddedCorrection, msgSsrGriddedCorrectionBounds, msgSsrOrbitClock, msgSsrOrbitClockBounds, msgSsrOrbitClockBoundsDegradation, msgSsrPhaseBiases, msgSsrSatelliteApc, msgSsrStecCorrection, msgSsrTileDefinition, msgStartup, msgStatusJournal, msgStatusReport, msgStmFlashLockSector, msgStmFlashUnlockSector, msgStmUniqueIDReq, msgStmUniqueIDResp, msgSvAzEl, msgTelSv, msgThreadState, msgTrackingIq, msgTrackingState, msgUARTState, msgUserData, msgUTCLeapSecond, msgUTCTime, msgUTCTimeGnss, msgVelBody, msgVelCog, msgVelECEF, msgVelECEFCov, msgVelECEFCovGnss, msgVelECEFGnss, msgVelNED, msgVelNEDCov, msgVelNEDCovGnss, msgVelNEDGnss, msgWheeltick, networkUsage, observationHeader, odoInputType, orbitClockBound, orbitClockBoundDegradation, packedObsContent, packedOsrContent, period, phaseBiasesContent, resourceBucket, stecHeader, stecResidual, stecResidualNoStd, stecSatElement, stecSatElementIntegrity, satelliteAPC, solutionInputType, statusJournalItem, subSystemReport, svAzEl, svID, telemetrySV, trackingChannelCorrelation, trackingChannelState, troposphericDelayCorrection, troposphericDelayCorrectionNoStd, uartChannel, utcTime) -- -- and you're off to the races with -- @@ -134,6 +134,9 @@ -- decodeString msgPosLLHGnss myJsonString -- decodeString msgPoseRelative myJsonString -- decodeString msgPpsTime myJsonString +-- decodeString msgProfilingResourceCounter myJsonString +-- decodeString msgProfilingSystemInfo myJsonString +-- decodeString msgProfilingThreadInfo myJsonString -- decodeString msgProtectionLevel myJsonString -- decodeString msgReferenceFrameParam myJsonString -- decodeString msgReset myJsonString @@ -207,6 +210,7 @@ -- decodeString packedOsrContent myJsonString -- decodeString period myJsonString -- decodeString phaseBiasesContent myJsonString +-- decodeString resourceBucket myJsonString -- decodeString stecHeader myJsonString -- decodeString stecResidual myJsonString -- decodeString stecResidualNoStd myJsonString @@ -602,6 +606,15 @@ module SbpJson exposing , MsgPpsTime , msgPpsTimeToString , msgPpsTime + , MsgProfilingResourceCounter + , msgProfilingResourceCounterToString + , msgProfilingResourceCounter + , MsgProfilingSystemInfo + , msgProfilingSystemInfoToString + , msgProfilingSystemInfo + , MsgProfilingThreadInfo + , msgProfilingThreadInfoToString + , msgProfilingThreadInfo , MsgProtectionLevel , msgProtectionLevelToString , msgProtectionLevel @@ -821,6 +834,9 @@ module SbpJson exposing , PhaseBiasesContent , phaseBiasesContentToString , phaseBiasesContent + , ResourceBucket + , resourceBucketToString + , resourceBucket , STECHeader , stecHeaderToString , stecHeader @@ -2448,6 +2464,54 @@ type alias MsgPpsTime = , time : Int } +{-| Information about resource buckets. Refer to product documentation to understand the +meaning and values in this message. +-} +type alias MsgProfilingResourceCounter = + { buckets : Array ResourceBucket + , seqLen : Int + , seqNo : Int + } + +{-| Information about allocation of various resources grouped by buckets. Refer to product +documentation to understand the meaning and values in this message. +-} +type alias ResourceBucket = + { cv : Int + , heapBytesAlloc : Int + , heapBytesFree : Int + , io : Int + , ioRead : Int + , ioWrite : Int + , mutex : Int + , name : String + , thread : Int + } + +{-| Contains basic information about system resource usage. System is defined in terms of the +source of this message and may vary from sender to sender. Refer to product +documentation to understand the exact scope and meaning of this message. +-} +type alias MsgProfilingSystemInfo = + { age : Int + , heapUsage : Int + , nThreads : Int + , totalCPUTime : Int + } + +{-| Contains profiling information related to a single thread being tracked by the producing +system. Refer to product documentation to understand the exact scope and meaning of this +message. +-} +type alias MsgProfilingThreadInfo = + { age : Int + , name : String + , stackSize : Int + , stackUsage : Int + , state : Int + , totalCPUTime : Int + } + {-| This message reports the protection levels associated to the given state estimate. The full GPS time is given by the preceding MSG_GPS_TIME with the matching time-of-week (tow). -} @@ -3895,6 +3959,15 @@ msgPoseRelativeToString r = Jenc.encode 0 (encodeMsgPoseRelative r) msgPpsTimeToString : MsgPpsTime -> String msgPpsTimeToString r = Jenc.encode 0 (encodeMsgPpsTime r) +msgProfilingResourceCounterToString : MsgProfilingResourceCounter -> String +msgProfilingResourceCounterToString r = Jenc.encode 0 (encodeMsgProfilingResourceCounter r) + +msgProfilingSystemInfoToString : MsgProfilingSystemInfo -> String +msgProfilingSystemInfoToString r = Jenc.encode 0 (encodeMsgProfilingSystemInfo r) + +msgProfilingThreadInfoToString : MsgProfilingThreadInfo -> String +msgProfilingThreadInfoToString r = Jenc.encode 0 (encodeMsgProfilingThreadInfo r) + msgProtectionLevelToString : MsgProtectionLevel -> String msgProtectionLevelToString r = Jenc.encode 0 (encodeMsgProtectionLevel r) @@ -4126,6 +4199,9 @@ periodToString r = Jenc.encode 0 (encodePeriod r) phaseBiasesContentToString : PhaseBiasesContent -> String phaseBiasesContentToString r = Jenc.encode 0 (encodePhaseBiasesContent r) +resourceBucketToString : ResourceBucket -> String +resourceBucketToString r = Jenc.encode 0 (encodeResourceBucket r) + stecHeaderToString : STECHeader -> String stecHeaderToString r = Jenc.encode 0 (encodeSTECHeader r) @@ -6589,6 +6665,86 @@ encodeMsgPpsTime x = , ("time", Jenc.int x.time) ] +msgProfilingResourceCounter : Jdec.Decoder MsgProfilingResourceCounter +msgProfilingResourceCounter = + Jpipe.decode MsgProfilingResourceCounter + |> Jpipe.required "buckets" (Jdec.array resourceBucket) + |> Jpipe.required "seq_len" Jdec.int + |> Jpipe.required "seq_no" Jdec.int + +encodeMsgProfilingResourceCounter : MsgProfilingResourceCounter -> Jenc.Value +encodeMsgProfilingResourceCounter x = + Jenc.object + [ ("buckets", makeArrayEncoder encodeResourceBucket x.buckets) + , ("seq_len", Jenc.int x.seqLen) + , ("seq_no", Jenc.int x.seqNo) + ] + +resourceBucket : Jdec.Decoder ResourceBucket +resourceBucket = + Jpipe.decode ResourceBucket + |> Jpipe.required "cv" Jdec.int + |> Jpipe.required "heap_bytes_alloc" Jdec.int + |> Jpipe.required "heap_bytes_free" Jdec.int + |> Jpipe.required "io" Jdec.int + |> Jpipe.required "io_read" Jdec.int + |> Jpipe.required "io_write" Jdec.int + |> Jpipe.required "mutex" Jdec.int + |> Jpipe.required "name" Jdec.string + |> Jpipe.required "thread" Jdec.int + +encodeResourceBucket : ResourceBucket -> Jenc.Value +encodeResourceBucket x = + Jenc.object + [ ("cv", Jenc.int x.cv) + , ("heap_bytes_alloc", Jenc.int x.heapBytesAlloc) + , ("heap_bytes_free", Jenc.int x.heapBytesFree) + , ("io", Jenc.int x.io) + , ("io_read", Jenc.int x.ioRead) + , ("io_write", Jenc.int x.ioWrite) + , ("mutex", Jenc.int x.mutex) + , ("name", Jenc.string x.name) + , ("thread", Jenc.int x.thread) + ] + +msgProfilingSystemInfo : Jdec.Decoder MsgProfilingSystemInfo +msgProfilingSystemInfo = + Jpipe.decode MsgProfilingSystemInfo + |> Jpipe.required "age" Jdec.int + |> Jpipe.required "heap_usage" Jdec.int + |> Jpipe.required "n_threads" Jdec.int + |> Jpipe.required "total_cpu_time" Jdec.int + +encodeMsgProfilingSystemInfo : MsgProfilingSystemInfo -> Jenc.Value +encodeMsgProfilingSystemInfo x = + Jenc.object + [ ("age", Jenc.int x.age) + , ("heap_usage", Jenc.int x.heapUsage) + , ("n_threads", Jenc.int x.nThreads) + , ("total_cpu_time", Jenc.int x.totalCPUTime) + ] + +msgProfilingThreadInfo : Jdec.Decoder MsgProfilingThreadInfo +msgProfilingThreadInfo = + Jpipe.decode MsgProfilingThreadInfo + |> Jpipe.required "age" Jdec.int + |> Jpipe.required "name" Jdec.string + |> Jpipe.required "stack_size" Jdec.int + |> Jpipe.required "stack_usage" Jdec.int + |> Jpipe.required "state" Jdec.int + |> Jpipe.required "total_cpu_time" Jdec.int + +encodeMsgProfilingThreadInfo : MsgProfilingThreadInfo -> Jenc.Value +encodeMsgProfilingThreadInfo x = + Jenc.object + [ ("age", Jenc.int x.age) + , ("name", Jenc.string x.name) + , ("stack_size", Jenc.int x.stackSize) + , ("stack_usage", Jenc.int x.stackUsage) + , ("state", Jenc.int x.state) + , ("total_cpu_time", Jenc.int x.totalCPUTime) + ] + msgProtectionLevel : Jdec.Decoder MsgProtectionLevel msgProtectionLevel = Jpipe.decode MsgProtectionLevel diff --git a/sbpjson/javascript/SbpJson.js b/sbpjson/javascript/SbpJson.js index fd15b5f96b..cefc2733a2 100644 --- a/sbpjson/javascript/SbpJson.js +++ b/sbpjson/javascript/SbpJson.js @@ -127,6 +127,9 @@ // const msgPosLLHGnss = Convert.toMsgPosLLHGnss(json); // const msgPoseRelative = Convert.toMsgPoseRelative(json); // const msgPpsTime = Convert.toMsgPpsTime(json); +// const msgProfilingResourceCounter = Convert.toMsgProfilingResourceCounter(json); +// const msgProfilingSystemInfo = Convert.toMsgProfilingSystemInfo(json); +// const msgProfilingThreadInfo = Convert.toMsgProfilingThreadInfo(json); // const msgProtectionLevel = Convert.toMsgProtectionLevel(json); // const msgReferenceFrameParam = Convert.toMsgReferenceFrameParam(json); // const msgReset = Convert.toMsgReset(json); @@ -200,6 +203,7 @@ // const packedOsrContent = Convert.toPackedOsrContent(json); // const period = Convert.toPeriod(json); // const phaseBiasesContent = Convert.toPhaseBiasesContent(json); +// const resourceBucket = Convert.toResourceBucket(json); // const sTECHeader = Convert.toSTECHeader(json); // const sTECResidual = Convert.toSTECResidual(json); // const sTECResidualNoStd = Convert.toSTECResidualNoStd(json); @@ -1224,6 +1228,30 @@ function msgPpsTimeToJson(value) { return JSON.stringify(uncast(value, r("MsgPpsTime")), null, 2); } +function toMsgProfilingResourceCounter(json) { + return cast(JSON.parse(json), r("MsgProfilingResourceCounter")); +} + +function msgProfilingResourceCounterToJson(value) { + return JSON.stringify(uncast(value, r("MsgProfilingResourceCounter")), null, 2); +} + +function toMsgProfilingSystemInfo(json) { + return cast(JSON.parse(json), r("MsgProfilingSystemInfo")); +} + +function msgProfilingSystemInfoToJson(value) { + return JSON.stringify(uncast(value, r("MsgProfilingSystemInfo")), null, 2); +} + +function toMsgProfilingThreadInfo(json) { + return cast(JSON.parse(json), r("MsgProfilingThreadInfo")); +} + +function msgProfilingThreadInfoToJson(value) { + return JSON.stringify(uncast(value, r("MsgProfilingThreadInfo")), null, 2); +} + function toMsgProtectionLevel(json) { return cast(JSON.parse(json), r("MsgProtectionLevel")); } @@ -1808,6 +1836,14 @@ function phaseBiasesContentToJson(value) { return JSON.stringify(uncast(value, r("PhaseBiasesContent")), null, 2); } +function toResourceBucket(json) { + return cast(JSON.parse(json), r("ResourceBucket")); +} + +function resourceBucketToJson(value) { + return JSON.stringify(uncast(value, r("ResourceBucket")), null, 2); +} + function toSTECHeader(json) { return cast(JSON.parse(json), r("STECHeader")); } @@ -3002,6 +3038,36 @@ const typeMap = { { json: "flags", js: "flags", typ: 0 }, { json: "time", js: "time", typ: 0 }, ], "any"), + "MsgProfilingResourceCounter": o([ + { json: "buckets", js: "buckets", typ: a(r("ResourceBucket")) }, + { json: "seq_len", js: "seq_len", typ: 0 }, + { json: "seq_no", js: "seq_no", typ: 0 }, + ], "any"), + "ResourceBucket": o([ + { json: "cv", js: "cv", typ: 0 }, + { json: "heap_bytes_alloc", js: "heap_bytes_alloc", typ: 0 }, + { json: "heap_bytes_free", js: "heap_bytes_free", typ: 0 }, + { json: "io", js: "io", typ: 0 }, + { json: "io_read", js: "io_read", typ: 0 }, + { json: "io_write", js: "io_write", typ: 0 }, + { json: "mutex", js: "mutex", typ: 0 }, + { json: "name", js: "name", typ: "" }, + { json: "thread", js: "thread", typ: 0 }, + ], "any"), + "MsgProfilingSystemInfo": o([ + { json: "age", js: "age", typ: 0 }, + { json: "heap_usage", js: "heap_usage", typ: 0 }, + { json: "n_threads", js: "n_threads", typ: 0 }, + { json: "total_cpu_time", js: "total_cpu_time", typ: 0 }, + ], "any"), + "MsgProfilingThreadInfo": o([ + { json: "age", js: "age", typ: 0 }, + { json: "name", js: "name", typ: "" }, + { json: "stack_size", js: "stack_size", typ: 0 }, + { json: "stack_usage", js: "stack_usage", typ: 0 }, + { json: "state", js: "state", typ: 0 }, + { json: "total_cpu_time", js: "total_cpu_time", typ: 0 }, + ], "any"), "MsgProtectionLevel": o([ { json: "atpl", js: "atpl", typ: 0 }, { json: "ctpl", js: "ctpl", typ: 0 }, @@ -3886,6 +3952,12 @@ module.exports = { "toMsgPoseRelative": toMsgPoseRelative, "msgPpsTimeToJson": msgPpsTimeToJson, "toMsgPpsTime": toMsgPpsTime, + "msgProfilingResourceCounterToJson": msgProfilingResourceCounterToJson, + "toMsgProfilingResourceCounter": toMsgProfilingResourceCounter, + "msgProfilingSystemInfoToJson": msgProfilingSystemInfoToJson, + "toMsgProfilingSystemInfo": toMsgProfilingSystemInfo, + "msgProfilingThreadInfoToJson": msgProfilingThreadInfoToJson, + "toMsgProfilingThreadInfo": toMsgProfilingThreadInfo, "msgProtectionLevelToJson": msgProtectionLevelToJson, "toMsgProtectionLevel": toMsgProtectionLevel, "msgReferenceFrameParamToJson": msgReferenceFrameParamToJson, @@ -4032,6 +4104,8 @@ module.exports = { "toPeriod": toPeriod, "phaseBiasesContentToJson": phaseBiasesContentToJson, "toPhaseBiasesContent": toPhaseBiasesContent, + "resourceBucketToJson": resourceBucketToJson, + "toResourceBucket": toResourceBucket, "sTECHeaderToJson": sTECHeaderToJson, "toSTECHeader": toSTECHeader, "sTECResidualToJson": sTECResidualToJson, diff --git a/sbpjson/typescript/SbpJson.ts b/sbpjson/typescript/SbpJson.ts index fb17ed827d..5c0690f5ea 100644 --- a/sbpjson/typescript/SbpJson.ts +++ b/sbpjson/typescript/SbpJson.ts @@ -1,6 +1,6 @@ // To parse this data: // -// import { Convert, AcqSvProfile, AlmanacCommonContent, BoundsHeader, CarrierPhase, CodeBiasesContent, CodePhaseBiasesSatSig, Doppler, ECDSASignature, EphemerisCommonContent, EstimatedHorizontalErrorEllipse, GNSSInputType, GnssCapb, GnssSignal, GpsTime, GpsTimeSEC, GridElement, GridElementNoStd, GriddedCorrectionHeader, IMUInputType, IntegritySSRHeader, Latency, MeasurementState, MsgAcknowledge, MsgAcqResult, MsgAcqSvProfile, MsgAgeCorrections, MsgAlmanacGPS, MsgAlmanacGlo, MsgAngularRate, MsgBasePosECEF, MsgBasePosLLH, MsgBaselineECEF, MsgBaselineHeading, MsgBaselineNED, MsgBootloaderHandshakeResp, MsgBootloaderJumpToApp, MsgCellModemStatus, MsgCertificateChain, MsgCommandOutput, MsgCommandReq, MsgCommandResp, MsgCsacTelemetry, MsgCsacTelemetryLabels, MsgDeviceMonitor, MsgDgnssStatus, MsgDops, MsgEcdsaCertificate, MsgEcdsaSignature, MsgEphemerisBds, MsgEphemerisGPS, MsgEphemerisGal, MsgEphemerisGlo, MsgEphemerisQzss, MsgEphemerisSbas, MsgEXTEvent, MsgFileioConfigReq, MsgFileioConfigResp, MsgFileioReadDirReq, MsgFileioReadDirResp, MsgFileioReadReq, MsgFileioReadResp, MsgFileioRemove, MsgFileioWriteReq, MsgFileioWriteResp, MsgFlashDone, MsgFlashErase, MsgFlashProgram, MsgFlashReadReq, MsgFlashReadResp, MsgFrontEndGain, MsgFwd, MsgGPSTime, MsgGPSTimeGnss, MsgGloBiases, MsgGnssCapb, MsgGnssTimeOffset, MsgGroupDelay, MsgGroupMeta, MsgHeartbeat, MsgIarState, MsgImuAux, MsgImuRaw, MsgInsStatus, MsgInsUpdates, MsgIono, MsgLinuxCPUState, MsgLinuxMemState, MsgLinuxProcessFdCount, MsgLinuxProcessFdSummary, MsgLinuxProcessSocketCounts, MsgLinuxProcessSocketQueues, MsgLinuxSocketUsage, MsgLinuxSysState, MsgLog, MsgM25FlashWriteStatus, MsgMagRaw, MsgMaskSatellite, MsgMeasurementPoint, MsgMeasurementState, MsgNapDeviceDnaResp, MsgNdbEvent, MsgNetworkBandwidthUsage, MsgNetworkStateResp, MsgObs, MsgOdometry, MsgOrientEuler, MsgOrientQuat, MsgOsr, MsgPosECEF, MsgPosECEFCov, MsgPosECEFCovGnss, MsgPosECEFGnss, MsgPosLLH, MsgPosLLHAcc, MsgPosLLHCov, MsgPosLLHCovGnss, MsgPosLLHGnss, MsgPoseRelative, MsgPpsTime, MsgProtectionLevel, MsgReferenceFrameParam, MsgReset, MsgResetFilters, MsgSbasRaw, MsgSensorAidEvent, MsgSettingsReadByIndexReq, MsgSettingsReadByIndexResp, MsgSettingsReadReq, MsgSettingsReadResp, MsgSettingsRegister, MsgSettingsRegisterResp, MsgSettingsWrite, MsgSettingsWriteResp, MsgSolnMeta, MsgSpecan, MsgSsrCodeBiases, MsgSsrCodePhaseBiasesBounds, MsgSsrFlagHighLevel, MsgSsrFlagIonoGridPointSatLos, MsgSsrFlagIonoGridPoints, MsgSsrFlagIonoTileSatLos, MsgSsrFlagSatellites, MsgSsrFlagTropoGridPoints, MsgSsrGriddedCorrection, MsgSsrGriddedCorrectionBounds, MsgSsrOrbitClock, MsgSsrOrbitClockBounds, MsgSsrOrbitClockBoundsDegradation, MsgSsrPhaseBiases, MsgSsrSatelliteApc, MsgSsrStecCorrection, MsgSsrTileDefinition, MsgStartup, MsgStatusJournal, MsgStatusReport, MsgStmFlashLockSector, MsgStmFlashUnlockSector, MsgStmUniqueIDResp, MsgSvAzEl, MsgTelSv, MsgThreadState, MsgTrackingIq, MsgTrackingState, MsgUARTState, MsgUserData, MsgUTCLeapSecond, MsgUTCTime, MsgUTCTimeGnss, MsgVelBody, MsgVelCog, MsgVelECEF, MsgVelECEFCov, MsgVelECEFCovGnss, MsgVelECEFGnss, MsgVelNED, MsgVelNEDCov, MsgVelNEDCovGnss, MsgVelNEDGnss, MsgWheeltick, NetworkUsage, ObservationHeader, OdoInputType, OrbitClockBound, OrbitClockBoundDegradation, PackedObsContent, PackedOsrContent, Period, PhaseBiasesContent, STECHeader, STECResidual, STECResidualNoStd, STECSatElement, STECSatElementIntegrity, SatelliteAPC, SolutionInputType, StatusJournalItem, SubSystemReport, SvAzEl, SvID, TelemetrySV, TrackingChannelCorrelation, TrackingChannelState, TroposphericDelayCorrection, TroposphericDelayCorrectionNoStd, UARTChannel, UTCTime } from "./file"; +// import { Convert, AcqSvProfile, AlmanacCommonContent, BoundsHeader, CarrierPhase, CodeBiasesContent, CodePhaseBiasesSatSig, Doppler, ECDSASignature, EphemerisCommonContent, EstimatedHorizontalErrorEllipse, GNSSInputType, GnssCapb, GnssSignal, GpsTime, GpsTimeSEC, GridElement, GridElementNoStd, GriddedCorrectionHeader, IMUInputType, IntegritySSRHeader, Latency, MeasurementState, MsgAcknowledge, MsgAcqResult, MsgAcqSvProfile, MsgAgeCorrections, MsgAlmanacGPS, MsgAlmanacGlo, MsgAngularRate, MsgBasePosECEF, MsgBasePosLLH, MsgBaselineECEF, MsgBaselineHeading, MsgBaselineNED, MsgBootloaderHandshakeResp, MsgBootloaderJumpToApp, MsgCellModemStatus, MsgCertificateChain, MsgCommandOutput, MsgCommandReq, MsgCommandResp, MsgCsacTelemetry, MsgCsacTelemetryLabels, MsgDeviceMonitor, MsgDgnssStatus, MsgDops, MsgEcdsaCertificate, MsgEcdsaSignature, MsgEphemerisBds, MsgEphemerisGPS, MsgEphemerisGal, MsgEphemerisGlo, MsgEphemerisQzss, MsgEphemerisSbas, MsgEXTEvent, MsgFileioConfigReq, MsgFileioConfigResp, MsgFileioReadDirReq, MsgFileioReadDirResp, MsgFileioReadReq, MsgFileioReadResp, MsgFileioRemove, MsgFileioWriteReq, MsgFileioWriteResp, MsgFlashDone, MsgFlashErase, MsgFlashProgram, MsgFlashReadReq, MsgFlashReadResp, MsgFrontEndGain, MsgFwd, MsgGPSTime, MsgGPSTimeGnss, MsgGloBiases, MsgGnssCapb, MsgGnssTimeOffset, MsgGroupDelay, MsgGroupMeta, MsgHeartbeat, MsgIarState, MsgImuAux, MsgImuRaw, MsgInsStatus, MsgInsUpdates, MsgIono, MsgLinuxCPUState, MsgLinuxMemState, MsgLinuxProcessFdCount, MsgLinuxProcessFdSummary, MsgLinuxProcessSocketCounts, MsgLinuxProcessSocketQueues, MsgLinuxSocketUsage, MsgLinuxSysState, MsgLog, MsgM25FlashWriteStatus, MsgMagRaw, MsgMaskSatellite, MsgMeasurementPoint, MsgMeasurementState, MsgNapDeviceDnaResp, MsgNdbEvent, MsgNetworkBandwidthUsage, MsgNetworkStateResp, MsgObs, MsgOdometry, MsgOrientEuler, MsgOrientQuat, MsgOsr, MsgPosECEF, MsgPosECEFCov, MsgPosECEFCovGnss, MsgPosECEFGnss, MsgPosLLH, MsgPosLLHAcc, MsgPosLLHCov, MsgPosLLHCovGnss, MsgPosLLHGnss, MsgPoseRelative, MsgPpsTime, MsgProfilingResourceCounter, MsgProfilingSystemInfo, MsgProfilingThreadInfo, MsgProtectionLevel, MsgReferenceFrameParam, MsgReset, MsgResetFilters, MsgSbasRaw, MsgSensorAidEvent, MsgSettingsReadByIndexReq, MsgSettingsReadByIndexResp, MsgSettingsReadReq, MsgSettingsReadResp, MsgSettingsRegister, MsgSettingsRegisterResp, MsgSettingsWrite, MsgSettingsWriteResp, MsgSolnMeta, MsgSpecan, MsgSsrCodeBiases, MsgSsrCodePhaseBiasesBounds, MsgSsrFlagHighLevel, MsgSsrFlagIonoGridPointSatLos, MsgSsrFlagIonoGridPoints, MsgSsrFlagIonoTileSatLos, MsgSsrFlagSatellites, MsgSsrFlagTropoGridPoints, MsgSsrGriddedCorrection, MsgSsrGriddedCorrectionBounds, MsgSsrOrbitClock, MsgSsrOrbitClockBounds, MsgSsrOrbitClockBoundsDegradation, MsgSsrPhaseBiases, MsgSsrSatelliteApc, MsgSsrStecCorrection, MsgSsrTileDefinition, MsgStartup, MsgStatusJournal, MsgStatusReport, MsgStmFlashLockSector, MsgStmFlashUnlockSector, MsgStmUniqueIDResp, MsgSvAzEl, MsgTelSv, MsgThreadState, MsgTrackingIq, MsgTrackingState, MsgUARTState, MsgUserData, MsgUTCLeapSecond, MsgUTCTime, MsgUTCTimeGnss, MsgVelBody, MsgVelCog, MsgVelECEF, MsgVelECEFCov, MsgVelECEFCovGnss, MsgVelECEFGnss, MsgVelNED, MsgVelNEDCov, MsgVelNEDCovGnss, MsgVelNEDGnss, MsgWheeltick, NetworkUsage, ObservationHeader, OdoInputType, OrbitClockBound, OrbitClockBoundDegradation, PackedObsContent, PackedOsrContent, Period, PhaseBiasesContent, ResourceBucket, STECHeader, STECResidual, STECResidualNoStd, STECSatElement, STECSatElementIntegrity, SatelliteAPC, SolutionInputType, StatusJournalItem, SubSystemReport, SvAzEl, SvID, TelemetrySV, TrackingChannelCorrelation, TrackingChannelState, TroposphericDelayCorrection, TroposphericDelayCorrectionNoStd, UARTChannel, UTCTime } from "./file"; // // const acqSvProfile = Convert.toAcqSvProfile(json); // const almanacCommonContent = Convert.toAlmanacCommonContent(json); @@ -127,6 +127,9 @@ // const msgPosLLHGnss = Convert.toMsgPosLLHGnss(json); // const msgPoseRelative = Convert.toMsgPoseRelative(json); // const msgPpsTime = Convert.toMsgPpsTime(json); +// const msgProfilingResourceCounter = Convert.toMsgProfilingResourceCounter(json); +// const msgProfilingSystemInfo = Convert.toMsgProfilingSystemInfo(json); +// const msgProfilingThreadInfo = Convert.toMsgProfilingThreadInfo(json); // const msgProtectionLevel = Convert.toMsgProtectionLevel(json); // const msgReferenceFrameParam = Convert.toMsgReferenceFrameParam(json); // const msgReset = Convert.toMsgReset(json); @@ -200,6 +203,7 @@ // const packedOsrContent = Convert.toPackedOsrContent(json); // const period = Convert.toPeriod(json); // const phaseBiasesContent = Convert.toPhaseBiasesContent(json); +// const resourceBucket = Convert.toResourceBucket(json); // const sTECHeader = Convert.toSTECHeader(json); // const sTECResidual = Convert.toSTECResidual(json); // const sTECResidualNoStd = Convert.toSTECResidualNoStd(json); @@ -2026,6 +2030,62 @@ export interface MsgPpsTime { [property: string]: any; } +/** + * Information about resource buckets. Refer to product documentation to understand the + * meaning and values in this message. + */ +export interface MsgProfilingResourceCounter { + buckets: ResourceBucket[]; + seq_len: number; + seq_no: number; + [property: string]: any; +} + +/** + * Information about allocation of various resources grouped by buckets. Refer to product + * documentation to understand the meaning and values in this message. + */ +export interface ResourceBucket { + cv: number; + heap_bytes_alloc: number; + heap_bytes_free: number; + io: number; + io_read: number; + io_write: number; + mutex: number; + name: string; + thread: number; + [property: string]: any; +} + +/** + * Contains basic information about system resource usage. System is defined in terms of the + * source of this message and may vary from sender to sender. Refer to product + * documentation to understand the exact scope and meaning of this message. + */ +export interface MsgProfilingSystemInfo { + age: number; + heap_usage: number; + n_threads: number; + total_cpu_time: number; + [property: string]: any; +} + +/** + * Contains profiling information related to a single thread being tracked by the producing + * system. Refer to product documentation to understand the exact scope and meaning of this + * message. + */ +export interface MsgProfilingThreadInfo { + age: number; + name: string; + stack_size: number; + stack_usage: number; + state: number; + total_cpu_time: number; + [property: string]: any; +} + /** * This message reports the protection levels associated to the given state estimate. The * full GPS time is given by the preceding MSG_GPS_TIME with the matching time-of-week (tow). @@ -4245,6 +4305,30 @@ export class Convert { return JSON.stringify(uncast(value, r("MsgPpsTime")), null, 2); } + public static toMsgProfilingResourceCounter(json: string): MsgProfilingResourceCounter { + return cast(JSON.parse(json), r("MsgProfilingResourceCounter")); + } + + public static msgProfilingResourceCounterToJson(value: MsgProfilingResourceCounter): string { + return JSON.stringify(uncast(value, r("MsgProfilingResourceCounter")), null, 2); + } + + public static toMsgProfilingSystemInfo(json: string): MsgProfilingSystemInfo { + return cast(JSON.parse(json), r("MsgProfilingSystemInfo")); + } + + public static msgProfilingSystemInfoToJson(value: MsgProfilingSystemInfo): string { + return JSON.stringify(uncast(value, r("MsgProfilingSystemInfo")), null, 2); + } + + public static toMsgProfilingThreadInfo(json: string): MsgProfilingThreadInfo { + return cast(JSON.parse(json), r("MsgProfilingThreadInfo")); + } + + public static msgProfilingThreadInfoToJson(value: MsgProfilingThreadInfo): string { + return JSON.stringify(uncast(value, r("MsgProfilingThreadInfo")), null, 2); + } + public static toMsgProtectionLevel(json: string): MsgProtectionLevel { return cast(JSON.parse(json), r("MsgProtectionLevel")); } @@ -4829,6 +4913,14 @@ export class Convert { return JSON.stringify(uncast(value, r("PhaseBiasesContent")), null, 2); } + public static toResourceBucket(json: string): ResourceBucket { + return cast(JSON.parse(json), r("ResourceBucket")); + } + + public static resourceBucketToJson(value: ResourceBucket): string { + return JSON.stringify(uncast(value, r("ResourceBucket")), null, 2); + } + public static toSTECHeader(json: string): STECHeader { return cast(JSON.parse(json), r("STECHeader")); } @@ -6024,6 +6116,36 @@ const typeMap: any = { { json: "flags", js: "flags", typ: 0 }, { json: "time", js: "time", typ: 0 }, ], "any"), + "MsgProfilingResourceCounter": o([ + { json: "buckets", js: "buckets", typ: a(r("ResourceBucket")) }, + { json: "seq_len", js: "seq_len", typ: 0 }, + { json: "seq_no", js: "seq_no", typ: 0 }, + ], "any"), + "ResourceBucket": o([ + { json: "cv", js: "cv", typ: 0 }, + { json: "heap_bytes_alloc", js: "heap_bytes_alloc", typ: 0 }, + { json: "heap_bytes_free", js: "heap_bytes_free", typ: 0 }, + { json: "io", js: "io", typ: 0 }, + { json: "io_read", js: "io_read", typ: 0 }, + { json: "io_write", js: "io_write", typ: 0 }, + { json: "mutex", js: "mutex", typ: 0 }, + { json: "name", js: "name", typ: "" }, + { json: "thread", js: "thread", typ: 0 }, + ], "any"), + "MsgProfilingSystemInfo": o([ + { json: "age", js: "age", typ: 0 }, + { json: "heap_usage", js: "heap_usage", typ: 0 }, + { json: "n_threads", js: "n_threads", typ: 0 }, + { json: "total_cpu_time", js: "total_cpu_time", typ: 0 }, + ], "any"), + "MsgProfilingThreadInfo": o([ + { json: "age", js: "age", typ: 0 }, + { json: "name", js: "name", typ: "" }, + { json: "stack_size", js: "stack_size", typ: 0 }, + { json: "stack_usage", js: "stack_usage", typ: 0 }, + { json: "state", js: "state", typ: 0 }, + { json: "total_cpu_time", js: "total_cpu_time", typ: 0 }, + ], "any"), "MsgProtectionLevel": o([ { json: "atpl", js: "atpl", typ: 0 }, { json: "ctpl", js: "ctpl", typ: 0 }, diff --git a/spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingResourceCounter.yaml b/spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingResourceCounter.yaml new file mode 100644 index 0000000000..0d9e3fc43e --- /dev/null +++ b/spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingResourceCounter.yaml @@ -0,0 +1,92 @@ +--- +description: Unit tests for swiftnav.sbp.profiling MSgProfilingResourceCounter +generated_on: 2024-02-01 00:00:00.00 # manually generated +package: sbp.profiling +tests: + + + - msg: + c_decoded_fields: + n_buckets: + handle_as: vararray-len + relates_to: buckets + value: 6 + fields: + seq_no: 1 + seq_len: 3 + buckets: + - name: "Fusion engine\0\0\0\0\0\0\0\0" + thread: 1 + mutex: 2 + cv: 2 + io: 0 + heap_bytes_alloc: 927480 + heap_bytes_free: 0 + io_write: 0 + io_read: 0 + - name: "NTRIP client\0\0\0\0\0\0\0\0\0" + thread: 1 + mutex: 1 + cv: 1 + io: 1 + heap_bytes_alloc: 84454 + heap_bytes_free: 0 + io_write: 879 + io_read: 19520 + - name: "SSR2OSR\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + thread: 1 + mutex: 1 + cv: 1 + io: 0 + heap_bytes_alloc: 4328776 + heap_bytes_free: 0 + io_write: 0 + io_read: 0 + - name: "Periodic\0\0\0\0\0\0\0\0\0\0\0\0\0" + thread: 1 + mutex: 2 + cv: 1 + io: 0 + heap_bytes_alloc: 247112 + heap_bytes_free: 0 + io_write: 0 + io_read: 0 + - name: "IMU\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + thread: 1 + mutex: 1 + cv: 1 + io: 1 + heap_bytes_alloc: 18305 + heap_bytes_free: 0 + io_write: 0 + io_read: 26207 + - name: "sbp\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + thread: 5 + mutex: 2 + cv: 2 + io: 2 + heap_bytes_alloc: 43507 + heap_bytes_free: 0 + io_write: 235451 + io_read: 498 + module: sbp.profiling + name: MsgProfilingResourceCounter + msg_type: '0xcf03' + raw_json: > + {"crc": 39349, "preamble": 85, "sender": 4096, "length": 248, "msg_type": 52995, + "seq_no": 1, "seq_len": 3, "buckets": [ + {"name": "Fusion engine\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "thread": 1, "mutex": 2, "cv": 2, "io": 0, "heap_bytes_alloc": 927480, "heap_bytes_free": 0, "io_write": 0, "io_read": 0}, + {"name": "NTRIP client\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "thread": 1, "mutex": 1, "cv": 1, "io": 1, "heap_bytes_alloc": 84454, "heap_bytes_free": 0, "io_write": 879, "io_read": 19520}, + {"name": "SSR2OSR\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "thread": 1, "mutex": 1, "cv": 1, "io": 0, "heap_bytes_alloc": 4328776, "heap_bytes_free": 0, "io_write": 0, "io_read": 0}, + {"name": "Periodic\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "thread": 1, "mutex": 2, "cv": 1, "io": 0, "heap_bytes_alloc": 247112, "heap_bytes_free": 0, "io_write": 0, "io_read": 0}, + {"name": "IMU\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "thread": 1, "mutex": 1, "cv": 1, "io": 1, "heap_bytes_alloc": 18305, "heap_bytes_free": 0, "io_write": 0, "io_read": 26207}, + {"name": "sbp\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", "thread": 5, "mutex": 2, "cv": 2, "io": 2, "heap_bytes_alloc": 43507, "heap_bytes_free": 0, "io_write": 235451, "io_read": 498}], + "payload": "AQNGdXNpb24gZW5naW5lAAAAAAAAAAABAgIA+CYOAAAAAAAAAAAAAAAAAE5UUklQIGNsaWVudAAAAAAAAAAAAAEBAQHmSQEAAAAAAG8DAABATAAAU1NSMk9TUgAAAAAAAAAAAAAAAAAAAQEBAEgNQgAAAAAAAAAAAAAAAABQZXJpb2RpYwAAAAAAAAAAAAAAAAABAgEASMUDAAAAAAAAAAAAAAAAAElNVQAAAAAAAAAAAAAAAAAAAAAAAAEBAQGBRwAAAAAAAAAAAABfZgAAc2JwAAAAAAAAAAAAAAAAAAAAAAAABQICAvOpAAAAAAAAu5cDAPIBAAA="} + raw_packet: VQPPABD4AQNGdXNpb24gZW5naW5lAAAAAAAAAAABAgIA+CYOAAAAAAAAAAAAAAAAAE5UUklQIGNsaWVudAAAAAAAAAAAAAEBAQHmSQEAAAAAAG8DAABATAAAU1NSMk9TUgAAAAAAAAAAAAAAAAAAAQEBAEgNQgAAAAAAAAAAAAAAAABQZXJpb2RpYwAAAAAAAAAAAAAAAAABAgEASMUDAAAAAAAAAAAAAAAAAElNVQAAAAAAAAAAAAAAAAAAAAAAAAEBAQGBRwAAAAAAAAAAAABfZgAAc2JwAAAAAAAAAAAAAAAAAAAAAAAABQICAvOpAAAAAAAAu5cDAPIBAAC1mQ== + sbp: + crc: '0x99b5' + length: 248 + msg_type: '0xcf03' + payload: AQNGdXNpb24gZW5naW5lAAAAAAAAAAABAgIA+CYOAAAAAAAAAAAAAAAAAE5UUklQIGNsaWVudAAAAAAAAAAAAAEBAQHmSQEAAAAAAG8DAABATAAAU1NSMk9TUgAAAAAAAAAAAAAAAAAAAQEBAEgNQgAAAAAAAAAAAAAAAABQZXJpb2RpYwAAAAAAAAAAAAAAAAABAgEASMUDAAAAAAAAAAAAAAAAAElNVQAAAAAAAAAAAAAAAAAAAAAAAAEBAQGBRwAAAAAAAAAAAABfZgAAc2JwAAAAAAAAAAAAAAAAAAAAAAAABQICAvOpAAAAAAAAu5cDAPIBAAA= + preamble: '0x55' + sender: '0x1000' diff --git a/spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingSystemInfo.yaml b/spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingSystemInfo.yaml new file mode 100644 index 0000000000..10365f52e4 --- /dev/null +++ b/spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingSystemInfo.yaml @@ -0,0 +1,29 @@ +--- +description: Unit tests for swiftnav.sbp.profiling MsgProfilingSystemInfo +generated_on: 2024-02-01 00:00:00.00 # manually generated +package: sbp.profiling +tests: + + + - msg: + fields: + total_cpu_time: 3418210 + age: 10292338 + n_threads: 27 + heap_usage: 14861128 + module: sbp.profiling + name: MsgProfilingSystemInfo + + msg_type: '0xcf01' + raw_json: > + {"crc": 16892, "preamble": 85, "sender": 4096, "length": 21, "msg_type": 52993, + "total_cpu_time": 3418210, "age": 10292338, "n_threads": 27, "heap_usage": 14861128, + "payload": "Yig0AAAAAAByDJ0AAAAAABtIw+IA"} + raw_packet: VQHPABAVYig0AAAAAAByDJ0AAAAAABtIw+IA/EE= + sbp: + crc: '0x41fc' + length: 21 + msg_type: '0xcf01' + payload: Yig0AAAAAAByDJ0AAAAAABtIw+IA + preamble: '0x55' + sender: '0x1000' diff --git a/spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingThreadInfo.yaml b/spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingThreadInfo.yaml new file mode 100644 index 0000000000..9006083778 --- /dev/null +++ b/spec/tests/yaml/swiftnav/sbp/profiling/test_MsgProfilingThreadInfo.yaml @@ -0,0 +1,38 @@ +--- +description: Unit tests for swiftnav.sbp.profiling MsgProfilingThreadInfo +generated_on: 2024-02-01 00:00:00.00 # manually generated +package: sbp.profiling +tests: + + + - msg: + c_decoded_fields: + name: + handle_as: encoded-string + text: Fusion engine + fn_prefix: sbp_msg_profiling_thread_info_name + encoded_len: 14 + fields: + total_cpu_time: 678775 + age: 10159470 + state: 1 + stack_size: 8388608 + stack_usage: 275920 + name: "Fusion engine\u0000" + module: sbp.profiling + name: MsgProfilingThreadInfo + + msg_type: '0xcf02' + raw_json: > + {"crc": 43762, "preamble": 85, "sender": 4096, "length": 39, "msg_type": 52994, + "total_cpu_time": 678775, "age": 10159470, "state": 1, "stack_size": 8388608, + "stack_usage": 275920, "name": "Fusion engine\u0000", + "payload": "d1sKAAAAAABuBZsAAAAAAAEAAIAA0DUEAEZ1c2lvbiBlbmdpbmUA"} + raw_packet: VQLPABAnd1sKAAAAAABuBZsAAAAAAAEAAIAA0DUEAEZ1c2lvbiBlbmdpbmUA8qo= + sbp: + crc: '0xaaf2' + length: 39 + msg_type: '0xcf02' + payload: d1sKAAAAAABuBZsAAAAAAAEAAIAA0DUEAEZ1c2lvbiBlbmdpbmUA + preamble: '0x55' + sender: '0x1000' diff --git a/spec/yaml/swiftnav/sbp/profiling.yaml b/spec/yaml/swiftnav/sbp/profiling.yaml index 11c5d41254..e2d8417e3e 100644 --- a/spec/yaml/swiftnav/sbp/profiling.yaml +++ b/spec/yaml/swiftnav/sbp/profiling.yaml @@ -52,3 +52,120 @@ definitions: type: string encoding: null_terminated desc: Function name + + - MSG_PROFILING_SYSTEM_INFO: + id: 0xCF01 + short_desc: System Profiling Information + desc: > + Contains basic information about system resource usage. + System is defined in terms of the source of this message and may vary from + sender to sender. Refer to product documentation to understand the exact scope + and meaning of this message. + fields: + - total_cpu_time: + type: u64 + desc: Total cpu time in microseconds consumed by this system + - age: + type: u64 + desc: Age of the producing system in microseconds + - n_threads: + type: u8 + desc: Number of threads being tracked by this system + - heap_usage: + type: u32 + desc: Number of bytes allocated on the heap + + - MSG_PROFILING_THREAD_INFO: + id: 0xCF02 + short_desc: Thread Profiling Information + desc: > + Contains profiling information related to a single thread being tracked by + the producing system. Refer to product documentation to understand the exact scope + and meaning of this message. + fields: + - total_cpu_time: + type: u64 + desc: Total cpu time in microseconds consumed by this thread + - age: + type: u64 + desc: Age of the thread in microseconds + - state: + type: u8 + desc: Thread state + fields: + - 0-1: + desc: Thread state + values: + - 0: External + - 1: Running + - 2: Stopped + - 3: Reserved + - stack_size: + type: u32 + desc: Stack size in bytes + - stack_usage: + type: u32 + desc: Stack highwater usage in bytes + - name: + type: string + encoding: null_terminated + desc: Thread name + + - ResourceBucket: + short_desc: A bucket containing various resources + desc: > + Information about allocation of various resources grouped by buckets. Refer to product + documentation to understand the meaning and values in this message. + fields: + - name: + type: string + encoding: null_terminated + size: 21 + desc: Bucket name + - thread: + type: u8 + desc: Number of threads + - mutex: + type: u8 + desc: Number of mutexes + - cv: + type: u8 + desc: Number of condition variables + - io: + type: u8 + desc: Number of IO handles + - heap_bytes_alloc: + type: u32 + desc: Number of bytes allocated on the heap + - heap_bytes_free: + type: u32 + desc: Number of bytes freed on the heap + - io_write: + type: u32 + desc: Number of bytes written to IO handles + - io_read: + type: u32 + desc: Number of bytes read from IO handles + + + - MSG_PROFILING_RESOURCE_COUNTER: + id: 0xCF03 + short_desc: Information about resource buckets + desc: > + Information about resource buckets. Refer to product documentation to understand + the meaning and values in this message. + fields: + - seq_no: + type: u8 + desc: Message number in complete sequence + - seq_len: + type: u8 + desc: Length of message sequence + - buckets: + type: array + fill: ResourceBucket + desc: List of resource buckets + + + +