From 346768a14433c81065e8a7b687b4b130a6dda193 Mon Sep 17 00:00:00 2001 From: Rongsong Shen Date: Mon, 3 Nov 2025 18:19:59 +0800 Subject: [PATCH] use nix build & meson & zlog --- src/default.nix | 37 + src/flake.lock | 97 ++ src/flake.nix | 38 + src/include/client.h | 81 + src/include/clusterconfig.h | 58 + src/include/config.h | 20 + src/include/dataq.h | 28 + src/include/hook.h | 30 + src/include/htab.h | 44 + src/include/kvmgr.h | 26 + src/include/mylock.h | 38 + src/include/netio.h | 73 + src/include/objmgr.h | 78 + src/include/objs.h | 9 + src/include/request.h | 82 + src/include/typemap.h | 192 +++ src/include/utils.h | 94 ++ src/include/vtaskmgr.h | 61 + src/include/xce/cluster_def.h | 168 ++ src/include/xce/errnox.h | 26 + src/include/xce/types.h | 619 +++++++ src/include/xceapi.h | 34 + src/include/xcectx.h | 52 + src/include/xlist.h | 21 + src/include/xstring.h | 25 + src/include/zarray.h | 32 + src/lib/client.c | 629 ++++++++ src/lib/dataq.c | 119 ++ src/lib/hook.c | 136 ++ src/lib/htab.c | 215 +++ src/lib/kvmgr.c | 211 +++ src/lib/meson.build | 69 + src/lib/mylock.c | 212 +++ src/lib/netio.c | 687 ++++++++ src/lib/objmgr.c | 322 ++++ src/lib/request.c | 931 +++++++++++ src/lib/testsuite/test.c | 35 + src/lib/testsuite/test_error.c | 44 + src/lib/testsuite/test_htab.c | 50 + src/lib/testsuite/test_htab_int.c | 52 + src/lib/testsuite/test_utils.c | 105 ++ src/lib/testsuite/test_xstring.c | 128 ++ src/lib/testsuite/test_zarray.c | 102 ++ src/lib/threshold.c | 81 + src/lib/utils.c | 371 +++++ src/lib/vtaskmgr.c | 362 +++++ src/lib/window.c | 126 ++ src/lib/xceapi.c | 667 ++++++++ src/lib/xcectx.c | 371 +++++ src/lib/xlist.c | 99 ++ src/lib/xstring.c | 147 ++ src/lib/zarray.c | 277 ++++ src/meson.build | 28 + src/meson.options | 3 + src/schema/c.capnp | 69 + src/schema/controller.capnp | 590 +++++++ src/unity/unity.c | 2501 +++++++++++++++++++++++++++++ src/unity/unity.h | 698 ++++++++ src/unity/unity_internals.h | 1183 ++++++++++++++ src/xce.nix | 56 + 60 files changed, 13739 insertions(+) create mode 100644 src/default.nix create mode 100644 src/flake.lock create mode 100644 src/flake.nix create mode 100644 src/include/client.h create mode 100644 src/include/clusterconfig.h create mode 100644 src/include/config.h create mode 100644 src/include/dataq.h create mode 100644 src/include/hook.h create mode 100644 src/include/htab.h create mode 100644 src/include/kvmgr.h create mode 100644 src/include/mylock.h create mode 100644 src/include/netio.h create mode 100644 src/include/objmgr.h create mode 100644 src/include/objs.h create mode 100644 src/include/request.h create mode 100644 src/include/typemap.h create mode 100644 src/include/utils.h create mode 100644 src/include/vtaskmgr.h create mode 100644 src/include/xce/cluster_def.h create mode 100644 src/include/xce/errnox.h create mode 100644 src/include/xce/types.h create mode 100644 src/include/xceapi.h create mode 100644 src/include/xcectx.h create mode 100644 src/include/xlist.h create mode 100644 src/include/xstring.h create mode 100644 src/include/zarray.h create mode 100644 src/lib/client.c create mode 100644 src/lib/dataq.c create mode 100644 src/lib/hook.c create mode 100644 src/lib/htab.c create mode 100644 src/lib/kvmgr.c create mode 100644 src/lib/meson.build create mode 100644 src/lib/mylock.c create mode 100644 src/lib/netio.c create mode 100644 src/lib/objmgr.c create mode 100644 src/lib/request.c create mode 100644 src/lib/testsuite/test.c create mode 100644 src/lib/testsuite/test_error.c create mode 100644 src/lib/testsuite/test_htab.c create mode 100644 src/lib/testsuite/test_htab_int.c create mode 100644 src/lib/testsuite/test_utils.c create mode 100644 src/lib/testsuite/test_xstring.c create mode 100644 src/lib/testsuite/test_zarray.c create mode 100644 src/lib/threshold.c create mode 100755 src/lib/utils.c create mode 100644 src/lib/vtaskmgr.c create mode 100644 src/lib/window.c create mode 100644 src/lib/xceapi.c create mode 100644 src/lib/xcectx.c create mode 100644 src/lib/xlist.c create mode 100644 src/lib/xstring.c create mode 100644 src/lib/zarray.c create mode 100644 src/meson.build create mode 100644 src/meson.options create mode 100644 src/schema/c.capnp create mode 100644 src/schema/controller.capnp create mode 100644 src/unity/unity.c create mode 100644 src/unity/unity.h create mode 100644 src/unity/unity_internals.h create mode 100644 src/xce.nix diff --git a/src/default.nix b/src/default.nix new file mode 100644 index 00000000..01266e41 --- /dev/null +++ b/src/default.nix @@ -0,0 +1,37 @@ +{ + pkgs, + myCommitId, + ... +}: +let + xce = pkgs.callPackage ./xce.nix { + inherit pkgs myCommitId; + withDebug = false; + withAsan = false; + withoutDb = false; + }; + xce_withoutdb = pkgs.callPackage ./xce.nix { + inherit pkgs myCommitId; + withDebug = false; + withAsan = false; + withoutDb = true; + }; + xce_withoutdb_debug = pkgs.callPackage ./xce.nix { + inherit pkgs myCommitId; + withDebug = true; + withAsan = true; + withoutDb = true; + }; + xce_debug = pkgs.callPackage ./xce.nix { + inherit pkgs myCommitId; + withDebug = true; + withAsan = true; + withoutDb = false; + }; +in +{ + xce = xce; + xce_debug = xce_debug; + xce_withoutdb = xce_withoutdb; + xce_withoutdb_debug = xce_withoutdb_debug; +} diff --git a/src/flake.lock b/src/flake.lock new file mode 100644 index 00000000..791eb2b1 --- /dev/null +++ b/src/flake.lock @@ -0,0 +1,97 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1761907660, + "narHash": "sha256-kJ8lIZsiPOmbkJypG+B5sReDXSD1KGu2VEPNqhRa/ew=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "2fb006b87f04c4d3bdf08cfdbc7fab9c13d94a15", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1755615617, + "narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "xbuild": "xbuild" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "xbuild": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1762160937, + "narHash": "sha256-L0wBnhZxneDKm9ym7XroRexjuio62sVV0xi5sgAMiaA=", + "owner": "shen390s", + "repo": "my-nix-channel", + "rev": "3eb8b50d886f197ec5b842aadb022b026c9b2bfd", + "type": "github" + }, + "original": { + "owner": "shen390s", + "ref": "master", + "repo": "my-nix-channel", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/src/flake.nix b/src/flake.nix new file mode 100644 index 00000000..1b6b5391 --- /dev/null +++ b/src/flake.nix @@ -0,0 +1,38 @@ +{ + description = "Flake for NEXA xce"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + xbuild.url = "github:shen390s/my-nix-channel?ref=master"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, xbuild, flake-utils }: + let + supportedSystems = [ "x86_64-linux" ]; + myCommitId = + if builtins.hasAttr "shortRev" self + then self.shortRev + else self.dirtyShortRev; + in + flake-utils.lib.eachSystem supportedSystems ( + system: let + mypkgs = xbuild.packages.${system}; + overlays = [ + (final: prev: prev // mypkgs) + ]; + pkgs = import nixpkgs { inherit overlays system;}; + xpkgs = import ./default.nix { + inherit pkgs myCommitId; + }; + in rec { + packages = pkgs // xpkgs; + defaultPackage = xpkgs.xce_withoutdb_debug; + devShells.default = pkgs.mkShell { + nativeBuildInputs = xpkgs.xce.nativeBuildInputs; + }; + + devShell = self.devShells.${system}.default; + } + ); +} diff --git a/src/include/client.h b/src/include/client.h new file mode 100644 index 00000000..3cff1ee0 --- /dev/null +++ b/src/include/client.h @@ -0,0 +1,81 @@ +#if !defined(_CLIENT_H_) + +#define _CLIENT_H_ + +#include + +#include "netio.h" +#include "request.h" +#include "xce/types.h" +#include "xceapi.h" + +typedef int (*xce_request_handler_t)(xce_request_t*); +typedef void* xcecli_ctx_t; + +#define N_MAX_MASTERS (3) + +typedef struct { + int nmasters; + char* masters[N_MAX_MASTERS]; + int master_ports[N_MAX_MASTERS]; + char* from; + char* key; +} xce_client_config_t; + +#define xcecli_jobfinish(ctx, finish) \ + xcecli_notify_jobfinish(ctx, finish) + +extern int xcecli_ctx_init(xcecli_ctx_t*, xce_client_config_t*); +extern void xcecli_ctx_fini(xcecli_ctx_t); +extern int xcecli_set_handler(xcecli_ctx_t, xce_request_handler_t); +extern int xcecli_start(xcecli_ctx_t); +extern int xcecli_stop(xcecli_ctx_t); +extern int xcecli_wakeup(xcecli_ctx_t, int); +extern int xcecli_hello(xcecli_ctx_t, char*); +extern int xcecli_shutdown(xcecli_ctx_t); +extern int xcecli_reslist(xcecli_ctx_t, xce_resource_t***); +extern int xcecli_join(xcecli_ctx_t, int, hostattrs_t*); +extern int xcecli_workerlist(xcecli_ctx_t, xce_worker_t***); +extern int xcecli_jobdispatch(xcecli_ctx_t, xce_job_dispatch_t*); +extern int xcecli_joblist(xcecli_ctx_t, xce_job_t***); +extern int xcecli_clusterconf(xcecli_ctx_t, xce_clusterconf_t**); +extern int xcecli_notify_jobfinish(xcecli_ctx_t, xce_jobfinish_t*); +extern int xcecli_notify_jobstart(xcecli_ctx_t, job_pidinfo_t*); +extern int xcecli_notify_jobfail(xcecli_ctx_t c, job_failinfo_t*); +extern int xcecli_notify_jobstop(xcecli_ctx_t, uint64_t); +extern int xcecli_notify_jobresume(xcecli_ctx_t, uint64_t); +extern int xcecli_notify_jobpostdone(xcecli_ctx_t, uint64_t); +extern int xcecli_jobsubmit(xcecli_ctx_t, xce_job_submit_t*, + uint64_t*); +extern int xcecli_update_resvals(xcecli_ctx_t, int, xce_resval_t**); +extern int xcecli_resval(xcecli_ctx_t, char*, + char*, xce_resval_t***); +extern int xcecli_update_jusage(xcecli_ctx_t, uint64_t, int, int*, + int, int*, int, xce_rusage_t**); +extern int xcecli_notify(xcecli_ctx_t, xce_notify_data_t*); +extern int xcecli_jobctrl(xcecli_ctx_t, xce_jobctrl_t*); +extern int xcecli_notify_jobchkpt(xcecli_ctx_t, uint64_t, char*); +extern int xcecli_queuectrl(xcecli_ctx_t, xce_queuectrl_t*); +extern int xcecli_runtask(xcecli_ctx_t, xce_taskrun_t*); +extern int xcecli_notify_taskstart(xcecli_ctx_t, xce_task_pidinfo_t*); +extern int xcecli_notify_taskfail(xcecli_ctx_t, xce_task_failinfo_t*); +extern int xcecli_notify_taskfinish(xcecli_ctx_t, xce_task_finish_t*); +extern endpoint_t* xcecli_get_my_endpoint(xcecli_ctx_t); +extern xce_peerinfo_t* xcecli_get_myinfo(xcecli_ctx_t); +extern void xcecli_block_tasks(xcecli_ctx_t); +extern void xcecli_unblock_tasks(xcecli_ctx_t); + +#define xcecli_free_ress(nres, ress) \ + xce_free_ress(nres, ress) +#define xcecli_free_workers(nworkers, workers) \ + xce_free_workers(nworkers, workers) +#define xcecli_free_jobs(njobs, jobs) \ + xce_free_jobs(njobs, jobs) +#define xcecli_free_queues(nqueues, queues) \ + xce_free_queues(nqueues, queues) +#define xcecli_free_groups(ngroups, groups) \ + xce_free_groups(ngroups, groups) +#define xcecli_free_clusterconf(conf) \ + xce_free_clusterconf(conf) + +#endif diff --git a/src/include/clusterconfig.h b/src/include/clusterconfig.h new file mode 100644 index 00000000..5ae899de --- /dev/null +++ b/src/include/clusterconfig.h @@ -0,0 +1,58 @@ +#if !defined(_CLUSTERCONFIG_H_) + +#define _CLUSTERCONFIG_H_ 1 + +#include "xce/types.h" + +typedef struct { + int nhash_slots; + int delta; +} hash_zarray_config_t; + +typedef hash_zarray_config_t jobmgr_config_t; + +typedef hash_zarray_config_t workermgr_config_t; +typedef hash_zarray_config_t qmgr_config_t; + +typedef struct { + int nhash_slots; + int delta; + int inst_delta; +} resmgr_config_t; + +typedef hash_zarray_config_t xstrings_config_t; + +typedef struct { + char* name; + char* host; + int port; +} master_candidate_t; + +typedef struct { + char* clustername; + int port; + int ncandidates; + master_candidate_t** candidates; + int heartbeat_interval; + int inactive_heartbeat_count; + int fetch_job_interval; + int netio_timeout; + int vcpus; + int nres; + xce_resource_t** resources; + int nqueues; + xce_queue_t** queues; + int nugroups; + xce_group_t** ugroups; + int nhgroups; + xce_group_t** hgroups; + int nhconfigs; + xce_hostconfig_t** hconfigs; + jobmgr_config_t* jobmgr; + workermgr_config_t* workermgr; + qmgr_config_t* qmgr; + resmgr_config_t* resmgr; + xstrings_config_t* xstrings; +} cluster_config_t; + +#endif diff --git a/src/include/config.h b/src/include/config.h new file mode 100644 index 00000000..1c2091b6 --- /dev/null +++ b/src/include/config.h @@ -0,0 +1,20 @@ +#if !defined(_CONFIG_H_) + +#define _CONFIG_H_ + +#define BUG_EMAIL "rshen@shenrs.eu" +#define XCE_MAXNAME_LEN (64) +#define XCE_MAXHOSTNAME_LEN (256) /* hostname suggest to 256 */ +#define XCE_MAXDESC_LEN (4096) /* enlarge to 4096 */ +#define XCE_MAXKEY_LEN (256) +#define XCE_MAXMODEL_LEN (32) +#define XCE_MAXTYPE_LEN (32) + +#define XCE_WORKER_HTAB_SIZE (673) +#define XCE_JOB_HTAB_SIZE (5009) + +#define XCE_MAXPATH_LEN (4096) /* enlarge to 4096 */ +#define XCE_MAXCMD_LEN (4096) +#define XCE_MAX_ERRMSG_LEN (4096) + +#endif diff --git a/src/include/dataq.h b/src/include/dataq.h new file mode 100644 index 00000000..e16a46ff --- /dev/null +++ b/src/include/dataq.h @@ -0,0 +1,28 @@ +#if !defined(_DATAQ_H_) + +#define _DATAQ_H_ 1 + +#include "mylock.h" + +typedef struct _data_item { + struct _data_item* next; +} data_item_t; + +typedef int (*data_item_match_fn_t)(data_item_t*); +typedef void (*data_item_killer_t)(data_item_t*); + +typedef struct { + data_item_t* head; + data_item_t* tail; + data_item_killer_t killer; + mylock_t lock; +} dataq_t; + +#define DATAQ_EMPTY(q) ((q)->head == NULL) + +extern int dataq_init(dataq_t*, data_item_killer_t); +extern data_item_t* dataq_deq(dataq_t*, data_item_match_fn_t); +extern int dataq_enq(dataq_t*, data_item_t*); +extern void dataq_fini(dataq_t*); + +#endif diff --git a/src/include/hook.h b/src/include/hook.h new file mode 100644 index 00000000..c136a7b6 --- /dev/null +++ b/src/include/hook.h @@ -0,0 +1,30 @@ +#if !defined(__HOOK_H__) + +#define __HOOK_H__ 1 + +#include +#include + +#include "xlist.h" + +#define HOOK_BEFORE_EVENT (0) +#define HOOK_AFTER_EVENT (1) + +typedef int (*hook_fn_t)(int, int, int, void*, va_list); +typedef struct { + hook_fn_t fn; + void* data; +} hook_item_t; + +typedef struct { + int maxtypes; + xlist_t* hooks; +} hooksys_t; + +extern int xce_hook_init(hooksys_t*, int); +extern int xce_add_hook(hooksys_t*, int, + hook_fn_t, void*); +extern int xce_run_hooks(hooksys_t*, int, int, int, ...); +extern void xce_hook_fini(hooksys_t*); + +#endif diff --git a/src/include/htab.h b/src/include/htab.h new file mode 100644 index 00000000..f2d8c9ff --- /dev/null +++ b/src/include/htab.h @@ -0,0 +1,44 @@ +#if !defined(_HTAB_H_) + +#define _HTAB_H_ 1 + +#include + +#include "mylock.h" + +typedef unsigned int (*hash_key_hash_fn_t)(void*); +typedef int (*hash_key_cmp_fn_t)(void*, void*); +typedef void* (*hash_key_copy_fn_t)(void*); +typedef void (*hash_key_free_fn_t)(void*); + +typedef struct { + hash_key_hash_fn_t hash; + hash_key_cmp_fn_t cmp; + hash_key_copy_fn_t copy; + hash_key_free_fn_t free; +} hash_key_fn_t; + +typedef struct _hent { + struct _hent* next; + void* key; + int64_t data; +} hent_t; + +typedef struct { + mylock_t lock; + int nslots; + hash_key_fn_t fn; + hent_t** slots; +} htab_t; + +extern hash_key_fn_t string_hash_key; +extern hash_key_fn_t int_hash_key; + +extern int ht_init(htab_t*, int, + hash_key_fn_t); +extern void ht_fini(htab_t*); +extern hent_t* ht_get(htab_t*, void*); +extern hent_t* ht_add(htab_t*, void*); +extern int ht_del(htab_t*, void*); + +#endif diff --git a/src/include/kvmgr.h b/src/include/kvmgr.h new file mode 100644 index 00000000..87321c05 --- /dev/null +++ b/src/include/kvmgr.h @@ -0,0 +1,26 @@ +#if !defined(__KVMGR_H__) + +#define __KVMGR_H__ 1 + +#include "htab.h" +#include "mylock.h" +#include "xlist.h" +#include "zarray.h" + +typedef struct { + mylock_t lock; + htab_t htab; + zarray_t data; +} kvmgr_t; + +extern int kvmgr_init(kvmgr_t*, hash_key_fn_t, + int, int, + zarray_item_killer_t); +extern void kvmgr_fini(kvmgr_t*); +extern void* kvmgr_lock(kvmgr_t*, void*, int); +extern int32_t kvmgr_add(kvmgr_t*, void*, void*); +extern void kvmgr_del(kvmgr_t*, void*); +extern int kvmgr_publish(kvmgr_t*, xlist_action_fn_t, void*); +extern int kvmgr_iter(kvmgr_t*, xlist_t*, void*); + +#endif diff --git a/src/include/mylock.h b/src/include/mylock.h new file mode 100644 index 00000000..3fb81df6 --- /dev/null +++ b/src/include/mylock.h @@ -0,0 +1,38 @@ +#if !defined(_MYLOCK_H_) + +#define _MYLOCK_H_ 1 + +#include + +typedef pthread_mutex_t mylock_t; +typedef pthread_rwlock_t my_rwlock_t; + +typedef struct { + int ncap; + int head; + int len; + int isize; + void* data; + pthread_mutex_t mutex; + pthread_cond_t condget; + pthread_cond_t condput; +} cbuf_t; + +extern int mylock_init(mylock_t*); +extern void mylock_fini(mylock_t*); +extern int mylock_try(mylock_t*); +extern int mylock_lock(mylock_t*); +extern int mylock_unlock(mylock_t*); + +extern int my_rwlock_init(my_rwlock_t*); +extern void my_rwlock_fini(my_rwlock_t*); +extern int my_rwlock_rlock(my_rwlock_t*); +extern int my_rwlock_wlock(my_rwlock_t*); +extern int my_rwlock_unlock(my_rwlock_t*); + +extern int cbuf_init(cbuf_t*, int, int); +extern void cbuf_fini(cbuf_t*); +extern int cbuf_put(cbuf_t*, void*); +extern int cbuf_tryput(cbuf_t*, void*); +extern int cbuf_get(cbuf_t*, void*); +#endif diff --git a/src/include/netio.h b/src/include/netio.h new file mode 100644 index 00000000..682614e2 --- /dev/null +++ b/src/include/netio.h @@ -0,0 +1,73 @@ +#if !defined(_NETIO_H_) + +#define _NETIO_H_ 1 + +#include +#include +#include +#include + +#include "dataq.h" +#include "mylock.h" + +typedef int (*msghandler_t)(struct epoll_event*); + +#define IO_MON_INPUT (0x01) +#define IO_MON_OUTPUT (0x02) + +typedef struct { + uint16_t sz; + char* data; +} io_packet_t; + +typedef struct { + mylock_t lock; + int epoll_fd; + struct epoll_event ev; + pthread_t worker; +} iomgr_t; + +typedef struct { + mylock_t lock; + iomgr_t* iomgr; + int fd; + int idx; + int flags; + unsigned int busy : 1; + unsigned int needfree : 1; + uint32_t refcount; + dataq_t outq; + uint64_t seq; + msghandler_t handler; + void* owner; + void* data; +} endpoint_t; + +extern int netio_write(int, char*, int); +extern int netio_read(int, char*, int); +extern int write_packet(int, io_packet_t*); +extern int alloc_packet(io_packet_t*); +extern int read_packet(int, io_packet_t*); +extern void free_packet(io_packet_t*); + +extern endpoint_t* endpoint_get(void); +extern int endpoint_init(endpoint_t*, int, int, int, int); +extern int endpoint_connect(endpoint_t*, char*, int); +extern int endpoint_accept(endpoint_t*, endpoint_t*); +extern int endpoint_set_handler(endpoint_t*, msghandler_t, void*); +extern int endpoint_enq(endpoint_t*, data_item_t*); +extern data_item_t* endpoint_deq(endpoint_t*); +extern endpoint_t* endpoint_ref(endpoint_t*); +extern void endpoint_deref(endpoint_t*); +extern uint64_t endpoint_getseq(endpoint_t*); +extern void endpoint_block_tasks(endpoint_t*); +extern void endpoint_unblock_tasks(endpoint_t*); +extern int endpoint_is_task_blocked(endpoint_t*); + +extern int iomgr_init(iomgr_t*); +extern int iomgr_monitor(iomgr_t*, endpoint_t*); +extern int iomgr_unmonitor(iomgr_t*, endpoint_t*); +extern int iomgr_start(iomgr_t*); +extern int iomgr_fini(iomgr_t*); +extern int iomgr_stop(iomgr_t*); +#endif diff --git a/src/include/objmgr.h b/src/include/objmgr.h new file mode 100644 index 00000000..a70b08a0 --- /dev/null +++ b/src/include/objmgr.h @@ -0,0 +1,78 @@ +#if !defined(__OBJMGR_H__) + +#define __OBJMGR_H__ + +#include "config.h" + +#include +#include +#include + +#include "htab.h" +#include "mylock.h" +#include "zarray.h" + +#define OBJ_MAGIC (0x4a424f58) + +#define OBJREF_NOP (0) /* ref obj without lock, \ + * just keep object alive */ +#define OBJREF_READ (1) /* ref obj with read lock */ +#define OBJREF_UPDATE (2) /* ref obj with write lock */ + +typedef void* (*obj_create_fn_t)(void*, void*, + va_list); +typedef void (*obj_fini_fn_t)(void*); +typedef void (*objtype_fini_fn_t)(void*); + +typedef struct { + char* type; /* name of type */ + mylock_t lock; + obj_create_fn_t fn_create; /* function to initialize object */ + obj_fini_fn_t fn_fini; /* function to finalize obj */ + objtype_fini_fn_t fn_type_fini; /* function to finalize typeinfo */ + void* typedata; /* extra information for type */ +} objtype_t; + +typedef struct { + uint32_t magic; + uint32_t nref; + my_rwlock_t rwlock; + mylock_t lock; + objtype_t* type; + int32_t exdata; + uint32_t nread : 28; + uint32_t nwrite : 4; +} myobj_t; + +typedef struct { + mylock_t lock; + htab_t names; + zarray_t types; +} objmgr_t; + +#define MYOBJ_TO_OBJ(type, myobj) \ + ((type)(((char*)myobj) + sizeof(myobj_t))) + +#define TO_MYOBJ(obj) \ + ((myobj_t*)(((char*)obj) - sizeof(myobj_t))) + +#define DEREF_OBJ(obj) \ + if ((obj) != NULL) { \ + obj_deref(obj); \ + (obj) = NULL; \ + } + +extern int objmgr_init(objmgr_t*); +extern void objmgr_fini(objmgr_t*); +extern int objmgr_register(objmgr_t*, objtype_t*); +extern int obj_init(objmgr_t*, objtype_t*, int32_t, myobj_t*); +extern void* create_obj_by_typeid(objmgr_t*, int, ...); +extern void* create_obj_by_typename(objmgr_t*, char*, ...); +extern void* obj_ref(void*, int); +extern void obj_deref(void*); +extern int typeid_of_name(objmgr_t*, char*); +extern objmgr_t* objmgr_get_default(); +extern int objmgr_set_default(objmgr_t*); +extern myobj_t* obj_alloc(size_t); + +#endif diff --git a/src/include/objs.h b/src/include/objs.h new file mode 100644 index 00000000..0bb13a19 --- /dev/null +++ b/src/include/objs.h @@ -0,0 +1,9 @@ +#if !defined(_OBJS_H_) + +#define _OBJS_H_ 1 + +#include "xce/types.h" + +job_pidinfo_t *new_job_pidinfo(job_pidinfo_t *); + +#endif diff --git a/src/include/request.h b/src/include/request.h new file mode 100644 index 00000000..0c4316f2 --- /dev/null +++ b/src/include/request.h @@ -0,0 +1,82 @@ +#if !defined(_REQUEST_H_) + +#define _REQUEST_H_ 1 + +#include +#include +#include + +#include "netio.h" +#include "typemap.h" +#include "utils.h" +#include "xce/types.h" + +typedef struct { + int wait; +} reqbar_t; + +typedef struct { + data_item_t link; + endpoint_t* ep; + xce_peerinfo_t* from; + io_packet_t pkt; + struct capn c; + struct Request rq; + uint32_t nrefs; +} ioctx_t; + +#define ITPTR_TO_IOCTX(p) \ + ((ioctx_t*)(((char*)p) - offsetof(ioctx_t, link))) + +typedef int (*xce_check_fn_t)(void*); + +extern ioctx_t* ioctx_alloc(endpoint_t*, xce_peerinfo_t*); +extern int ioctx_ref(ioctx_t*); +extern void ioctx_deref(ioctx_t*, int); +extern int ioctx_flush(ioctx_t*, int); +extern int ioctx_encode(ioctx_t*, xce_request_t*); +extern int ioctx_decode(ioctx_t*, xce_request_t*); + +extern int xce_reply(endpoint_t*, xce_peerinfo_t*, xce_reply_t*); +extern int xce_hello_req(ioctx_t*, char*); +extern int xce_nop_req(ioctx_t*); +extern int xce_shutdown_req(ioctx_t*); +extern void init_reply_by_req(xce_reply_t*, xce_request_t*); +extern int xce_join_req(ioctx_t*, int, hostattrs_t*); +extern int xce_pushconfig_req(endpoint_t*, + xce_peerinfo_t*, + xce_configdata_t*); +extern int xce_push_data_req(endpoint_t*, xce_peerinfo_t*, + xce_data_t*, xce_check_fn_t, + void*, int); + +extern int xce_workerlist_req(ioctx_t*, xce_peerinfo_t*); +extern int xce_reply_workerlist(endpoint_t*, uint64_t, int, + xce_peerinfo_t*, xce_workerlist_t*); +extern int xce_jobdispatch_req(ioctx_t*, xce_job_dispatch_t*); +extern int xce_jobsubmit_req(ioctx_t*, xce_job_submit_t*); +extern int xce_reply_jobdispatch(endpoint_t*, uint64_t, int32_t, + xce_peerinfo_t*); +extern int xce_reply_jobid(endpoint_t*, int, + uint64_t, uint64_t, + xce_peerinfo_t*); +extern int xce_joblist_req(ioctx_t*, xce_peerinfo_t*); +extern int xce_reply_joblist(endpoint_t*, uint64_t, int, + xce_peerinfo_t*, xce_job_list_t*); +extern int xce_startjob_req(ioctx_t*, xce_job_exec_t*); +extern int xce_clusterconf_req(ioctx_t*); +extern int xce_reply_clusterconf(endpoint_t*, uint64_t, int, + xce_peerinfo_t*, + xce_clusterconf_t*); +extern int xce_get_req(ioctx_t*, xce_get_t*); +extern int xce_reply_get(endpoint_t*, xce_peerinfo_t*, + xce_reply_t*, xce_check_fn_t, + void*, int); +extern int xce_notify_req(ioctx_t*, xce_notify_data_t*); +extern int extract_data(dataset_t*, xce_data_t*); +extern int xce_update_req(ioctx_t*, xce_update_data_t*); +extern int xce_jobctrl_req(ioctx_t*, xce_jobctrl_t*); +extern int xce_queuectrl_req(ioctx_t*, xce_queuectrl_t*); +extern int xce_runtask_req(ioctx_t* , xce_taskrun_t *) ; + +#endif diff --git a/src/include/typemap.h b/src/include/typemap.h new file mode 100644 index 00000000..cba95bab --- /dev/null +++ b/src/include/typemap.h @@ -0,0 +1,192 @@ +#if !defined(_TYPEMAP_H_) + +#define _TYPEMAP_H_ 1 +#include + +#include "xce/types.h" + +typedef struct { + char* resname; + char* hostname; +} xce_reskey_t; + +typedef struct { + int type; + union { + uint64_t jobid; + char* wname; + xce_reskey_t* reskey; + } condition; +} xce_match_t; + +typedef struct { + int table; + int nrows; + void* rows; +} dataset_t; + +typedef struct { + int role; + int data_which; + union { + hostattrs_t* attrs; + } data; +} xce_joindata_t; + +typedef struct { + char* clustername; + int n_confvars; + xce_config_t** confvars; + int n_resources; + xce_resource_t** resources; + int n_queues; + xce_queue_t** queues; + int n_ugroups; + xce_group_t** ugroups; + int n_hgroups; + xce_group_t** hgroups; + int nresvals; + xce_val_with_idx_t** resvals; +} xce_conf4sched_t; + +typedef struct { + char* clustername; + int n_confvars; + xce_config_t** confvars; +} xce_conf4worker_t; + +typedef struct { + int data_which; + union { + xce_conf4sched_t* conf4sched; + xce_conf4worker_t* conf4worker; + } data; +} xce_configdata_t; + +typedef struct { + int n_total; + int pos; + int count; + xce_job_t** jobs; +} xce_jobs_data_t; + +typedef struct { + int n_total; + int pos; + int count; + xce_worker_t** workers; +} xce_workers_data_t; + +typedef struct { + int n_total; + int pos; + int count; + xce_resource_t** resources; +} xce_resource_data_t; + +typedef struct { + int n_total; + int pos; + int count; + xce_resval_t** vals; +} xce_resval_data_t; + +typedef struct { + int count; + xce_resval_t** vals; +} xce_resval_list_t; + +typedef struct { + uint64_t jobid; + int npids; + int* pids; + int npgids; + int* pgids; + int count; + xce_rusage_t** usages; +} xce_job_rusages_t; + +typedef struct { + int table; + union { + xce_jobs_data_t* jobs; + xce_workers_data_t* workers; + xce_resource_data_t* resources; + xce_resval_data_t* resvals; + } data; +} xce_data_t; + +typedef struct { + int table; + xce_match_t* condition; +} xce_get_t; + +typedef struct { + int event; + union { + job_pidinfo_t* pidinfo; + job_failinfo_t* failinfo; + job_failinfo_t* dispatchfail; + xce_jobfinish_t* finishinfo; + uint64_t sched_start_job; + uint64_t sched_exit_job; + uint64_t sched_fail_job; + xce_job_t* sched_update_job; + xce_resval_list_t* sched_update_resvals; + uint64_t stopped_job; + uint64_t resumed_job; + xce_ckptinfo_t* ckptinfo; + xce_queue_t* sched_update_queue; + xce_task_pidinfo_t* taskinfo; + xce_task_failinfo_t* taskfailinfo; + xce_task_finish_t* taskfinish; + uint64_t pdone_job; + } data; +} xce_notify_data_t; + +typedef struct { + int table; + union { + xce_resval_list_t* resvals; + xce_job_rusages_t* jobrusages; + } data; +} xce_update_data_t; + +typedef struct { + uint64_t seq; + uint32_t opcode; + int32_t status; + int data_which; + union { + char* debugmsg; + uint64_t jobid; + xce_data_t* getdata; + xce_clusterconf_t* clusterconf; + } data; +} xce_reply_t; + +typedef struct { + uint32_t opcode; + uint64_t seq; + xce_peerinfo_t* from; + int body_which; + union { + xce_reply_t* replymsg; + char* hellomsg; + xce_joindata_t* joinmsg; + xce_configdata_t* configpushmsg; + xce_data_t* pushmsg; + xce_get_t* getmsg; + dataset_t* datamsg; + xce_job_dispatch_t* dispatchmsg; + xce_job_exec_t* jobstartmsg; + xce_notify_data_t* notifymsg; + xce_job_submit_t* jobsubmsg; + xce_update_data_t* updatemsg; + xce_jobctrl_t* jobctrlmsg; + xce_queuectrl_t* queuectrlmsg; + xce_taskrun_t* runtaskmsg; + } body; +} xce_request_t; + +#endif diff --git a/src/include/utils.h b/src/include/utils.h new file mode 100644 index 00000000..38b4edcc --- /dev/null +++ b/src/include/utils.h @@ -0,0 +1,94 @@ +#if !defined(_UTILS_H_) + +#define _UTILS_H_ + +#include "config.h" + +#include +#include +#include +#include + +#include "controller.capnp.h" +#include "xce/errnox.h" +#include "xce/types.h" + +#define xce_use(x) (void)(x) + +#define float_near_zero (0.000001) + +#define float_equal(a, b) (fabs((a) - (b)) < float_near_zero) + +#define STR(x) _STR(x) +#define _STR(x) #x + +#define MK_VERSION(ver, commit) ver commit + +#ifndef FREEUP +#define FREEUP(p) \ + if ((p) != NULL) { \ + free(p); \ + (p) = NULL; \ + } +#endif + +#define N_EL_ARRAY(arr) (sizeof(arr) / sizeof(arr[0])) +#define PTR_STEP(p, delta) \ + ((void*)(((char*)p) + (delta))) + +#define N_EL_ARRAY(arr) (sizeof(arr) / sizeof(arr[0])) +#define PTR_STEP(p, delta) \ + ((void*)(((char*)p) + (delta))) + +/* move the owner ship of pointer from src to dst */ +#define MOVE_PTR(dst, src) \ + do { \ + (dst) = (src); \ + (src) = NULL; \ + } while (0) + +#define NULLSTR(p) (((p) == NULL) || (strlen(p) == 0)) + +#define SET_ERROR(code) \ + do { \ + set_error((char*)__FILE__, \ + (char*)__func__, \ + __LINE__, \ + (code)); \ + } while (0) + +#define PERROR(s) xce_perror(s) + +typedef struct { + char* file; + char* func; + int line; + int code; +} ectx_t; + +#define TRACE(...) +#define WARN(...) + +extern capn_text chars_to_text(const char*); +extern int parse_argv(char*, char***); +extern void free_argv(char**, int); +extern void freeup_kvs(int, xce_kv_t*); +extern int mylog_init(char*, char*, char*, int, int); +extern void mylog_fini(void); +extern int mylog_setlevel(char*); +extern void set_error(char*, char*, int, int); +extern ectx_t* get_ectx(void); +extern int xce_vprintf(const char*, va_list); +extern int xce_strerror_r(int, char*, size_t); +extern void xce_perror(const char*); +extern char* frame_symbol(int); +extern int copy_int_list(int**, int*, int); +extern int copy_strlist(xce_strlist_t*, xce_strlist_t); +extern void free_timewindow_config(xce_timewindow_config_t*); +extern xce_timewindow_config_t* dup_timewindow_config(xce_timewindow_config_t*); +extern void free_resource_thresholds(xce_res_threshold_t**, int); +extern xce_res_threshold_t** dup_resource_thresholds(xce_res_threshold_t**, int); +extern void free_resval_with_idx_list(xce_val_with_idx_t***, int); +extern void free_strlist(xce_strlist_t*); + +#endif diff --git a/src/include/vtaskmgr.h b/src/include/vtaskmgr.h new file mode 100644 index 00000000..d530be0a --- /dev/null +++ b/src/include/vtaskmgr.h @@ -0,0 +1,61 @@ +#if !defined(_VTASKMGR_H_) + +#define _VTASKMGR_H_ 1 + +#include +#include + +#include "dataq.h" +#include "mylock.h" +#include "netio.h" +#include "request.h" + +typedef int (*vtask_func_t)(void*); + +typedef struct { + void* owner; + ioctx_t ctx; + int vcpu; + vtask_func_t entry; +} vtask_t; + +#define ITPTR_TO_VTASK(p) \ + ((vtask_t*)(((char*)p) - offsetof(ioctx_t, link) - offsetof(vtask_t, ctx))) + +typedef enum { + VCPU_IDLE = 0, + VCPU_BUSY, + VCPU_ERR +} vcpu_state_t; + +typedef struct { + int cpuid; + vcpu_state_t state; + void* owner; + cbuf_t wbuf; + vtask_t* task; + pthread_t vcpu; +} vcpu_t; + +typedef struct { + int n_vcpus; + pthread_t dispatcher; + vcpu_t* vcpus; + cbuf_t wbuf; + cbuf_t wtbuf; /* used to wake up vtaskmgr to check tasks */ + dataq_t taskq; +} vtaskmgr_t; + +extern vtask_t* vtask_alloc(); +extern int vtask_init(vtask_t*, vtask_func_t, endpoint_t*); +extern void vtask_fini(vtask_t*); + +extern int vtask_enq(vtaskmgr_t*, vtask_t*); + +extern int vtaskmgr_init(vtaskmgr_t*, int); +extern int vtaskmgr_start(vtaskmgr_t*); +extern void vtaskmgr_fini(vtaskmgr_t*); +extern void vtaskmgr_wait(vtaskmgr_t *); +extern void vtaskmgr_wakeup(vtaskmgr_t *); + +#endif diff --git a/src/include/xce/cluster_def.h b/src/include/xce/cluster_def.h new file mode 100644 index 00000000..770fde47 --- /dev/null +++ b/src/include/xce/cluster_def.h @@ -0,0 +1,168 @@ +#ifndef XCE_CLUSTER_DEF_H +#define XCE_CLUSTER_DEF_H + +#include "config.h" + +#include +#include + +#include "hook.h" +#include "htab.h" +#include "kvmgr.h" +#include "myconf.h" +#include "mylock.h" +#include "netio.h" +#include "objmgr.h" +#include "vtaskmgr.h" +#include "xce/types.h" +#include "xlist.h" +#include "zarray.h" + +#define N_CONTROLLER_MAX (16) + +enum { + XCE_CONTROLLER_HOOK_JOB = 0, + XCE_CONTROLLER_HOOK_WORKER, + XCE_CONTROLLER_HOOK_SCHEDULER, + XCE_CONTROLLER_HOOK_CLUSTER, + XCE_CONTROLLER_HOOK_RESOURCE, + XCE_CONTROLLER_HOOK_CTRL_REQ, + XCE_CONTROLLER_HOOK_QUEUE, + XCE_CONTROLLER_HOOK_USERGROUP, + XCE_CONTROLLER_HOOK_HOSTGROUP, + XCE_CONTROLLER_HOOK_MAX /* keep this as the max */ +}; + +enum { + HOOK_DETAIL_JOB_NEW = 0, + HOOK_DETAIL_JOB_START, + HOOK_DETAIL_JOB_EXIT, + HOOK_DETAIL_JOB_FAIL, + HOOK_DETAIL_JOB_UPDATE, + HOOK_DETAIL_JOB_CKPT, + HOOK_DETAIL_WORKER_JOIN, + HOOK_DETAIL_WORKER_DEAD, + HOOK_DETAIL_WORKER_UPDATE, + HOOK_DETAIL_SCHEDULER_JOIN, + HOOK_DETAIL_SCHEDULER_DEAD, + HOOK_DETAIL_CLUSTER_INIT, + HOOK_DETAIL_DB_INIT, + HOOK_DETAIL_CLUSTER_SHUTDOWN, + HOOK_DETAIL_DB_SHUTDOWN, + HOOK_DETAIL_RESOURCE_UPDATE, + HOOK_DETAIL_RESOURCE_LOC_UPDATE, + HOOK_DETAIL_CTRL_REQ_FINISH, + HOOK_DETAIL_QUEUE_UPDATE, + HOOK_DETAIL_USERGROUP_UPDATE, + HOOK_DETAIL_HOSTGROUP_UPDATE +}; + +#define XCE_NS_CONFIG (0) +#define XCE_NS_UGROUP (1) +#define XCE_NS_HGROUP (2) +#define XCE_NS_MAX (2) + +typedef struct { + int role; + union { + int idx; + } u; +} ep_private_t; + +typedef struct { + endpoint_t* ep; +} controller_t; + +typedef struct { +} metrics_t; + +typedef struct { + xce_queue_t queue; +} queue_t; + +typedef struct { + xce_job_t job; +} job_t; + +typedef struct { + mylock_t lock; + htab_t htab; + zarray_t jobs; +} jobmgr_t; + +typedef struct { + mylock_t lock; + htab_t htab; + int nshared; + int nunshared; + zarray_t defs; + zarray_t sharedinst; +} resmgr_t; + +typedef struct { + mylock_t lock; + htab_t htab; + zarray_t workers; +} workermgr_t; + +typedef struct { + mylock_t lock; + htab_t htab; + zarray_t queues; +} qmgr_t; + +typedef struct { + mylock_t lock; + endpoint_t* ep; +} scheduler_t; + +typedef struct { + DBPool* db_pool; + DBHandle* db_handle; + pthread_t fetch_thread; + int64_t fetch_job_pos; + int fetch_job_interval; + int running; + mylock_t db_lock; +} db_ctx_t; + +typedef struct { + pthread_t thread; + int runing; + int interval; +} ctrlreq_ctx_t; + +typedef struct { + mylock_t lock; + ctrlreq_ctx_t ctrlreq_ctx; +} ctrl_req_mgr_t; + +typedef struct { + myconf_t* myconf; + xce_peerinfo_t* myhost; + hooksys_t hooksys; + iomgr_t iomgr; + objmgr_t objmgr; + zarray_t endpoints; + endpoint_t ep; + zarray_t configs; + controller_t controllers[N_CONTROLLER_MAX]; + int myidx; + int master; + int ncontrollers; + scheduler_t sched; + jobmgr_t jobmgr; + resmgr_t resmgr; + workermgr_t workermgr; + qmgr_t qmgr; + kvmgr_t configmgr; + kvmgr_t ugmgr; + kvmgr_t hgmgr; + vtaskmgr_t vtaskmgr; + cbuf_t wbuf; + int running; + db_ctx_t dbctx; + ctrl_req_mgr_t ctrl_req_mgr; +} cluster_t; + +#endif /* XCE_CLUSTER_DEF_H */ diff --git a/src/include/xce/errnox.h b/src/include/xce/errnox.h new file mode 100644 index 00000000..eadee394 --- /dev/null +++ b/src/include/xce/errnox.h @@ -0,0 +1,26 @@ +#if !defined(__XCE_ERRNOX_H__) + +#define __XCE_ERRNOX_H__ 1 + +#include +#include +#include + +#define XCE_ERRNO_BASE (10001) + +enum { + E_XCE_BAD_JOB = XCE_ERRNO_BASE, + E_XCE_BAD_WORKER, + E_XCE_DUP_JOB, + E_XCE_DUP_WORKER, + E_XCE_BAD_OPCODE, + E_XCE_BAD_ROLE, + E_XCE_BAD_RES, + E_XCE_BAD_QUEUE, + E_XCE_BAD_GROUP, + E_XCE_INTERNAL, + E_XCE_MAX +}; + + +#endif diff --git a/src/include/xce/types.h b/src/include/xce/types.h new file mode 100644 index 00000000..b499e522 --- /dev/null +++ b/src/include/xce/types.h @@ -0,0 +1,619 @@ +#if !defined(_XCE_TYPES_H_) + +#define _XCE_TYPES_H_ + +#include "config.h" + +#include +#include + +#include "xlist.h" +#include "zarray.h" + +#define XCE_VAL_STRING (0) +#define XCE_VAL_NUMERIC (1) +#define XCE_VAL_BOOLEAN (2) + +typedef enum { + XCE_ORD_INCR = 0, + XCE_ORD_DECR, + XCE_ORD_NA +} xce_order_t; + +typedef struct { + int which; + union { + int32_t ivalue32; + uint32_t uvalue32; + int64_t ivalue64; + uint64_t uvalue64; + char* svalue; + double fvalue; + int bvalue; + } u; +} xce_val_t; + +typedef struct { + int idx; + xce_val_t* val; +} xce_val_with_idx_t; + +typedef struct { + char* name; + char* host; + xce_val_t* val; +} xce_resval_t; + +typedef struct { + int field; + xce_val_t value; +} xce_kv_t; + +typedef struct { + int count; + xce_kv_t* vals; +} xce_kv_list_t; + +typedef struct { + int day; /* 1 - 7 (Mon to Sun, 0 unspecified) */ + int hour; /* 0 - 23 */ + int min; /* 0 - 59 */ +} xce_timewindow_time_t; + +typedef struct { + char* tz; + xce_timewindow_time_t* open; + xce_timewindow_time_t* close; +} xce_timewindow_seg_config_t; + +typedef struct { + int nsegs; + xce_timewindow_seg_config_t** segs; +} xce_timewindow_config_t; + +#define XCE_RESF_BUILTIN (0x01) +#define XCE_RESF_DYNAMIC (0x02) +#define XCE_RESF_GLOBAL (0x04) +#define XCE_RESF_SHARED (0x08) +#define XCE_RESF_EXTERNAL (0x10) +#define XCE_RESF_RELEASE (0x20) +#define XCE_RESF_DEFAULT_HOST (0x40) +#define XCE_RESF_CONSUMABLE (0x80) + +typedef struct { + int count; + void* data; +} xce_list_t; + +typedef struct { + int count; + int* data; +} xce_intlist_t; + +typedef struct { + int count; + char** data; +} xce_strlist_t; + +typedef struct { + char* name; + char* key; +} xce_peerinfo_t; + +typedef struct { + char* name; + char* value; +} xce_config_t; + +typedef struct { + int count; + xce_config_t** configs; +} xce_configlist_t; + +typedef struct { + char* name; + xce_strlist_t members; + xce_strlist_t ex_members; +} xce_group_t; + +typedef struct { + int count; + xce_group_t** groups; +} xce_grouplist_t; + +typedef struct { + xce_val_t* value; + int nhosts; + char** hosts; +} res_distribution_t; + +typedef struct { + char* name; + char* desc; + int idx; + int valtype; + xce_order_t ordtype; + int flags; + int interval; + time_t last_report; + int ndistributions; + res_distribution_t** distributions; + xce_val_t* hbased_defined; +} xce_resource_t; + +typedef struct { + int count; + xce_resource_t** res; +} xce_reslist_t; + +typedef struct { + char* name; + double sched; + double stop; +} xce_res_threshold_t; + +typedef struct { + char* name; + char* hostmodel; + char* hosttype; + int mxj; + int nresources; + xce_config_t** resources; + int nthresholds; + xce_res_threshold_t** thresholds; + xce_timewindow_config_t* dispatchwindow; +} xce_hostconfig_t; + +#define XCE_WORKER_UNAVAIL (0x00010000) +#define XCE_WORKER_LOCKEDU (0x00020000) +#define XCE_WORKER_LOCKEDW (0x00040000) +#define XCE_WORKER_BUSY (0x00080000) +#define XCE_WORKER_CLOSED (0x00100000) + +#define IS_WORKER_UNAVAIL(status) \ + (((status) & XCE_WORKER_UNAVAIL) != 0) +#define IS_WORKER_LOCKEDU(status) \ + (((status) & XCE_WORKER_LOCKEDU) != 0) +#define IS_WORKER_LOCKEDW(status) \ + (((status) & XCE_WORKER_LOCKEDW) != 0) +#define IS_WORKER_LOCKED(status) \ + (IS_WORKER_LOCKEDU(status) || IS_WORKER_LOCKEDW(status)) +#define IS_WORKER_BUSY(status) \ + (((status) & XCE_WORKER_BUSY) != 0) + +typedef struct { + char* hosttype; + char* hostmodel; + double cpufactor; + int maxcpus; + double maxmem; + double maxswap; + double maxtmp; + int ndisks; +} hostattrs_t; + +typedef struct { + uint64_t start; + uint64_t end; +} xce_timerange_t; + +typedef struct { + int nsegs; + xce_timerange_t* ranges; +} xce_timewindow_t; + +typedef struct { + char* name; + hostattrs_t* attrs; + uint32_t status; + zarray_t resvals; + time_t dead_since; + int64_t pending_ctrl; + xce_timewindow_config_t* dispatch_window_config; + int nthresholds; + xce_res_threshold_t** thresholds; + /* following two vars used to push resource values to sched */ + int nresvals_to_sched; + xce_val_with_idx_t** resvals_to_sched; +} xce_worker_t; + +typedef struct { + int count; + xce_worker_t** workers; +} xce_workerlist_t; + +typedef struct { + char* host; + int nranks; +} xce_host_launch_t; + +typedef struct { + int nhosts; + xce_host_launch_t** hosts; +} xce_launch_t; + +typedef struct { + char* exechome; + char* execcwd; + char* execuser; + char* cmdline; + char* exdata; + char* launch_type; + char* q_pre_exec; + char* q_post_exec; + char* job_pre_exec; + char* job_post_exec; +} job_startinfo_t; + +typedef struct { + uint64_t jobid; + int npids; + unsigned int* pids; + int npgids; + unsigned int* pgids; + char* exdata; +} job_pidinfo_t; + +typedef struct { + uint64_t jobid; + uint32_t stage; + int code; + char* detail; +} job_failinfo_t; + +typedef struct { + char* resname; + char* reserve; + uint32_t instid; + double value; + uint64_t from; + int64_t duration; +} xce_alloc_t; + +typedef struct { + char* host; + int nallocs; + xce_alloc_t** allocs; +} xce_host_alloc_t; + +typedef struct { + uint64_t jobid; + int nhosts; + xce_host_alloc_t** allocs; +} xce_job_alloc_t; + +typedef struct { + int njobs; + xce_job_alloc_t** allocs; +} xce_job_dispatch_t; + +typedef struct { + char* queue; + char* user; + char* cmdline; + char* resreq; + char* exdata; + char* pre_exec; + char* post_exec; + uint32_t mintasks; + uint32_t maxtasks; +} xce_job_submit_t; + +typedef struct { + int exitcode; +} job_exitinfo_t; + +#define JOB_STAT_NULL 0x00 /**< NULL. */ +#define JOB_STAT_PEND 0x01 /**< Job is submitted. */ +#define JOB_STAT_RUN 0x02 /**< Job is running. */ +#define JOB_STAT_EXIT 0x04 /**< Job is exit. */ +#define JOB_STAT_DONE 0x08 /**< Job is done. */ +#define JOB_STAT_PSUSP 0x10 /**< Job is pending and suspend*/ +#define JOB_STAT_USUSP 0x20 /**< Job is user suspend*/ +#define JOB_STAT_SSUSP 0x40 /**< Job is system suspend*/ + +#define JOB_STAT_PDONE (0x80) /**< Post job process done successfully */ +#define JOB_STAT_PERR (0x100) /**< Post job process has error */ +#define JOB_STAT_WAIT (0x200) /**< Chunk job waiting its turn to exec */ +#define JOB_STAT_RUNKWN 0x8000 /* Flag : Job status is UNKWN caused by losting contact with remote cluster */ +#define JOB_STAT_UNKWN 0x10000 /**< The worker on the host on which the \ + * job is processed has lost contact with controller */ +#define JOB_STAT_PROV (0x20000) /**< this state shows that the job is dispatched to a standby \ + * power saved host, and this host is \ + * being waken up or started up */ +#define JOB_STAT_ERR (0x40000) /**ERROR */ + +#define JOB_EXEC_STAGE_Q_PRE_EXEC (0) +#define JOB_EXEC_STAGE_PRE_EXEC (1) +#define JOB_EXEC_STAGE_MAIN (2) +#define JOB_EXEC_STAGE_POST_EXEC (3) +#define JOB_EXEC_STAGE_Q_POST_EXEC (4) + +#define QUEUE_STAT_OPEN 0x00 /**< OPEN. */ +#define QUEUE_STAT_CLOSED 0x01 /**< The queue is closed */ +#define QUEUE_STAT_INACT_WINDOW 0x02 /**< The queue inactivated due to dispatch or run windows closed */ +#define QUEUE_STAT_INACT_ADMIN 0x04 /**< The queue inactivated by admin */ +#define QUEUE_STAT_NOPERM 0x08 /**< Remote queue rejecting jobs. */ +#define QUEUE_STAT_DISC 0x10 /**< Remote queue status is disconnected. */ +#define QUEUE_STAT_FAIRSHARE_DEFAULT 0x20 /**< Fairshare queue with null user share defined*/ + +typedef enum { + NORMAL = 0, + TTY, + XJOB, + DISPLAY +} xce_job_type; + +typedef struct { + char* host_name; + int num_slots; +} xce_job_host_slots_t; + +typedef struct { + int num_hosts; + xce_job_host_slots_t* host_slots; +} xce_job_slots_alloc_t; + +typedef struct { + char* host_name; + int cpu_time; + double mem_usage; +} xce_host_runusage_t; + +typedef struct { + double max_mem; + double avg_mem; + double used_mem; + int cpu_time; + int peak_cpu_time; + int peak_cpu_duration; + float mem_efficiency; + float avg_cpu_efficiency; + float peak_cpu_efficiency; + int num_hosts; + xce_host_runusage_t** host_runusage; +} xce_job_runusage_t; + +typedef struct { + uint64_t jobid; + char* ckptinfo; +} xce_ckptinfo_t; + +typedef struct { + uint64_t jobid; + uint64_t array_base_id; + int array_idx; + char* queue; + char* user; + int64_t idx; + time_t sub_time; + time_t queue_time; + time_t start_time; + time_t finish_time; + uint32_t mintasks; + uint32_t maxtasks; + job_pidinfo_t* pidinfo; + job_startinfo_t* start_info; + unsigned int state; + char* job_name; + char* project_name; + char* user_group; + char* job_description; + char* resreq; + xce_job_alloc_t* allocs; + int run_time; + xce_job_runusage_t* run_usage; + job_exitinfo_t* exit_info; + char* ckptinfo; + int64_t pending_ctrl; +} xce_job_t; + +typedef struct { + int count; + xce_job_t** data; +} xce_job_list_t; + +typedef struct { + uint64_t jobid; + job_startinfo_t* start_info; + xce_launch_t* launchinfo; +} xce_job_exec_t; + +typedef struct { + uint64_t jobid; + job_pidinfo_t pidinfo; +} xce_job_runinfo_t; + +typedef struct { + uint64_t jobid; + int exit_code; +} xce_jobfinish_t; + +typedef struct { + char* queue; + uint32_t attrs; + uint32_t status; + int32_t priority; + int32_t accept_interval; + int32_t sched_delay; + char* resreq; + xce_group_t* users; + xce_group_t* hosts; + int32_t nthresholds; + xce_res_threshold_t** thresholds; + xce_timewindow_t* runwindow; + xce_timewindow_t* dispatchwindow; + xce_timewindow_config_t* runwindow_config; + xce_timewindow_config_t* dispatchwindow_config; + int64_t pending_ctrl; + char* pre_exec; + char* post_exec; +} xce_queue_t; + +typedef struct { + int count; + xce_queue_t** queues; +} xce_queuelist_t; + +typedef struct { + char* name; + xce_reslist_t reslist; + xce_queuelist_t qlist; + xce_workerlist_t wlist; + xce_grouplist_t uglist; + xce_grouplist_t hglist; + xce_configlist_t cfglist; +} xce_clusterconf_t; + +typedef enum { + CONTROL_NONE = 0, + CONTROL_JOB, + CONTROL_HOST, + CONTROL_QUEUE, + CONTROL_CLUSTER, + CONTROL_DEBUG +} ctrl_target_type_t; + +typedef enum { + JOB_DO_NONE = 0, + JOB_STOP, + JOB_RESUME, + JOB_KILL, + JOB_MIG, + JOB_REQUEUE, + JOB_MODIFY, + JOB_SWITCH, + JOB_CHKPNT, + JOB_POST, + JOB_READ, + JOB_TOP, + JOB_BOT +} job_ctrl_type_t; + +typedef enum { + HOST_DO_NONE = 0, + HOST_OPEN, + HOST_CLOSE, + HOST_TAG, + HOST_UNTAG +} host_ctrl_type_t; + +typedef enum { + QUEUE_DO_NONE = 0, + QUEUE_OPEN, + QUEUE_CLOSE, + QUEUE_INACTIVE, + QUEUE_ACTIVE +} queue_ctrl_type_t; + +typedef struct { + uint64_t jobid; + int signal; + int forcekill; + char* method; + char* comment; +} job_ctrl_content_t; + +typedef struct { + char* hostname; + char* comment; +} host_ctrl_content_t; + +typedef struct { + char* queuename; + char* comment; +} queue_ctrl_content_t; + +typedef struct { + int64_t id; + int target_type; + int action_type; + time_t request_time; + char* user; + void* content; +} xce_ctrl_req_t; + +typedef struct { + int signo; + int force; +} xce_signal_t; + +typedef struct { + int kill; + char* method; +} xce_ckpt_options_t; + +typedef struct { + int action; + uint64_t jobid; + union { + xce_signal_t* siginfo; + xce_ckpt_options_t* ckptoption; + } u; +} xce_jobctrl_t; + +typedef struct { + int action; + char* queue; +} xce_queuectrl_t; + +typedef struct { + int action; + char* hostname; +} xce_hostctrl_t; + +typedef struct { + char* host; + char* launch_type; /* MPI ranks or something others */ + int ntasks; + char* exechome; + char* execcwd; + char* execuser; + char* cmdline; + char* exdata; +} xce_taskhost_t; + +typedef struct { + uint64_t jobid; + int nhosts; + int clientidx; + xce_taskhost_t** taskhosts; +} xce_taskrun_t; + +typedef struct { + uint64_t jobid; + char* host; + int clientidx; + int taskidx; + int npids; + unsigned int* pids; + int npgids; + unsigned int* pgids; + char* exdata; +} xce_task_pidinfo_t; + +typedef struct { + uint64_t jobid; + char* host; + int clientidx; + int taskidx; /* taskidx == -1 for fail of all tasks + * in the same host of xcecli_runtask() + */ + int code; + char* detail; +} xce_task_failinfo_t; + +typedef struct { + uint64_t jobid; + char* host; + int taskidx; + int clientidx; + int exit_code; +} xce_task_finish_t; + +typedef struct { + char* resname; + float value; +} xce_rusage_t; + +#endif diff --git a/src/include/xceapi.h b/src/include/xceapi.h new file mode 100644 index 00000000..0dcb5cf1 --- /dev/null +++ b/src/include/xceapi.h @@ -0,0 +1,34 @@ +#if !defined(_XCEAPI_H_) + +#define _XCEAPI_H_ 1 + +#include "config.h" + +#include "xce/types.h" +#include "xcectx.h" + +extern int xce_hello(xce_ctx_t*, char*); +extern int xce_shutdown(xce_ctx_t*); +extern int xce_reslist(xce_ctx_t*, xce_resource_t***); +extern int xce_join(xce_ctx_t*, int, hostattrs_t*); +extern int xce_workerlist(xce_ctx_t*, xce_worker_t***); +extern int xce_jobdispatch(xce_ctx_t*, xce_job_dispatch_t*); +extern int xce_jobsubmit(xce_ctx_t*, xce_job_submit_t*, + uint64_t*); +extern int xce_joblist(xce_ctx_t*, xce_job_t***); +extern int xce_clusterconf(xce_ctx_t*, xce_clusterconf_t**); +extern int xce_push(xce_ctx_t*, xce_check_fn_t, + void*, int, int, int, void**); +extern int xce_update_rows(xce_ctx_t*, int, int, xlist_t*); +extern int xce_resval(xce_ctx_t*, char*, + char*, xce_resval_t***); + +extern int xce_notify(xce_ctx_t*, xce_notify_data_t*); +extern int xce_update_resvals(xce_ctx_t*, int, xce_resval_t**); +extern int xce_jobctrl(xce_ctx_t*, xce_jobctrl_t*); +extern int xce_queuectrl(xce_ctx_t*, xce_queuectrl_t*); +extern int xce_runtask(xce_ctx_t*, xce_taskrun_t*); +extern int xce_update_jusage(xce_ctx_t*, uint64_t, int, + int*, int, int*, int, xce_rusage_t**); + +#endif diff --git a/src/include/xcectx.h b/src/include/xcectx.h new file mode 100644 index 00000000..22d44492 --- /dev/null +++ b/src/include/xcectx.h @@ -0,0 +1,52 @@ +#if !defined(_XCECTX_H_) + +#define _XCECTX_H_ 1 + +#include "netio.h" +#include "request.h" +#include "vtaskmgr.h" +#include "xce/types.h" + +typedef enum { + XCE_CTX_INIT = 0, + XCE_CTX_RUN, + XCE_CTX_DOWN, + XCE_CTX_BUSY, + XCE_CTX_ERR +} xce_ctx_state_t; + +typedef int (*xce_request_handler_t)(xce_request_t*); + +typedef struct { + xce_ctx_state_t state; + xce_peerinfo_t myinfo; + iomgr_t iomgr; + vtaskmgr_t vtaskmgr; + endpoint_t* ep; + xce_request_handler_t handler; + cbuf_t wbuf; + dataset_t* dataset; + + struct { + union { + char* debugmsg; + dataset_t* get; + uint64_t jobid; + xce_clusterconf_t* clusterconf; + } u; + } reply; +} xce_ctx_t; + +extern int xce_ctx_init(xce_ctx_t*, char*, char*); +extern void xce_ctx_fini(xce_ctx_t*); +extern int xce_ctx_set_handler(xce_ctx_t*, + xce_request_handler_t); +extern int xce_ctx_start(xce_ctx_t*); +extern int xce_ctx_stop(xce_ctx_t*); +extern int xce_wakeup(xce_ctx_t*, int); +extern int xce_try_wakeup(xce_ctx_t*, int); +extern int xce_ctx_set_endpoint(xce_ctx_t*, endpoint_t*); +extern void xce_block_tasks(xce_ctx_t*); +extern void xce_unblock_tasks(xce_ctx_t*); + +#endif diff --git a/src/include/xlist.h b/src/include/xlist.h new file mode 100644 index 00000000..bfcbb3c5 --- /dev/null +++ b/src/include/xlist.h @@ -0,0 +1,21 @@ +#if !defined(__XLIST_H__) + +#define __XLIST_H__ 1 + +typedef int (*xlist_iter_fn_t)(void*, void*); + +typedef struct { + int count; + int caps; + int delta; + void** data; +} xlist_t; + +typedef int (*xlist_action_fn_t)(xlist_t*, void*); + +extern int xlist_init(xlist_t*, int); +extern int xlist_store(xlist_t*, void*); +extern void xlist_clear(xlist_t*); +extern int xlist_iter(xlist_t*, xlist_iter_fn_t, void*); +extern void xlist_fini(xlist_t*); +#endif diff --git a/src/include/xstring.h b/src/include/xstring.h new file mode 100644 index 00000000..524482a7 --- /dev/null +++ b/src/include/xstring.h @@ -0,0 +1,25 @@ +#if !defined(__XSTRING_H__) + +#define __XSTRING_H__ 1 + +#include "objmgr.h" + +typedef struct { + htab_t tab; + zarray_t strings; +} xstring_typedata_t; + +#define XSTRING_OBJ_TYPE_HTAB(obj) \ + (((xstring_typedata_t *)obj->type->typedata)->tab) +#define XSTRING_OBJ_TYPE_STRINGS(obj) \ + (((xstring_typedata_t *)obj->type->typedata)->strings) + +#define XSTRING_TYPE_HTAB(type) \ + (((xstring_typedata_t *)type->typedata)->tab) + +#define XSTRING_TYPE_STRINGS(type) \ + (((xstring_typedata_t *)type->typedata)->strings) + +extern int register_xstring(objmgr_t*, int,int); + +#endif diff --git a/src/include/zarray.h b/src/include/zarray.h new file mode 100644 index 00000000..aebac56a --- /dev/null +++ b/src/include/zarray.h @@ -0,0 +1,32 @@ +#if !defined(_ZARRAY_H_) + +#define _ZARRAY_H_ 1 + +#include "mylock.h" +#include "xlist.h" + +typedef void (*zarray_item_killer_t)(void*); +typedef int (*zarray_iter_fn_t)(void*, void*); + +typedef struct { + mylock_t lock; + int count; + int pos; + int caps; + int delta; + zarray_item_killer_t killer; + void** data; +} zarray_t; + +extern int zarray_init(zarray_t*, int, + zarray_item_killer_t); +extern int zarray_store(zarray_t*, void*); +extern int zarray_clear(zarray_t*, int); +extern int zarray_iter_ex(zarray_t*, xlist_t*, void*); +extern int zarray_iter(zarray_t*, zarray_iter_fn_t, void*); +extern int zarray_del(zarray_t*, int); +extern int zarray_put(zarray_t*, int, void*); +extern void* zarray_get(zarray_t*, int); +extern void zarray_fini(zarray_t*); + +#endif diff --git a/src/lib/client.c b/src/lib/client.c new file mode 100644 index 00000000..7cf3e68e --- /dev/null +++ b/src/lib/client.c @@ -0,0 +1,629 @@ +#include +#include +#include +#include + +#include "client.h" +#include "controller.capnp.h" +#include "mylock.h" + +#include "request.h" +#include "xce/types.h" +#include "xceapi.h" +#include "xcectx.h" +#include "xlist.h" + +typedef enum { + API_CTX_INIT = 0, + API_CTX_RUN, + API_CTX_DOWN, + API_CTX_ERR +} api_ctx_state_t; + +typedef struct { + xce_client_config_t* conf; + endpoint_t ep; + xce_ctx_t ctx; +} api_ctx_t; + +int xcecli_ctx_init(xcecli_ctx_t* c, + xce_client_config_t* cfg) +{ + api_ctx_t* ctx; + int rc; + + if ((c == NULL) || (cfg == NULL)) { + return -EINVAL; + } + + if (cfg->nmasters < 1) { + return -EINVAL; + } + + ctx = (api_ctx_t*)calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + return -ENOMEM; + } + + ctx->conf = cfg; + rc = xce_ctx_init(&(ctx->ctx), + ctx->conf->from, + ctx->conf->key); + if (rc < 0) { + free(ctx); + return rc; + } + + endpoint_init(&(ctx->ep), AF_INET, + SOCK_STREAM, 0, 0); + + xce_ctx_set_endpoint(&(ctx->ctx), &(ctx->ep)); + + *c = (void*)ctx; + + return 0; +} + +void xcecli_ctx_fini(xcecli_ctx_t c) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + if (ctx == NULL) { + return; + } + + xce_ctx_fini(&(ctx->ctx)); + endpoint_deref(&(ctx->ep)); + + free(ctx); +} + +int xcecli_set_handler(xcecli_ctx_t c, + xce_request_handler_t handler) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if ((c == NULL) || (handler == NULL)) { + return -EINVAL; + } + + return xce_ctx_set_handler(&(ctx->ctx), handler); +} + +int xcecli_wakeup(xcecli_ctx_t c, + int status) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return -EINVAL; + } + + return xce_wakeup(&(ctx->ctx), status); +} + +int xcecli_try_wakeup(xcecli_ctx_t c, + int status) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return -EINVAL; + } + + return xce_try_wakeup(&(ctx->ctx), status); +} + +int xcecli_start(xcecli_ctx_t c) +{ + int rc; + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return -EINVAL; + } + + rc = endpoint_connect(&(ctx->ep), + ctx->conf->masters[0], + ctx->conf->master_ports[0]); + if (rc < 0) { + endpoint_deref(&(ctx->ep)); + return rc; + } + + return xce_ctx_start(&(ctx->ctx)); +} + +int xcecli_stop(xcecli_ctx_t c) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return -EINVAL; + } + + xce_ctx_stop(&(ctx->ctx)); + endpoint_deref(&(ctx->ep)); + + return 0; +} + +endpoint_t* xcecli_get_my_endpoint(xcecli_ctx_t c) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return NULL; + } + + return &(ctx->ep); +} + +xce_peerinfo_t* xcecli_get_myinfo(xcecli_ctx_t c) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return NULL; + } + + return &(ctx->ctx.myinfo); +} + +int xcecli_hello(xcecli_ctx_t c, + char* msg) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return -EINVAL; + } + + return xce_hello(&(ctx->ctx), msg); +} + +int xcecli_shutdown(xcecli_ctx_t c) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return -EINVAL; + } + + return xce_shutdown(&(ctx->ctx)); +} + +int xcecli_reslist(xcecli_ctx_t c, + xce_resource_t*** res) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return -EINVAL; + } + + return xce_reslist(&(ctx->ctx), res); +} + +int xcecli_join(xcecli_ctx_t c, + int role, + hostattrs_t* attrs) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + if (ctx == NULL) { + return -EINVAL; + } + + return xce_join(&(ctx->ctx), role, attrs); +} + +int xcecli_workerlist(xcecli_ctx_t c, + xce_worker_t*** workers) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + if (ctx == NULL) { + return -EINVAL; + } + + return xce_workerlist(&(ctx->ctx), workers); +} + +int xcecli_jobdispatch(xcecli_ctx_t c, + xce_job_dispatch_t* info) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return -EINVAL; + } + + return xce_jobdispatch(&(ctx->ctx), info); +} + +int xcecli_jobsubmit(xcecli_ctx_t c, + xce_job_submit_t* submit, + uint64_t* jobid) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return -EINVAL; + } + + return xce_jobsubmit(&(ctx->ctx), submit, jobid); +} + +int xcecli_joblist(xcecli_ctx_t c, + xce_job_t*** jobs) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return -EINVAL; + } + + return xce_joblist(&(ctx->ctx), jobs); +} + +int xcecli_clusterconf(xcecli_ctx_t c, + xce_clusterconf_t** conf) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return -EINVAL; + } + + return xce_clusterconf(&(ctx->ctx), conf); +} + +int xcecli_notify_jobfinish(xcecli_ctx_t c, + xce_jobfinish_t* jfinish) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + /* clang-format off */ + xce_notify_data_t data = { + .event = NotifyData_data_jobFinishInfo, + .data = { + .finishinfo = jfinish + } + }; + /* clang-format on */ + + if (c == NULL) { + return -EINVAL; + } + + if (jfinish == NULL) { + return -EINVAL; + } + + return xcecli_notify(ctx, &data); +} + +int xcecli_update_resvals(xcecli_ctx_t c, + int nres, + xce_resval_t** vals) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + int rc; + + if ((ctx == NULL) || (vals == NULL)) { + return -EINVAL; + } + + rc = xce_update_resvals(&(ctx->ctx), nres, vals); + + return rc; +} + +int xcecli_update_jusage(xcecli_ctx_t c, + uint64_t jobid, + int npids, + int* pids, + int npgids, + int* pgids, + int nusage, + xce_rusage_t** usages) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + int rc; + + if ((ctx == NULL) || (jobid == 0)) { + return -EINVAL; + } + + rc = xce_update_jusage(&(ctx->ctx), jobid, + npids, pids, npgids, pgids, + nusage, usages); + + return rc; +} + +int xcecli_resval(xcecli_ctx_t c, + char* host, + char* res, + xce_resval_t*** val) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return -EINVAL; + } + + if (res == NULL) { + return -EINVAL; + } + + return xce_resval(&(ctx->ctx), host, res, val); +} + +int xcecli_notify(xcecli_ctx_t c, + xce_notify_data_t* data) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return -EINVAL; + } + + if (data == NULL) { + return -EINVAL; + } + + return xce_notify(&(ctx->ctx), data); +} + +int xcecli_notify_jobstart(xcecli_ctx_t c, + job_pidinfo_t* pidinfo) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + /* clang-format off */ + xce_notify_data_t data = { + .event = NotifyData_data_jobPidInfo, + .data = { + .pidinfo = pidinfo + } + }; + /* clang-format on */ + + if ((c == NULL) || (pidinfo == NULL)) { + return -EINVAL; + } + + return xcecli_notify(ctx, &data); +} + +int xcecli_notify_jobfail(xcecli_ctx_t c, + job_failinfo_t* failinfo) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + /* clang-format off */ + xce_notify_data_t data = { + .event = NotifyData_data_jobFailInfo, + .data = { + .failinfo = failinfo + } + }; + /* clang-format on */ + + if ((c == NULL) || (failinfo == NULL)) { + return -EINVAL; + } + + return xcecli_notify(ctx, &data); +} + +int xcecli_jobctrl(xcecli_ctx_t c, + xce_jobctrl_t* ctrlinfo) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + int rc; + + if ((ctx == NULL) || (ctrlinfo == NULL)) { + return -EINVAL; + } + + rc = xce_jobctrl(&(ctx->ctx), ctrlinfo); + + return rc; +} + +int xcecli_notify_jobstop(xcecli_ctx_t c, + uint64_t jobid) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + /* clang-format off */ + xce_notify_data_t data = { + .event = NotifyData_data_stoppedJob, + .data = { + .stopped_job = jobid + } + }; + /* clang-format on */ + + if ((c == NULL) || (jobid == 0)) { + return -EINVAL; + } + + return xcecli_notify(ctx, &data); +} + +int xcecli_notify_jobresume(xcecli_ctx_t c, + uint64_t jobid) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + /* clang-format off */ + xce_notify_data_t data = { + .event = NotifyData_data_resumedJob, + .data = { + .resumed_job = jobid + } + }; + /* clang-format on */ + + if ((c == NULL) || (jobid == 0)) { + return -EINVAL; + } + + return xcecli_notify(ctx, &data); +} + +int xcecli_notify_jobchkpt(xcecli_ctx_t c, + uint64_t jobid, + char* info) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + /* clang-format off */ + xce_ckptinfo_t ckptinfo = { + .jobid = jobid, + .ckptinfo = info + }; + xce_notify_data_t data = { + .event = NotifyData_data_ckptinfo, + .data = { + .ckptinfo = &ckptinfo + } + }; + /* clang-format on */ + + if ((c == NULL) || (jobid == 0) || (info == NULL)) { + return -EINVAL; + } + + return xcecli_notify(ctx, &data); +} + +int xcecli_notify_jobpostdone(xcecli_ctx_t c, + uint64_t jobid) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + /* clang-format off */ + xce_notify_data_t data = { + .event = NotifyData_data_postDoneJob, + .data = { + .pdone_job = jobid + } + }; + /* clang-format on */ + + if ((c == NULL) || (jobid == 0)) { + return -EINVAL; + } + + return xcecli_notify(ctx, &data); +} + +int xcecli_queuectrl(xcecli_ctx_t c, + xce_queuectrl_t* ctrlinfo) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + int rc; + + if ((ctx == NULL) || (ctrlinfo == NULL)) { + return -EINVAL; + } + + rc = xce_queuectrl(&(ctx->ctx), ctrlinfo); + + return rc; +} + +int xcecli_runtask(xcecli_ctx_t c, + xce_taskrun_t* info) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + int rc; + + if ((ctx == NULL) || (info == NULL)) { + return -EINVAL; + } + + info->clientidx = -1; /* this field will be used by + * controller to trace back + * client + */ + rc = xce_runtask(&(ctx->ctx), info); + + return rc; +} + +int xcecli_notify_taskstart(xcecli_ctx_t c, + xce_task_pidinfo_t* pidinfo) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + /* clang-format off */ + xce_notify_data_t data = { + .event = NotifyData_data_taskPidInfo, + .data = { + .taskinfo = pidinfo + } + }; + /* clang-format on */ + + if ((c == NULL) || (pidinfo == NULL)) { + return -EINVAL; + } + + return xcecli_notify(ctx, &data); +} + +int xcecli_notify_taskfail(xcecli_ctx_t c, + xce_task_failinfo_t* failinfo) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + /* clang-format off */ + xce_notify_data_t data = { + .event = NotifyData_data_taskFailInfo, + .data = { + .taskfailinfo = failinfo + } + }; + /* clang-format on */ + + if ((c == NULL) || (failinfo == NULL)) { + return -EINVAL; + } + + return xcecli_notify(ctx, &data); +} + +int xcecli_notify_taskfinish(xcecli_ctx_t c, + xce_task_finish_t* info) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + /* clang-format off */ + xce_notify_data_t data = { + .event = NotifyData_data_taskFinish, + .data = { + .taskfinish = info + } + }; + /* clang-format on */ + + if ((c == NULL) || (info == NULL)) { + return -EINVAL; + } + + return xcecli_notify(ctx, &data); +} + +void xcecli_block_tasks(xcecli_ctx_t c) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + if (c == NULL) { + return; + } + + xce_block_tasks(&(ctx->ctx)); +} + +void xcecli_unblock_tasks(xcecli_ctx_t c) +{ + api_ctx_t* ctx = (api_ctx_t*)c; + + if (c == NULL) { + return; + } + + xce_unblock_tasks(&(ctx->ctx)); +} diff --git a/src/lib/dataq.c b/src/lib/dataq.c new file mode 100644 index 00000000..0b3a26fc --- /dev/null +++ b/src/lib/dataq.c @@ -0,0 +1,119 @@ +#include + +#include "dataq.h" + +int dataq_init(dataq_t* q, + data_item_killer_t killer) +{ + q->head = q->tail = NULL; + q->killer = killer; + mylock_init(&(q->lock)); + return 0; +} + +static data_item_t* dataq_deq_head(dataq_t* q) +{ + if (q->head != NULL) { + data_item_t* b = NULL; + b = q->head; + q->head = b->next; + b->next = NULL; + if (q->head == NULL) { + q->tail = NULL; + } + + return b; + } + + return NULL; +} + +static data_item_t* dataq_deq_first_match(dataq_t* q, + data_item_match_fn_t f) +{ + data_item_t* prev = NULL; + data_item_t* curr = q->head; + + while (curr != NULL) { + if ((*f)(curr)) { // Found the item to remove + if (prev == NULL) { + // Removing the head item + q->head = curr->next; + if (q->head == NULL) { + // Queue became empty after removing head + q->tail = NULL; + } + // else: tail remains unchanged (it wasn't the head) + } else { + // Removing an item after prev (middle or tail) + prev->next = curr->next; + if (curr == q->tail) { // Check if we are removing the tail + // We removed the tail item, prev is the new tail + q->tail = prev; + } + // else: tail remains unchanged (it was further down the list) + } + curr->next = NULL; // Isolate the removed item + return curr; // Return the removed item + } + // Move to the next item + prev = curr; + curr = curr->next; + } + + return NULL; +} + +data_item_t* dataq_deq(dataq_t* q, + data_item_match_fn_t f) +{ + data_item_t* b = NULL; + + mylock_lock(&(q->lock)); + if (f == NULL) { + b = dataq_deq_head(q); + } else { + b = dataq_deq_first_match(q, f); + } + + mylock_unlock(&(q->lock)); + + return b; +} + +int dataq_enq(dataq_t* q, data_item_t* b) +{ + int rc = 0; + + b->next = NULL; + + mylock_lock(&(q->lock)); + if (q->tail != NULL) { + q->tail->next = b; + } + + if (q->head == NULL) { + q->head = b; + } + + q->tail = b; + mylock_unlock(&(q->lock)); + + return rc; +} + +void dataq_fini(dataq_t* q) +{ + data_item_t* it; + while ((it = dataq_deq_head(q)) != NULL) { + if (q->killer != NULL) { + (q->killer)(it); + } + // Note: dataq_deq_head already isolates 'it' (it->next = NULL) + } + + q->head = q->tail = NULL; // Explicitly set just in case. + q->killer = NULL; + + return; +} diff --git a/src/lib/hook.c b/src/lib/hook.c new file mode 100644 index 00000000..7d7f5d17 --- /dev/null +++ b/src/lib/hook.c @@ -0,0 +1,136 @@ +#include +#include +#include + +#include "hook.h" +#include "utils.h" + +int xce_hook_init(hooksys_t* s, + int maxtypes) +{ + int i; + if ((s == NULL) || (maxtypes <= 0)) { + return -EINVAL; + } + + s->maxtypes = 0; + s->hooks = (xlist_t*)calloc(maxtypes, sizeof(xlist_t)); + if (s->hooks == NULL) { + return -ENOMEM; + } + + s->maxtypes = maxtypes; + for (i = 0; i < s->maxtypes; i++) { + xlist_init(&(s->hooks[i]), 8); + } + return 0; +} + +int xce_add_hook(hooksys_t* s, + int typ, + hook_fn_t fn, + void* data) +{ + hook_item_t* it; + + if (s == NULL) { + return -EINVAL; + } + + if (fn == NULL) { + return -EINVAL; + } + + if ((typ < 0) || (typ >= s->maxtypes)) { + return -EINVAL; + } + + it = (hook_item_t*)calloc(1, sizeof(*it)); + if (it == NULL) { + return -ENOMEM; + } + + it->fn = fn; + it->data = data; + + xlist_store(&(s->hooks[typ]), it); + + return 0; +} + +/* HOOK_BEFORE_EVENT returns + * negative value will cause + * fail + */ +int xce_run_hooks(hooksys_t* s, + int type, + int situation, + int detail, + ...) +{ + xlist_t* l; + int i; + int rc = 0; + + if (s == NULL) { + return -EINVAL; + } + + if ((type < 0) || (type >= s->maxtypes)) { + return -EINVAL; + } + + l = &(s->hooks[type]); + + for (i = 0; i < l->count; i++) { + hook_item_t* it = l->data[i]; + va_list ap; + + if (it == NULL) { + continue; + } + + va_start(ap, detail); + rc = (*(it->fn))(type, situation, detail, + it->data, ap); + va_end(ap); + + if ((situation == HOOK_BEFORE_EVENT) && (rc < 0)) { + break; + } + } + + return rc; +} + +static int free_hook_item(void *data1, + void *data2) { + if (data1 == NULL) { + return -EINVAL; + } + + free(data1); + return 0; +} + +void xce_hook_fini(hooksys_t* s) +{ + int i; + + if (s == NULL) { + return; + } + + if (s->hooks == NULL) { + return; + } + + for (i = 0; i < s->maxtypes; i++) { + xlist_iter(&(s->hooks[i]), + (xlist_iter_fn_t)free_hook_item, + NULL); + xlist_fini(&(s->hooks[i])); + } + + FREEUP(s->hooks); +} diff --git a/src/lib/htab.c b/src/lib/htab.c new file mode 100644 index 00000000..519ae2b7 --- /dev/null +++ b/src/lib/htab.c @@ -0,0 +1,215 @@ +#include +#include +#include + +#include "htab.h" +#include "utils.h" + +#define HASH_KEY_HASH(t, key) \ + (((t)->fn.hash != NULL) ? ((t)->fn.hash)(key) : (unsigned long)key) + +#define HASH_KEY_CMP(t, k1, k2) \ + (((t)->fn.cmp != NULL) ? ((t)->fn.cmp)((k1), (k2)) : ((k1) != (k2))) + +#define HASH_KEY_COPY(t, key) \ + (((t)->fn.copy != NULL) ? ((t)->fn.copy)(key) : (key)) + +#define HASH_KEY_FREE(t, key) \ + do { \ + if (((t)->fn.free != NULL) && ((key) != NULL)) { \ + (t)->fn.free(key); \ + } \ + } while (0) + +static unsigned int hash_code(const char* key) +{ + unsigned int hc = 5381; + int c; + + while ((c = *key++)) { + hc = ((hc << 5) + hc) + c; + } + + return hc; +} + +static unsigned int string_hash(void* data) +{ + return hash_code((const char*)data); +} + +static int string_cmp(void* d1, + void* d2) +{ + return (int)strcmp((char*)d1, (char*)d2); +} + +static void* string_dup(void* data) +{ + return (void*)strdup((char*)data); +} + +static void string_free(void* data) +{ + if (data != NULL) { + free(data); + } +} + +hash_key_fn_t string_hash_key = { + .hash = (hash_key_hash_fn_t)string_hash, + .cmp = (hash_key_cmp_fn_t)string_cmp, + .copy = (hash_key_copy_fn_t)string_dup, + .free = (hash_key_free_fn_t)string_free +}; + +hash_key_fn_t int_hash_key = { + .hash = NULL, + .cmp = NULL, + .copy = NULL, + .free = NULL +}; + +int ht_init(htab_t* t, + int nslots, + hash_key_fn_t fn) +{ + if ((t == NULL) || (nslots <= 1)) { + return -EINVAL; + } + + mylock_init(&(t->lock)); + t->slots = (hent_t**)calloc(nslots, sizeof(hent_t*)); + if (t->slots == NULL) { + return -ENOMEM; + } + + t->nslots = nslots; + t->fn = fn; + return 0; +} + +void ht_fini(htab_t* t) +{ + int i; + hent_t* e; + + if (t == NULL) { + return; + } + + for (i = 0; i < t->nslots; i++) { + while ((e = t->slots[i]) != NULL) { + t->slots[i] = e->next; + e->next = NULL; + HASH_KEY_FREE(t, e->key); + free(e); + } + } + + free(t->slots); + + return; +} + +hent_t* ht_get(htab_t* t, + void* key) +{ + unsigned int hc; + hent_t* e; + + if (t == NULL) { + SET_ERROR(EINVAL); + + return NULL; + } + + hc = HASH_KEY_HASH(t, key) % (t->nslots); + + mylock_lock(&(t->lock)); + e = t->slots[hc]; + + while (e != NULL) { + if (HASH_KEY_CMP(t, e->key, key) == 0) { + break; + } + + e = e->next; + } + mylock_unlock(&(t->lock)); + return e; +} + +hent_t* ht_add(htab_t* t, + void* key) +{ + unsigned int hc; + hent_t* e; + + if ((t == NULL) || (key == NULL)) { + return NULL; + } + + e = ht_get(t, key); + if (e != NULL) { + return e; + } + + e = (hent_t*)calloc(1, sizeof(*e)); + if (e == NULL) { + return NULL; + } + + e->key = HASH_KEY_COPY(t, key); + if (e->key == NULL) { + free(e); + return NULL; + } + + e->data = -1; + + hc = HASH_KEY_HASH(t, key) % (t->nslots); + mylock_init(&(t->lock)); + e->next = t->slots[hc]; + t->slots[hc] = e; + mylock_unlock(&(t->lock)); + + return e; +} + +int ht_del(htab_t* t, + void* key) +{ + unsigned int hc; + hent_t** e; + int deleted = 0; + + if ((t == NULL) || (key == NULL)) { + return -EINVAL; + } + + hc = HASH_KEY_HASH(t, key) % (t->nslots); + mylock_init(&(t->lock)); + e = &(t->slots[hc]); + while ((*e) != NULL) { + if (HASH_KEY_CMP(t, (*e)->key, key) == 0) { + hent_t* e1 = *e; + + *e = e1->next; + HASH_KEY_FREE(t, e1->key); + free(e1); + deleted = 1; + break; + } + + e = &((*e)->next); + } + + mylock_unlock(&(t->lock)); + + if (deleted) { + return 1; + } + + return -ENOENT; +} diff --git a/src/lib/kvmgr.c b/src/lib/kvmgr.c new file mode 100644 index 00000000..de4aad05 --- /dev/null +++ b/src/lib/kvmgr.c @@ -0,0 +1,211 @@ +#include +#include +#include + +#include "htab.h" +#include "kvmgr.h" +#include "objmgr.h" +#include "utils.h" +#include "xce/types.h" +#include "zarray.h" + +int kvmgr_init(kvmgr_t* mgr, + hash_key_fn_t keyfn, + int nslots, + int delta, + zarray_item_killer_t killer) +{ + ht_init(&(mgr->htab), nslots, keyfn); + zarray_init(&(mgr->data), delta, killer); + mylock_init(&(mgr->lock)); + return 0; +} + +void kvmgr_fini(kvmgr_t* mgr) +{ + ht_fini(&(mgr->htab)); + zarray_fini(&(mgr->data)); + mylock_fini(&(mgr->lock)); +} + +static void* kvmgr_lock_(kvmgr_t* mgr, + void* key, + int op) +{ + hent_t* e = NULL; + int32_t idx; + void* ptr; + + e = ht_get(&(mgr->htab), key); + if (e == NULL) { + SET_ERROR(ENOENT); + return NULL; + } + + idx = e->data; + if (idx < 0) { + SET_ERROR(ENOENT); + return NULL; + } + + ptr = (void*)zarray_get(&(mgr->data), idx); + + return obj_ref(ptr, op); +} + +void* kvmgr_lock(kvmgr_t* mgr, + void* key, + int op) +{ + void* ptr = NULL; + + if (mgr == NULL) { + SET_ERROR(EINVAL); + return NULL; + } + + /* clang-format off */ + if ((op != OBJREF_NOP) && + (op != OBJREF_READ) && + (op != OBJREF_UPDATE)) { + SET_ERROR(EINVAL); + return NULL; + } + /* clang-format on */ + + mylock_lock(&(mgr->lock)); + ptr = kvmgr_lock_(mgr, key, op); + mylock_unlock(&(mgr->lock)); + + return ptr; +} + +static int32_t kvmgr_add_(kvmgr_t* mgr, + void* key, + void* p) +{ + hent_t* e = NULL; + int idx; + + e = ht_get(&(mgr->htab), key); + if (e != NULL) { + return -EEXIST; + } + + idx = zarray_store(&(mgr->data), p); + if (idx < 0) { + return idx; + } + + e = ht_add(&(mgr->htab), + (void*)key); + if (e == NULL) { + zarray_del(&(mgr->data), idx); + return -errno; + } + + e->data = idx; + return idx; +} + +int32_t kvmgr_add(kvmgr_t* mgr, + void* key, + void* p) +{ + int32_t idx; + + if ((mgr == NULL) || (p == NULL)) { + return -EINVAL; + } + + mylock_lock(&(mgr->lock)); + idx = kvmgr_add_(mgr, key, p); + mylock_unlock(&(mgr->lock)); + + return idx; +} + +static void kvmgr_del_(kvmgr_t* mgr, + void* key) +{ + hent_t* e = NULL; + int idx; + + e = ht_get(&(mgr->htab), key); + if (e == NULL) { + return; + } + + idx = e->data; + if (idx < 0) { + return; + } + + zarray_del(&(mgr->data), idx); + + return; +} + +void kvmgr_del(kvmgr_t* mgr, + void* key) +{ + if (mgr == NULL) { + return; + } + mylock_lock(&(mgr->lock)); + kvmgr_del_(mgr, key); + mylock_unlock(&(mgr->lock)); +} + +static int add_config_(xlist_t* l, void* data) +{ + xce_config_t* config; + + if (data == NULL) { + return -EINVAL; + } + + config = (xce_config_t*)obj_ref(data, OBJREF_READ); + return xlist_store(l, config); +} + +int kvmgr_publish(kvmgr_t* mgr, + xlist_action_fn_t fn, + void* arg) +{ + xlist_t l; + int rc = 0; + int i; + + xlist_init(&l, 128); + + mylock_lock(&(mgr->lock)); + zarray_iter(&(mgr->data), + (zarray_iter_fn_t)add_config_, + &l); + mylock_unlock(&(mgr->lock)); + + rc = (*fn)(&l, arg); + + for (i = 0; i < l.count; i++) { + xce_config_t* config = l.data[i]; + + DEREF_OBJ(config); + } + + xlist_fini(&l); + return rc; +} + +int kvmgr_iter(kvmgr_t* mgr, + xlist_t* l, + void* arg) +{ + int rc = 0; + + mylock_lock(&(mgr->lock)); + rc = zarray_iter_ex(&(mgr->data), l, arg); + mylock_unlock(&(mgr->lock)); + + return rc; +} diff --git a/src/lib/meson.build b/src/lib/meson.build new file mode 100644 index 00000000..3da3a592 --- /dev/null +++ b/src/lib/meson.build @@ -0,0 +1,69 @@ +capnp = find_program('capnp') + +gen_srcs = custom_target( + 'controllercapnp.[ch]', + output:['controller.capnp.c', 'controller.capnp.h'], + input: '../schema/controller.capnp', + command: [capnp, 'compile','-o' ,'c:lib', '-I', '../schema','--src-prefix', '../schema', '@INPUT@'] +) + +libxce_src = [ gen_srcs[0], + 'client.c', + 'dataq.c', + 'hook.c', + 'htab.c', + 'kvmgr.c', + 'mylock.c', + 'netio.c', + 'objmgr.c', + 'request.c', + 'threshold.c', + 'utils.c', + 'vtaskmgr.c', + 'window.c', + 'xceapi.c', + 'xcectx.c', + 'xlist.c', + 'xstring.c', + 'zarray.c' + ] + +incdir = include_directories('../include') +build_inc = include_directories('.') + +capnpc_c_prog = find_program('capnpc-c') + +# debug('capnpc_c_prog %s\n', capnpc_c_prog) + +thread_dep = dependency('threads') +c_capnproto_dep = dependency('c-capnproto') +zlog_dep = dependency('zlog') +unity_dep = dependency('unity') + +libxce_deps = [c_capnproto_dep, zlog_dep, thread_dep] + +libxce = static_library('xce', + libxce_src, + include_directories: [incdir, build_inc], + dependencies: libxce_deps, + install: true) + +libxce_dep = declare_dependency(link_with: libxce) + +libxce_test_src = ['testsuite/test.c', + 'testsuite/test_error.c', + 'testsuite/test_htab.c', + 'testsuite/test_htab_int.c', + 'testsuite/test_utils.c', + 'testsuite/test_xstring.c', + 'testsuite/test_zarray.c' + ] + +libxce_test_deps = [libxce_deps, unity_dep, libxce_dep] +libxce_test = executable('xcelib_test', + libxce_test_src, + include_directories: [incdir, build_inc], + dependencies: libxce_test_deps, + install: true) + +test('libxce test', libxce_test) diff --git a/src/lib/mylock.c b/src/lib/mylock.c new file mode 100644 index 00000000..76fa676e --- /dev/null +++ b/src/lib/mylock.c @@ -0,0 +1,212 @@ +#include +#include +#include + +#include "mylock.h" + +int mylock_init(mylock_t* l) +{ + if (l == NULL) { + return -EINVAL; + } + + return pthread_mutex_init(l, NULL); +} + +void mylock_fini(mylock_t* l) +{ + if (l == NULL) { + return; + } + + pthread_mutex_destroy(l); +} +int mylock_try(mylock_t* l) +{ + if (l == NULL) { + return -EINVAL; + } + + return pthread_mutex_trylock(l); +} + +int mylock_lock(mylock_t* l) +{ + if (l == NULL) { + return -EINVAL; + } + + return pthread_mutex_lock(l); +} + +int mylock_unlock(mylock_t* l) +{ + if (l == NULL) { + return -EINVAL; + } + + return pthread_mutex_unlock(l); +} + +int cbuf_init(cbuf_t* b, + int cap, + int isize) +{ + if ((b == NULL) || (cap <= 0) || (isize <= 0)) { + return -EINVAL; + } + + b->ncap = cap; + b->isize = isize; + b->data = (void*)calloc(cap, isize); + + if (b->data == NULL) { + return -EINVAL; + } + + b->head = 0; + b->len = 0; + + pthread_mutex_init(&(b->mutex), NULL); + pthread_cond_init(&(b->condget), NULL); + pthread_cond_init(&(b->condput), NULL); + + return 0; +} + +void cbuf_fini(cbuf_t* b) +{ + if (b == NULL) { + return; + } + + if (b->data != NULL) { + free(b->data); + b->data = NULL; + } + + pthread_mutex_destroy(&(b->mutex)); + pthread_cond_destroy(&(b->condput)); + pthread_cond_destroy(&(b->condget)); +} + +int cbuf_put(cbuf_t* b, + void* it) +{ + int i; + + if ((b == NULL) || (it == NULL)) { + return -EINVAL; + } + + pthread_mutex_lock(&(b->mutex)); + while (b->len == b->ncap) { + pthread_cond_wait(&(b->condput), + &(b->mutex)); + } + + i = (b->head + b->len) % b->ncap; + + memcpy((void*)((char*)b->data) + b->isize * i, + it, b->isize); + + b->len++; + + pthread_cond_signal(&(b->condget)); + + pthread_mutex_unlock(&(b->mutex)); + return 0; +} + +int cbuf_tryput(cbuf_t* b, + void* it) +{ + int i; + int rc = 0; + + if ((b == NULL) || (it == NULL)) { + return -EINVAL; + } + + pthread_mutex_lock(&(b->mutex)); + if (b->len < b->ncap) { + i = (b->head + b->len) % b->ncap; + + memcpy((void*)((char*)b->data) + b->isize * i, + it, b->isize); + + b->len++; + + pthread_cond_signal(&(b->condget)); + } else { + rc = -EAGAIN; + } + + pthread_mutex_unlock(&(b->mutex)); + return rc; +} + +int cbuf_get(cbuf_t* b, + void* it) +{ + if ((b == NULL) || (it == NULL)) { + return -EINVAL; + } + + pthread_mutex_lock(&(b->mutex)); + while (b->len == 0) { + pthread_cond_wait(&(b->condget), + &(b->mutex)); + } + + memcpy(it, (void*)((char*)b->data) + b->isize * b->head, + b->isize); + + b->head = (b->head + 1) % b->ncap; + b->len--; + + pthread_cond_signal(&(b->condput)); + + pthread_mutex_unlock(&(b->mutex)); + return 0; +} + +int my_rwlock_init(my_rwlock_t *l) { + if ( l == NULL) { + return -EINVAL; + } + + return pthread_rwlock_init(l, NULL); +} + +void my_rwlock_fini(my_rwlock_t *l) { + if (l == NULL) { + return; + } + + pthread_rwlock_destroy(l); +} + +int my_rwlock_unlock(my_rwlock_t *l) { + if (l == NULL) { + return -EINVAL; + } + + return pthread_rwlock_unlock(l); +} + +int my_rwlock_rlock(my_rwlock_t *l) { + if (l == NULL) { + return -EINVAL; + } + + return pthread_rwlock_rdlock(l); +} + +int my_rwlock_wlock(my_rwlock_t *l) { + if (l==NULL) { + return -EINVAL; + } + + return pthread_rwlock_wrlock(l); +} diff --git a/src/lib/netio.c b/src/lib/netio.c new file mode 100644 index 00000000..b2420a01 --- /dev/null +++ b/src/lib/netio.c @@ -0,0 +1,687 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dataq.h" +#include "netio.h" +#include "request.h" +#include "utils.h" + +static int iomgr_update_poll(iomgr_t*, endpoint_t*, int); +static void endpoint_fini(endpoint_t*); + +static int socket_create(int domain, + int type, + int port, + int backlog) +{ + int sock; + int opt = 1; + + if ((domain < 0) || (type < 0)) { + return -EINVAL; + } + + sock = socket(domain, type, 0); + if (sock < 0) { + SET_ERROR(errno); + + return -errno; + } + + fcntl(sock, F_SETFD, (fcntl(sock, F_GETFD) | FD_CLOEXEC)); + + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) < 0) { + close(sock); + return -1; + } + + if (port > 0) { + struct sockaddr_in sin; + + memset((char*)&sin, 0, sizeof(sin)); + sin.sin_family = domain; + sin.sin_port = htons(port); + sin.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0) { + int rc; + + SET_ERROR(errno); + + rc = -errno; + (void)close(sock); + + return rc; + } + + if (backlog > 0) { + if (listen(sock, backlog) < 0) { + int rc; + + SET_ERROR(errno); + + rc = -errno; + (void)close(sock); + + return rc; + } + } + } + + return sock; +} + +static int socket_connect(int sock, + char* host, + int port) +{ + struct sockaddr_in server; + struct hostent* hp; + int rc; + + server.sin_family = AF_INET; + hp = gethostbyname(host); + if (hp == NULL) { + SET_ERROR(errno); + + rc = -errno; + + return rc; + } + + memcpy((char*)&server.sin_addr, (char*)hp->h_addr, (int)hp->h_length); + + server.sin_port = htons(port); + + rc = connect(sock, (struct sockaddr*)&server, sizeof(server)); + if (rc < 0) { + SET_ERROR(errno); + + return -errno; + } + + return rc; +} + +static int socket_accept(int sock) +{ + socklen_t len; + int s; + struct sockaddr_in from; + + len = sizeof(from); + s = accept(sock, (struct sockaddr*)&from, &len); + if (s < 0) { + SET_ERROR(errno); + + return -errno; + } + + fcntl(s, F_SETFD, (fcntl(s, F_GETFD) | FD_CLOEXEC)); + + return s; +} + +int netio_write(int fd, + char* data, + int sz) +{ + int nc = 0; + + while (sz > 0) { + int rc; + rc = write(fd, data + nc, sz); + if (rc < 0) { + SET_ERROR(errno); + + return -errno; + } + + sz -= rc; + nc += rc; + } + + return nc; +} + +int netio_read(int fd, + char* data, + int sz) +{ + int nc = 0; + + while (sz > 0) { + int rc; + + rc = read(fd, data + nc, sz); + if (rc < 0) { + SET_ERROR(errno); + + return -errno; + } + + if (rc == 0) { + /* network read return 0, it seems remote + * size has tear down the connection + */ + return -EPIPE; + } + + sz -= rc; + nc += rc; + } + + return nc; +} + +int write_packet(int fd, + io_packet_t* pkt) +{ + int rc; + + rc = netio_write(fd, (char*)&(pkt->sz), + sizeof(pkt->sz)); + if (rc < 0) { + return -errno; + } + + rc = netio_write(fd, pkt->data, pkt->sz); + if (rc < 0) { + return -errno; + } + return rc; +} + +int alloc_packet(io_packet_t* pkt) +{ + if (pkt->sz <= 0) { + SET_ERROR(EINVAL); + + return -EINVAL; + } + + pkt->data = (char*)malloc(pkt->sz); + if (pkt->data == NULL) { + SET_ERROR(ENOMEM); + + return -ENOMEM; + } + + return 1; +} +int read_packet(int fd, + io_packet_t* pkt) +{ + int rc; + + rc = netio_read(fd, (char*)&(pkt->sz), + sizeof(pkt->sz)); + if (rc < 0) { + return rc; + } + + rc = alloc_packet(pkt); + if (rc < 0) { + return rc; + } + + rc = netio_read(fd, pkt->data, pkt->sz); + if (rc < 0) { + free_packet(pkt); + } + + return rc; +} + +void free_packet(io_packet_t* pkt) +{ + if (pkt->data != NULL) { + free(pkt->data); + pkt->data = NULL; + } +} + +#define MAX_EPOLL_EVENTS (5) + +static void* io_worker(void* args) +{ + iomgr_t* iomgr = (iomgr_t*)args; + + while (1) { + int nfds = -1; + int i; + struct epoll_event events[MAX_EPOLL_EVENTS]; + + nfds = epoll_wait(iomgr->epoll_fd, events, + MAX_EPOLL_EVENTS, -1); + if (nfds == -1) { + if (errno == EINTR) { + continue; + } + + perror("epoll"); + + return NULL; + } + + for (i = 0; i < nfds; i++) { + endpoint_t* p = (endpoint_t*)events[i].data.ptr; + + if (p->handler != NULL) { + (p->handler)(&events[i]); + } + } + + pthread_testcancel(); + } + + return NULL; +} + +static int endpoint_calc_flags(endpoint_t* ep) +{ + int flags = EPOLLIN; + + if (ep->outq.head != NULL) { + flags = flags | EPOLLOUT; + } + + return flags; +} + +endpoint_t* endpoint_get() +{ + endpoint_t* ep; + + ep = (endpoint_t*)calloc(1, sizeof(*ep)); + if (ep == NULL) { + SET_ERROR(errno); + + return ep; + } + + ep->fd = -1; + ep->idx = -1; + ep->iomgr = NULL; + ep->busy = 0; + ep->needfree = 1; + + mylock_init(&(ep->lock)); + + return endpoint_ref(ep); +} + +static void outq_item_killer(data_item_t* it) +{ + if (it != NULL) { + ioctx_t* ctx = ITPTR_TO_IOCTX(it); + ioctx_deref(ctx, 1); + } +} +int endpoint_init(endpoint_t* ep, + int domain, + int type, + int port, + int backlog) +{ + int fd = -1; + + if (ep == NULL) { + SET_ERROR(EINVAL); + + return -EINVAL; + } + + fd = socket_create(domain, type, + port, backlog); + if (fd < 0) { + return -errno; + } + + ep->flags = 0; + ep->fd = fd; + ep->owner = NULL; + ep->data = NULL; + ep->iomgr = NULL; + ep->busy = 0; + ep->needfree = 0; + + dataq_init(&(ep->outq), + outq_item_killer); + mylock_init(&(ep->lock)); + + endpoint_ref(ep); + + return fd; +} + +int endpoint_connect(endpoint_t* ep, + char* host, + int port) +{ + int rc = -1; + + rc = socket_connect(ep->fd, host, port); + if (rc < 0) { + return rc; + } + + ep->flags = 0; + return rc; +} + +int endpoint_accept(endpoint_t* ep, + endpoint_t* ep2) +{ + int sock = -1; + + sock = socket_accept(ep->fd); + if (sock < 0) { + return sock; + } + + ep2->fd = sock; + ep2->flags = 0; + + return sock; +} + +int endpoint_set_handler(endpoint_t* ep, + msghandler_t h, + void* owner) +{ + if (ep->fd < 0) { + SET_ERROR(EINVAL); + + return -EINVAL; + } + + mylock_lock(&(ep->lock)); + ep->handler = h; + ep->owner = owner; + mylock_unlock(&(ep->lock)); + + return 1; +} + +int endpoint_enq(endpoint_t* ep, + data_item_t* it) +{ + int rc = 0; + int flags; + + if ((ep == NULL) || (it == NULL)) { + SET_ERROR(EINVAL); + + return -EINVAL; + } + + mylock_lock(&(ep->lock)); + rc = dataq_enq(&(ep->outq), it); + + flags = endpoint_calc_flags(ep); + if (flags != ep->flags) { + if (ep->iomgr != NULL) { + int rc1; + + mylock_lock(&(ep->iomgr->lock)); + rc1 = iomgr_update_poll(ep->iomgr, + ep, flags); + mylock_unlock(&(ep->iomgr->lock)); + + if (rc1 >= 0) { + ep->flags = flags; + } else { + WARN("rc1=%d < 0", rc1); + } + } + } + mylock_unlock(&(ep->lock)); + + return rc; +} + +data_item_t* endpoint_deq(endpoint_t* ep) +{ + data_item_t* it = NULL; + int flags; + + if (ep == NULL) { + SET_ERROR(EINVAL); + + return NULL; + } + + mylock_lock(&(ep->lock)); + it = dataq_deq(&(ep->outq), NULL); + flags = endpoint_calc_flags(ep); + if (flags != ep->flags) { + if (ep->iomgr != NULL) { + int rc; + + mylock_lock(&(ep->iomgr->lock)); + rc = iomgr_update_poll(ep->iomgr, + ep, flags); + mylock_unlock(&(ep->iomgr->lock)); + + if (rc >= 0) { + ep->flags = flags; + } + } + } + mylock_unlock(&(ep->lock)); + + return it; +} + +endpoint_t* endpoint_ref(endpoint_t* ep) +{ + mylock_lock(&(ep->lock)); + ep->refcount++; + mylock_unlock(&(ep->lock)); + + return ep; +} + +void endpoint_deref(endpoint_t* ep) +{ + uint32_t refcount; + + mylock_lock(&(ep->lock)); + ep->refcount--; + + refcount = ep->refcount; + mylock_unlock(&(ep->lock)); + + if (refcount == 0) { + endpoint_fini(ep); + } +} + +uint64_t endpoint_getseq(endpoint_t* ep) +{ + uint64_t seq; + + mylock_lock(&(ep->lock)); + seq = ep->seq++; + mylock_unlock(&(ep->lock)); + + return seq; +} + +void endpoint_block_tasks(endpoint_t* ep) +{ + TRACE("%s[%ld] block tasks for endpoint %p", + __func__, pthread_self(), ep); + mylock_lock(&(ep->lock)); + ep->busy = 1; + mylock_unlock(&(ep->lock)); +} + +void endpoint_unblock_tasks(endpoint_t* ep) +{ + TRACE("%s[%ld] unblock tasks for endpoint %p", + __func__, pthread_self(), ep); + mylock_lock(&(ep->lock)); + ep->busy = 0; + mylock_unlock(&(ep->lock)); +} + +int endpoint_is_task_blocked(endpoint_t* ep) +{ + int busy; + + mylock_lock(&(ep->lock)); + busy = ep->busy; + mylock_unlock(&(ep->lock)); + + TRACE("%s[%ld] endpoint %p task %s", + __func__, pthread_self(), + ep, (busy != 0) ? "blocked" : "not blocked"); + + return (busy != 0); +} + +static void endpoint_fini(endpoint_t* ep) +{ + int needfree = ep->needfree; + + dataq_fini(&(ep->outq)); + FREEUP(ep->data); + + if (ep->fd >= 0) { + close(ep->fd); + } + + ep->flags = 0; + ep->handler = NULL; + ep->owner = NULL; + + if (needfree) { + FREEUP(ep); + } +} + +int iomgr_init(iomgr_t* iomgr) +{ + mylock_init(&(iomgr->lock)); + iomgr->epoll_fd = epoll_create1(0); + if (iomgr->epoll_fd < 0) { + SET_ERROR(errno); + + return -errno; + } + + return 0; +} + +static int iomgr_update_poll(iomgr_t* iomgr, + endpoint_t* ep, + int flags) +{ + struct epoll_event ev; + + ev.events = flags; + ev.data.ptr = ep; + + return epoll_ctl(iomgr->epoll_fd, + EPOLL_CTL_MOD, + ep->fd, &ev); +} + +int iomgr_monitor(iomgr_t* iomgr, + endpoint_t* ep) +{ + struct epoll_event ev; + int rc; + int flags; + + flags = EPOLLIN; + ev.events = flags; + ev.data.ptr = ep; + + mylock_lock(&(ep->lock)); + ep->iomgr = iomgr; + mylock_lock(&(iomgr->lock)); + rc = epoll_ctl(iomgr->epoll_fd, EPOLL_CTL_ADD, + ep->fd, &ev); + mylock_unlock(&(iomgr->lock)); + + if (rc >= 0) { + ep->flags = flags; + } + + mylock_unlock(&(ep->lock)); + + return rc; +} + +int iomgr_unmonitor(iomgr_t* iomgr, + endpoint_t* ep) +{ + int rc; + + mylock_lock(&(iomgr->lock)); + rc = epoll_ctl(iomgr->epoll_fd, EPOLL_CTL_DEL, + ep->fd, NULL); + if (rc < 0) { + SET_ERROR(errno); + + rc = -errno; + } + mylock_unlock(&(iomgr->lock)); + + return rc; +} + +int iomgr_start(iomgr_t* iomgr) +{ + int rc; + + rc = pthread_create(&(iomgr->worker), NULL, &io_worker, iomgr); + return rc; +} + +int iomgr_fini(iomgr_t* iomgr) +{ + return 0; +} + +int iomgr_stop(iomgr_t* iomgr) +{ + int rc; + void* res; + + if (iomgr->worker == 0) { + return 0; + } + + rc = pthread_cancel(iomgr->worker); + if (rc != 0) { + SET_ERROR(errno); + + return -errno; + } + + rc = pthread_join(iomgr->worker, &res); + if (rc != 0) { + SET_ERROR(errno); + + return -errno; + } + + if (res == PTHREAD_CANCELED) { + iomgr->worker = 0; + return 0; + } + + return -1; +} diff --git a/src/lib/objmgr.c b/src/lib/objmgr.c new file mode 100644 index 00000000..6f319d1b --- /dev/null +++ b/src/lib/objmgr.c @@ -0,0 +1,322 @@ +#include +#include + +#include "htab.h" +#include "objmgr.h" +#include "utils.h" +#include "zarray.h" + +static objmgr_t* objmgr_default = NULL; + +static void objtype_killer(objtype_t* typeval) +{ + if (typeval == NULL) { + return; + } + + if (typeval->fn_type_fini == NULL) { + return; + } + + typeval->fn_type_fini(typeval); +} + +int objmgr_init(objmgr_t* mgr) +{ + if (mgr == NULL) { + return -EINVAL; + } + + mylock_init(&(mgr->lock)); + + ht_init(&(mgr->names), 32, + string_hash_key); + zarray_init(&(mgr->types), 32, + (zarray_item_killer_t)objtype_killer); + return 0; +} + +void objmgr_fini(objmgr_t* mgr) +{ + if (mgr == NULL) { + return; + } + + zarray_fini(&(mgr->types)); + ht_fini(&(mgr->names)); + + mylock_fini(&(mgr->lock)); +} + +static int objmgr_register_internal(objmgr_t* mgr, + objtype_t* type) +{ + hent_t* e = NULL; + int idx; + + e = ht_get(&(mgr->names), (void*)type->type); + if (e != NULL) { + return e->data; + } + + e = ht_add(&(mgr->names), (void*)type->type); + if (e == NULL) { + return -ENOMEM; + } + + idx = zarray_store(&(mgr->types), type); + if (idx < 0) { + ht_del(&(mgr->names), (void*)type->type); + return idx; + } + + e->data = idx; + return idx; +} + +int obj_init(objmgr_t* mgr, + objtype_t* type, + int32_t exdata, + myobj_t* obj) +{ + obj->type = type; + obj->nref = 1; + obj->nread = 0; + obj->nwrite = 0; + obj->exdata = exdata; + obj->magic = OBJ_MAGIC; + + my_rwlock_init(&(obj->rwlock)); + mylock_init(&(obj->lock)); + + return 1; +} + +int objmgr_register(objmgr_t* mgr, + objtype_t* type) +{ + int rc = 0; + + /* clang-format off */ + if ((mgr == NULL) || + (type == NULL) || + (type->type == NULL) || + (type->fn_create == NULL)) { + return -EINVAL; + } + /* clang-format on */ + + mylock_init(&(type->lock)); + + mylock_lock(&(mgr->lock)); + rc = objmgr_register_internal(mgr, type); + mylock_unlock(&(mgr->lock)); + + return rc; +} + +static void* create_obj_ex(objmgr_t* mgr, + int type, + va_list ap) +{ + objtype_t* typeval = NULL; + void* obj; + + if ((type < 0) || (type >= mgr->types.caps)) { + SET_ERROR(EINVAL); + return NULL; + } + + typeval = (objtype_t*)zarray_get(&(mgr->types), type); + if (typeval == NULL) { + SET_ERROR(EINVAL); + return NULL; + } + + obj = typeval->fn_create(mgr, typeval, ap); + + return obj; +} + +void* create_obj_by_typeid(objmgr_t* mgr, + int type, + ...) +{ + va_list ap; + void* p = NULL; + + va_start(ap, type); + + p = create_obj_ex(mgr, type, ap); + + va_end(ap); + + return p; +} + +void* create_obj_by_typename(objmgr_t* mgr, + char* type, + ...) +{ + hent_t* e; + va_list ap; + void* p = NULL; + + mylock_lock(&(mgr->lock)); + e = ht_get(&(mgr->names), (void*)type); + mylock_unlock(&(mgr->lock)); + + if (e == NULL) { + SET_ERROR(EINVAL); + return NULL; + } + + if (e->data < 0) { + SET_ERROR(EINVAL); + return NULL; + } + + va_start(ap, type); + + p = create_obj_ex(mgr, e->data, ap); + + va_end(ap); + + return p; +} + +int typeid_of_name(objmgr_t* mgr, + char* type) +{ + hent_t* e; + int typeid; + + mylock_lock(&(mgr->lock)); + e = ht_get(&(mgr->names), (void*)type); + if (e == NULL) { + typeid = -ENOENT; + } else { + typeid = e->data; + } + mylock_unlock(&(mgr->lock)); + + return typeid; +} +void* obj_ref(void* obj, int op) +{ + myobj_t* myobj; + + if (obj == NULL) { + SET_ERROR(EINVAL); + return NULL; + } + + myobj = TO_MYOBJ(obj); + if (myobj->magic != OBJ_MAGIC) { + SET_ERROR(EINVAL); + return NULL; + } + + switch (op) { + case OBJREF_READ: + my_rwlock_rlock(&(myobj->rwlock)); + break; + case OBJREF_UPDATE: + my_rwlock_wlock(&(myobj->rwlock)); + break; + default: + break; + } + + mylock_lock(&(myobj->lock)); + switch (op) { + case OBJREF_READ: + myobj->nread++; + break; + case OBJREF_UPDATE: + myobj->nwrite++; + break; + default: + break; + } + + myobj->nref++; + mylock_unlock(&(myobj->lock)); + + return obj; +} + +void obj_deref(void* obj) +{ + myobj_t* myobj; + int nc; + objtype_t* typeval; + int release_rwlock = 0; + + if (obj == NULL) { + SET_ERROR(EINVAL); + return; + } + + myobj = TO_MYOBJ(obj); + if (myobj->magic != OBJ_MAGIC) { + SET_ERROR(EINVAL); + return; + } + + /* the object lock should be held */ + mylock_lock(&(myobj->lock)); + myobj->nref--; + nc = myobj->nref; + if ((myobj->nread > 0) || (myobj->nwrite > 0)) { + release_rwlock = 1; + if (myobj->nread > 0) { + myobj->nread--; + } else { + myobj->nwrite--; + } + } + mylock_unlock(&(myobj->lock)); + + if (release_rwlock) { + my_rwlock_unlock(&(myobj->rwlock)); + } + + if (nc > 0) { + return; + } + + typeval = myobj->type; + if (typeval == NULL) { + return; + } + + if (typeval->fn_fini != NULL) { + typeval->fn_fini(obj); + } + + return; +} + +objmgr_t* objmgr_get_default() +{ + return objmgr_default; +} + +int objmgr_set_default(objmgr_t* mgr) +{ + objmgr_default = mgr; + return 0; +} + +myobj_t *obj_alloc(size_t size) { + myobj_t *obj; + + if (size <= 0) { + SET_ERROR(EINVAL); + return NULL; + } + + obj = (myobj_t *)calloc(1, sizeof(*obj) + size); + return obj; +} diff --git a/src/lib/request.c b/src/lib/request.c new file mode 100644 index 00000000..908d98c2 --- /dev/null +++ b/src/lib/request.c @@ -0,0 +1,931 @@ +#include +#include +#include +#include +#include + +#include "mylock.h" +#include "netio.h" +#include "request.h" +#include "typemap.h" +#include "utils.h" +#include "xce/types.h" + +ioctx_t* ioctx_alloc(endpoint_t* ep, + xce_peerinfo_t* peer) +{ + ioctx_t* ctx; + + ctx = (ioctx_t*)calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + errno = -ENOMEM; + return NULL; + } + + ctx->ep = endpoint_ref(ep); + ctx->from = peer; + ctx->nrefs++; + return ctx; +} + +int ioctx_ref(ioctx_t* ctx) +{ + int old = ctx->nrefs; + + ctx->nrefs++; + + return old; +} + +static void ioctx_kill(ioctx_t* ctx, + int free_ctx) +{ + if (ctx == NULL) { + return; + } + + endpoint_deref(ctx->ep); + + free_packet(&(ctx->pkt)); + capn_free(&(ctx->c)); + if (free_ctx) { + free(ctx); + } +} + +void ioctx_deref(ioctx_t* ctx, + int free_ctx) +{ + if (ctx == NULL) { + return; + } + + if (ctx->nrefs == 0) { + WARN("Something wrong. Have you forgotten to call ioctx_ref()?"); + return; + } + ctx->nrefs--; + if (ctx->nrefs == 0) { + ioctx_kill(ctx, free_ctx); + } +} + +int ioctx_encode(ioctx_t* ctx, + xce_request_t* req) +{ + struct capn_segment* cs; + Request_ptr rp; + int rc; + + capn_init_malloc(&(ctx->c)); + cs = capn_root(&(ctx->c)).seg; + + encode_Request(cs, &(ctx->rq), req); + + cs = capn_root(&(ctx->c)).seg; + rp = new_Request(cs); + write_Request(&(ctx->rq), rp); + + capn_setp(capn_root(&(ctx->c)), 0, rp.p); + + ctx->pkt.sz = capn_size(&(ctx->c)); + rc = alloc_packet(&(ctx->pkt)); + if (rc < 0) { + return rc; + } + + capn_write_mem(&(ctx->c), + (uint8_t*)ctx->pkt.data, + ctx->pkt.sz, 0); + return 0; +} + +int ioctx_decode(ioctx_t* ctx, + xce_request_t* req) +{ + Request_ptr rp; + + capn_init_mem(&(ctx->c), (const uint8_t*)ctx->pkt.data, + ctx->pkt.sz, 0); + rp.p = capn_getp(capn_root(&(ctx->c)), 0, 1); + + read_Request(&(ctx->rq), rp); + + decode_Request(req, &(ctx->rq)); + + return 0; +} + +int ioctx_flush(ioctx_t* ctx, int fd) +{ + int rc; + + rc = write_packet(fd, &(ctx->pkt)); + return rc; +} + +void init_reply_by_req(xce_reply_t* reply, + xce_request_t* req) +{ + reply->seq = req->seq; + reply->opcode = req->opcode; +} + +int xce_request(ioctx_t* ctx, + xce_request_t* req) +{ + int rc; + + req->seq = endpoint_getseq(ctx->ep); + req->from = ctx->from; + + rc = ioctx_encode(ctx, req); + if (rc < 0) { + return rc; + } + + endpoint_enq(ctx->ep, &(ctx->link)); + return 0; +} + +int xce_reply_with_ctx(ioctx_t* ctx, + xce_peerinfo_t* from, + xce_reply_t* reply) +{ + /* clang-format off */ + xce_request_t request = { + .opcode = OPCode_reply, + .body_which = Request_body_replymsg, + }; + /* clang-format on */ + int rc; + + TRACE("%s seq %lu opcode %d status %d data which %d", + __func__, reply->seq, reply->opcode, + reply->status, reply->data_which); + + request.from = from; + request.body.replymsg = reply; + + request.seq = endpoint_getseq(ctx->ep); + + rc = ioctx_encode(ctx, &request); + if (rc < 0) { + return rc; + } + + endpoint_enq(ctx->ep, &(ctx->link)); + return 0; +} + +int xce_reply(endpoint_t* ep, + xce_peerinfo_t* from, + xce_reply_t* reply) +{ + ioctx_t* ctx; + + ctx = ioctx_alloc(ep, from); + if (ctx == NULL) { + return -ENOMEM; + } + + return xce_reply_with_ctx(ctx, from, reply); +} + +int xce_nop_req(ioctx_t* ctx) +{ + xce_request_t request = { + .opcode = OPCode_nop, + .body_which = Request_body_nomsg + }; + + if (ctx == NULL) { + return -EINVAL; + } + + return xce_request(ctx, &request); +} + +int xce_hello_req(ioctx_t* ctx, + char* msg) +{ + /* clang-format off */ + xce_request_t request = { + .opcode = OPCode_hello, + .body_which = Request_body_hellomsg, + .body = { + .hellomsg = msg + } + }; + /* clang-format on */ + + if ((ctx == NULL) || (msg == NULL)) { + return -EINVAL; + } + return xce_request(ctx, &request); +} + +int xce_join_req(ioctx_t* ctx, + int role, + hostattrs_t* attrs) +{ + /* clang-format off */ + xce_joindata_t joinmsg = { + .role = role + }; + xce_request_t request = { + .opcode = OPCode_join, + .body_which = Request_body_joinmsg, + .body = { + .joinmsg = &joinmsg + } + }; + + if ((role != HostRole_client) && + (role != HostRole_worker) && + (role != HostRole_scheduler)) { + return -EINVAL; + } + /* clang-format on */ + + if (role == HostRole_worker) { + if (attrs == NULL) { + return -EINVAL; + } + + joinmsg.data_which = JoinData_data_attrs; + joinmsg.data.attrs = attrs; + } + return xce_request(ctx, &request); +} + +int xce_shutdown_req(ioctx_t* ctx) +{ + int rc; + dataq_t* outq; + xce_request_t request = { + .opcode = OPCode_shutdown, + .body_which = Request_body_nomsg + }; + + if (ctx == NULL) { + return -EINVAL; + } + + rc = xce_request(ctx, &request); + if (rc < 0) { + return rc; + } + + outq = &(ctx->ep->outq); + + while (!DATAQ_EMPTY(outq)) { + sleep(1); + } + + return 0; +} + +int xce_pushconfig_req(endpoint_t* ep, + xce_peerinfo_t* from, + xce_configdata_t* config) +{ + int rc = 0; + xce_request_t request = { + .opcode = OPCode_push, + .body_which = Request_body_configpushmsg + }; + ioctx_t* ctx = NULL; + + if ((ep == NULL) || (config == NULL)) { + return -EINVAL; + } + + ctx = ioctx_alloc(ep, from); + if (ctx == NULL) { + return -ENOMEM; + } + + request.body.configpushmsg = config; + rc = xce_request(ctx, &request); + + return rc; +} + +static int xce_push_req(endpoint_t* ep, + xce_peerinfo_t* from, + xce_data_t* data) +{ + int rc = 0; + ioctx_t* ctx = NULL; + xce_request_t request = { + .opcode = OPCode_push, + .body_which = Request_body_pushmsg + }; + + if ((ep == NULL) || (from == NULL) || (data == NULL)) { + return -EINVAL; + } + + ctx = ioctx_alloc(ep, from); + if (ctx == NULL) { + return -ENOMEM; + } + + request.body.pushmsg = data; + + rc = xce_request(ctx, &request); + return rc; +} + +int xce_push_data_req(endpoint_t* ep, + xce_peerinfo_t* from, + xce_data_t* data, + xce_check_fn_t checkf, + void* checkarg, + int pktlimit) +{ + int nrows = 0; + int pos = 0; + int rc = 0; + xce_data_t data1; + int checkstatus = 0; + + if ((ep == NULL) || (from == NULL) || (data == NULL)) { + return -EINVAL; + } + + data1.table = data->table; + switch (data->table) { + case Data_data_schedjobs: + nrows = data->data.jobs->n_total; + data1.data.jobs = (xce_jobs_data_t*)calloc(1, sizeof(xce_jobs_data_t)); + if (data1.data.jobs == NULL) { + rc = -ENOMEM; + } + break; + case Data_data_schedworkers: + nrows = data->data.workers->n_total; + data1.data.workers = (xce_workers_data_t*)calloc(1, sizeof(xce_workers_data_t)); + if (data1.data.workers == NULL) { + rc = -ENOMEM; + } + break; + default: + rc = -EINVAL; + break; + } + + if (rc < 0) { + return rc; + } + + if (pktlimit <= 0) { + pktlimit = nrows; + } + + do { + int nc = nrows - pos; + + if (nc > pktlimit) { + nc = pktlimit; + } + + if (checkf != NULL) { + checkstatus = (*checkf)(checkarg); + if (checkstatus < 0) { + nc = 0; + } + } + + switch (data->table) { + case Data_data_schedjobs: + data1.data.jobs->n_total = data->data.jobs->n_total; + data1.data.jobs->pos = pos; + data1.data.jobs->count = nc; + if (nc == 0) { + data1.data.jobs->jobs = NULL; + } else { + data1.data.jobs->jobs = &(data->data.jobs->jobs[pos]); + } + break; + case Data_data_schedworkers: + data1.data.workers->n_total = data->data.workers->n_total; + data1.data.workers->pos = pos; + data1.data.workers->count = nc; + if (nc == 0) { + data1.data.workers->workers = NULL; + } else { + data1.data.workers->workers = &(data->data.workers->workers[pos]); + } + break; + default: + break; + } + + rc = xce_push_req(ep, from, &data1); + + if (rc < 0) { + break; + } + + pos += nc; + + } while ((pos < nrows) && (checkstatus >= 0)); + + switch (data->table) { + case Data_data_schedjobs: + FREEUP(data1.data.jobs); + break; + case Data_data_schedworkers: + FREEUP(data1.data.workers); + break; + default: + break; + } + + return rc; +} + +int xce_get_req(ioctx_t* ctx, + xce_get_t* get) +{ + /* clang-format off */ + xce_request_t request = { + .opcode = OPCode_get, + .body_which = Request_body_getmsg, + .body = { + .getmsg = get + } + }; + /* clang-format on */ + + return xce_request(ctx, &request); +} + +int xce_reply_get(endpoint_t* ep, + xce_peerinfo_t* from, + xce_reply_t* reply, + xce_check_fn_t checkf, + void* checkarg, + int pktlimit) +{ + int rc = 0; + int nrows = 0; + int pos = 0; + /* clang-format off */ + xce_data_t getdata = { + .table = reply->data.getdata->table + }; + xce_reply_t reply1 = { + .seq = reply->seq, + .opcode = reply->opcode, + .status = reply->status, + .data_which = reply->data_which, + .data = { + .getdata = &getdata + } + }; + /* clang-format on */ + int checkstatus = 0; + xce_data_t* data = reply->data.getdata; + + if ((ep == NULL) || (from == NULL) || (reply == NULL)) { + return -EINVAL; + } + + switch (getdata.table) { + case Data_data_schedjobs: + case Data_data_jobs: + nrows = data->data.jobs->n_total; + getdata.data.jobs = (xce_jobs_data_t*)calloc(1, sizeof(xce_jobs_data_t)); + break; + case Data_data_schedworkers: + case Data_data_workers: + nrows = data->data.workers->n_total; + getdata.data.workers = (xce_workers_data_t*)calloc(1, sizeof(xce_workers_data_t)); + break; + case Data_data_resources: + nrows = data->data.resources->n_total; + getdata.data.resources = (xce_resource_data_t*)calloc(1, sizeof(xce_resource_data_t)); + break; + case Data_data_resvals: + nrows = data->data.resvals->n_total; + getdata.data.resvals = (xce_resval_data_t*)calloc(1, sizeof(xce_resval_data_t)); + break; + default: + rc = -EINVAL; + break; + } + + if (rc < 0) { + /* FIXME we need to reply no data */ + return rc; + } + + if (pktlimit <= 0) { + pktlimit = nrows; + } + + do { + int nc = nrows - pos; + + if (nc > pktlimit) { + nc = pktlimit; + } + + if (checkf != NULL) { + checkstatus = (*checkf)(checkarg); + + if (checkstatus < 0) { + nc = 0; + } + } + + switch (getdata.table) { + case Data_data_schedjobs: + case Data_data_jobs: + getdata.data.jobs->n_total = data->data.jobs->n_total; + getdata.data.jobs->pos = pos; + getdata.data.jobs->count = nc; + if (nc == 0) { + getdata.data.jobs->jobs = NULL; + } else { + getdata.data.jobs->jobs = &(data->data.jobs->jobs[pos]); + } + break; + case Data_data_schedworkers: + case Data_data_workers: + getdata.data.workers->n_total = data->data.workers->n_total; + getdata.data.workers->pos = pos; + getdata.data.workers->count = nc; + if (nc == 0) { + getdata.data.workers->workers = NULL; + } else { + getdata.data.workers->workers = &(data->data.workers->workers[pos]); + } + break; + case Data_data_resources: + getdata.data.resources->n_total = data->data.resources->n_total; + getdata.data.resources->pos = pos; + getdata.data.workers->count = nc; + if (nc == 0) { + getdata.data.resources->resources = NULL; + } else { + getdata.data.resources->resources = &(data->data.resources->resources[pos]); + } + break; + case Data_data_resvals: + getdata.data.resvals->n_total = data->data.resvals->n_total; + getdata.data.resvals->pos = pos; + getdata.data.resvals->count = nc; + if (nc == 0) { + getdata.data.resvals->vals = NULL; + } else { + getdata.data.resvals->vals = &(data->data.resvals->vals[pos]); + } + break; + default: + /* should never goes here */ + break; + } + + rc = xce_reply(ep, from, &reply1); + if (rc < 0) { + break; + } + + pos += nc; + } while ((pos < nrows) && (checkstatus >= 0)); + + switch (getdata.table) { + case Data_data_schedjobs: + case Data_data_jobs: + FREEUP(getdata.data.jobs); + break; + case Data_data_schedworkers: + case Data_data_workers: + FREEUP(getdata.data.workers); + break; + case Data_data_resources: + FREEUP(getdata.data.resources); + break; + case Data_data_resvals: + FREEUP(getdata.data.resvals); + break; + default: + break; + } + + return rc; +} + +int extract_data(dataset_t* dataset, + xce_data_t* getdata) +{ + int ntotal; + int rc = 0; + int pos = 0; + int count = 0; + + TRACE("%s ...", __func__); + + switch (getdata->table) { + case Data_data_schedjobs: + case Data_data_jobs: + if (getdata->data.jobs->count <= 0) { + return 1; + } + + ntotal = getdata->data.jobs->n_total; + pos = getdata->data.jobs->pos; + count = getdata->data.jobs->count; + + if (dataset->rows == NULL) { + dataset->rows = (xce_job_t**)calloc(ntotal, sizeof(xce_job_t*)); + dataset->nrows = 0; + } + + memcpy((void*)(((char*)dataset->rows) + sizeof(xce_job_t*) * pos), + getdata->data.jobs->jobs, count * sizeof(xce_job_t*)); + memset(getdata->data.jobs->jobs, 0x0, count * sizeof(xce_job_t*)); + + break; + case Data_data_schedworkers: + case Data_data_workers: + if (getdata->data.workers->count <= 0) { + return 1; + } + + ntotal = getdata->data.workers->n_total; + if (dataset->rows == NULL) { + dataset->rows = (xce_worker_t**)calloc(ntotal, sizeof(xce_worker_t*)); + dataset->nrows = 0; + } + pos = getdata->data.workers->pos; + count = getdata->data.workers->count; + + memcpy((void*)(((char*)dataset->rows) + sizeof(xce_worker_t*) * pos), + getdata->data.workers->workers, count * sizeof(xce_worker_t*)); + memset(getdata->data.workers->workers, 0x0, count * sizeof(xce_worker_t*)); + + break; + case Data_data_resources: + if (getdata->data.resources->count <= 0) { + return 1; + } + + ntotal = getdata->data.resources->n_total; + if (dataset->rows == NULL) { + dataset->rows = (xce_resource_t**)calloc(ntotal, sizeof(xce_resource_t*)); + dataset->nrows = 0; + } + pos = getdata->data.resources->pos; + count = getdata->data.resources->count; + + memcpy((void*)(((char*)dataset->rows) + sizeof(xce_resource_t*) * pos), + getdata->data.resources->resources, count * sizeof(xce_resource_t*)); + + memset(getdata->data.resources->resources, 0x0, count * sizeof(xce_resource_t*)); + break; + case Data_data_resvals: + if (getdata->data.resvals->count <= 0) { + return 1; + } + + ntotal = getdata->data.resvals->n_total; + if (dataset->rows == NULL) { + dataset->rows = (xce_resval_t**)calloc(ntotal, sizeof(xce_resval_t*)); + dataset->nrows = 0; + } + + pos = getdata->data.resvals->pos; + count = getdata->data.resvals->count; + + memcpy((void*)(((char*)dataset->rows) + sizeof(xce_resval_t*) * pos), + getdata->data.resvals->vals, count * sizeof(xce_resval_t*)); + + memset(getdata->data.resvals->vals, 0x0, count * sizeof(xce_resval_t*)); + break; + default: + rc = -EINVAL; + break; + } + + if (rc < 0) { + return rc; + } + + dataset->nrows += count; + if (dataset->nrows < ntotal) { + return 0; + } + + return 1; +} + +int xce_jobdispatch_req(ioctx_t* ctx, + xce_job_dispatch_t* info) +{ + /* clang-format off */ + xce_request_t request = { + .opcode = OPCode_jobdispatch, + .body_which = Request_body_dispatchmsg, + .body = { + .dispatchmsg = info + } + }; + /* clang-format on */ + + /* clang-format off */ + if ((ctx == NULL) || + (info == NULL)) { + return -EINVAL; + } + /* clang-format on */ + + return xce_request(ctx, &request); +} + +int xce_notify_req(ioctx_t* ctx, + xce_notify_data_t* data) +{ + /* clang-format off */ + xce_request_t request = { + .opcode = OPCode_notify, + .body_which = Request_body_notifymsg, + .body = { + .notifymsg = data + } + }; + /* clang-forn on */ + + if ((ctx == NULL) || (data == NULL)) { + return -EINVAL; + } + + return xce_request(ctx, &request); +} + +int xce_jobsubmit_req(ioctx_t* ctx, + xce_job_submit_t* submit) +{ + /* clang-format off */ + xce_request_t request = { + .opcode = OPCode_jobsub, + .body_which = Request_body_jobsubmsg, + .body = { + .jobsubmsg = submit + } + }; + /*clang-format on*/ + + /* clang-format off */ + if ((ctx == NULL) || + (submit == NULL)) { + return -EINVAL; + } + /* clang-format on */ + + return xce_request(ctx, &request); +} + +int xce_startjob_req(ioctx_t* ctx, + xce_job_exec_t* execinfo) +{ + /* clang-format off */ + xce_request_t request = { + .opcode = OPCode_startjob, + .body_which = Request_body_jobstartmsg, + .body = { + .jobstartmsg = execinfo + } + }; + /* clang-format on */ + + return xce_request(ctx, &request); +} + +int xce_clusterconf_req(ioctx_t* ctx) +{ + /* clang-format off */ + xce_request_t request = { + .opcode = OPCode_clusterconf, + .body_which = Request_body_nomsg + }; + /* clang-format on */ + + return xce_request(ctx, &request); +} + +int xce_update_req(ioctx_t* ctx, + xce_update_data_t* data) +{ + /* clang-format off */ + xce_request_t request = { + .opcode = OPCode_update, + .body_which = Request_body_updatemsg, + .body = { + .updatemsg = data + } + }; + /* clang-format on */ + + if ((ctx == NULL) || (data == NULL)) { + return -EINVAL; + } + + return xce_request(ctx, &request); +} + +int xce_jobctrl_req(ioctx_t* ctx, + xce_jobctrl_t* ctrinfo) +{ + /* clang-format off */ + xce_request_t request = { + .opcode = OPCode_jobcontrol, + .body_which = Request_body_jobctrlmsg, + .body = { + .jobctrlmsg = ctrinfo + } + }; + /* clang-format on */ + + if ((ctx == NULL) || (ctrinfo == NULL)) { + return -EINVAL; + } + + if (ctrinfo->jobid == 0) { + return -EINVAL; + } + + switch (ctrinfo->action) { + case JobControl_u_siginfo: + break; + case JobControl_u_ckptoption: + if (ctrinfo->u.ckptoption->method == NULL) { + ctrinfo->u.ckptoption->method = "default"; + } + break; + default: + return -EINVAL; + break; + } + return xce_request(ctx, &request); +} + +int xce_queuectrl_req(ioctx_t* ctx, + xce_queuectrl_t* ctrlinfo) +{ + /* clang-format off */ + xce_request_t request = { + .opcode = OPCode_queuecontrol, + .body_which = Request_body_queuectrlmsg, + .body = { + .queuectrlmsg = ctrlinfo + } + }; + /* clang-format on */ + + if ((ctx == NULL) || (ctrlinfo == NULL)) { + return -EINVAL; + } + + if ((ctrlinfo->queue == NULL) || (strlen(ctrlinfo->queue) == 0)) { + return -EINVAL; + } + + if (ctrlinfo->action == QUEUE_DO_NONE) { + return 0; + } + + if ((ctrlinfo->action < 0) || (ctrlinfo->action > QUEUE_ACTIVE)) { + return -EINVAL; + } + + return xce_request(ctx, &request); +} + +int xce_runtask_req(ioctx_t* ctx, + xce_taskrun_t* runinfo) +{ + /* clang-format off */ + xce_request_t request = { + .opcode = OPCode_runtasks, + .body_which = Request_body_runtaskmsg, + .body = { + .runtaskmsg = runinfo + } + }; + /* clang-format on */ + + if ((ctx == NULL) || (runinfo == NULL)) { + return -EINVAL; + } + + if (runinfo->nhosts <= 0) { + return -EINVAL; + } + + return xce_request(ctx, &request); +} diff --git a/src/lib/testsuite/test.c b/src/lib/testsuite/test.c new file mode 100644 index 00000000..23553142 --- /dev/null +++ b/src/lib/testsuite/test.c @@ -0,0 +1,35 @@ +#include +#include +#include + +#include "unity.h" + +extern void test_xstrings(void); +extern void test_zarray(void); +extern void test_ht_string(void); +extern void test_ht_int(void); +extern void test_error(void); +extern void test_utils(void); + +void setUp(void) +{ + return; +} + +void tearDown(void) +{ + return; +} + +int main(int argc, char* argv[]) +{ + UNITY_BEGIN(); + test_ht_string(); + test_ht_int(); + test_zarray(); + test_xstrings(); + test_error(); + test_utils(); + + return UNITY_END(); +} diff --git a/src/lib/testsuite/test_error.c b/src/lib/testsuite/test_error.c new file mode 100644 index 00000000..92d7be37 --- /dev/null +++ b/src/lib/testsuite/test_error.c @@ -0,0 +1,44 @@ +#include +#include + +#include "xce/errnox.h" +#include "unity.h" +#include "utils.h" + +static void test_error_setget(void) { + int myerrno =1; + ectx_t *e; + + SET_ERROR(myerrno); + e = get_ectx(); + + TEST_ASSERT_TRUE(e != NULL); + TEST_ASSERT_TRUE(errno == myerrno); + TEST_ASSERT_TRUE(e->file != NULL); + TEST_ASSERT_TRUE(e->func != NULL); + TEST_ASSERT_TRUE(strcmp(e->file, __FILE__) == 0); + TEST_ASSERT_TRUE(strcmp(e->func, __func__) == 0); +} + +#if 0 +static void test_strerror_r(void) { + char errmsg1[256]; + char errmsg2[256]; + int errors[] ={ENOENT, EINVAL, E_XCE_BAD_JOB, E_XCE_BAD_WORKER, 0}; + int i; + + for(i = 0; errors[i] != 0; i ++) { + strerror_r(errors[i], errmsg1, sizeof(errmsg1)); + xce_strerror_r(errors[i], errmsg2, sizeof(errmsg2)); + TEST_ASSERT_TRUE(strcmp(errmsg1, errmsg2) == 0); + } +} +#endif +void test_error(void) { + printf("\n>> error test\n\n"); + + RUN_TEST(test_error_setget); +#if 0 + RUN_TEST(test_strerror_r); +#endif +} diff --git a/src/lib/testsuite/test_htab.c b/src/lib/testsuite/test_htab.c new file mode 100644 index 00000000..537f695e --- /dev/null +++ b/src/lib/testsuite/test_htab.c @@ -0,0 +1,50 @@ +#include +#include +#include + +#include "unity.h" +#include "htab.h" + +static htab_t htab; +static char *s = "Hello,world"; + +static void test_ht_add_string(void) { + hent_t *e = NULL; + + e = ht_add(&(htab), (void *)s); + TEST_ASSERT_NOT_NULL(e); + + return; +} + +static void test_ht_get_string(void) { + hent_t *e = NULL; + + e = ht_get(&htab, (void *)s); + TEST_ASSERT_NOT_NULL(e); + + TEST_ASSERT_TRUE(0 == strcmp(e->key, s)); + + return; +} + +static void test_ht_del_string(void) { + hent_t *e = NULL; + + ht_del(&htab, (void *)s); + + e = ht_get(&htab, (void *)s); + TEST_ASSERT_TRUE( e == NULL); + + return; +} + +void test_ht_string(void) { + printf("\n>> htab test string\n\n"); + + ht_init(&htab, 13, string_hash_key); + + RUN_TEST(test_ht_add_string); + RUN_TEST(test_ht_get_string); + RUN_TEST(test_ht_del_string); +} diff --git a/src/lib/testsuite/test_htab_int.c b/src/lib/testsuite/test_htab_int.c new file mode 100644 index 00000000..a206f203 --- /dev/null +++ b/src/lib/testsuite/test_htab_int.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +#include "unity.h" +#include "htab.h" + +static htab_t htab; + +uint64_t key = (uint64_t)0xfabcde6666666666; + +static void test_ht_add_string(void) { + hent_t *e = NULL; + + e = ht_add(&(htab), (void *)key); + TEST_ASSERT_NOT_NULL(e); + + return; +} + +static void test_ht_get_string(void) { + hent_t *e = NULL; + + e = ht_get(&htab, (void *)key); + TEST_ASSERT_NOT_NULL(e); + + TEST_ASSERT_TRUE((uint64_t)e->key == (uint64_t)key); + + return; +} + +static void test_ht_del_string(void) { + hent_t *e = NULL; + + ht_del(&htab, (void *)key); + + e = ht_get(&htab, (void *)key); + TEST_ASSERT_TRUE( e == NULL); + + return; +} + +void test_ht_int(void) { + printf("\n>> htab test int\n\n"); + + ht_init(&htab, 13, int_hash_key); + + RUN_TEST(test_ht_add_string); + RUN_TEST(test_ht_get_string); + RUN_TEST(test_ht_del_string); +} diff --git a/src/lib/testsuite/test_utils.c b/src/lib/testsuite/test_utils.c new file mode 100644 index 00000000..1216369a --- /dev/null +++ b/src/lib/testsuite/test_utils.c @@ -0,0 +1,105 @@ +#include +#include +#include + +#include "unity.h" +#include "utils.h" +#include "xce/types.h" + +static void test_timewindow_config_dup() +{ + /* clang-format off */ + xce_timewindow_config_t win1 = { + .nsegs = 2, + .segs = (xce_timewindow_seg_config_t*[]) { + &(xce_timewindow_seg_config_t) { + .tz = "GMT-8", + .open = &(xce_timewindow_time_t) { + .day = 0, + .hour = 9, + .min = 0 }, + .close = &(xce_timewindow_time_t) { + .day = 0, + .hour = 17, + .min = 59 } }, + &(xce_timewindow_seg_config_t) { + .tz = "GMT-8", + .open = &(xce_timewindow_time_t) { + .day = 5, + .hour = 21, + .min = 0 }, + .close = &(xce_timewindow_time_t) { + .day = 7, + .hour = 20, + .min = 59 } } } + }; + /* clang-format on */ + xce_timewindow_config_t* win2 = NULL; + + win2 = dup_timewindow_config(&win1); + + TEST_ASSERT_TRUE(win2 != NULL); + TEST_ASSERT_TRUE(win2->nsegs == 2); + TEST_ASSERT_TRUE((strcmp(win2->segs[0]->tz, "GMT-8") == 0)); + TEST_ASSERT_TRUE(win2->segs[0]->open->day == 0); + TEST_ASSERT_TRUE(win2->segs[0]->open->hour == 9); + TEST_ASSERT_TRUE(win2->segs[0]->open->min == 0); + TEST_ASSERT_TRUE(win2->segs[0]->close->day == 0); + TEST_ASSERT_TRUE(win2->segs[0]->close->hour == 17); + TEST_ASSERT_TRUE(win2->segs[0]->close->min == 59); + + TEST_ASSERT_TRUE((strcmp(win2->segs[1]->tz, "GMT-8") == 0)); + TEST_ASSERT_TRUE(win2->segs[1]->open->day == 5); + TEST_ASSERT_TRUE(win2->segs[1]->open->hour == 21); + TEST_ASSERT_TRUE(win2->segs[1]->open->min == 0); + TEST_ASSERT_TRUE(win2->segs[1]->close->day == 7); + TEST_ASSERT_TRUE(win2->segs[1]->close->hour == 20); + TEST_ASSERT_TRUE(win2->segs[1]->close->min == 59); + + free_timewindow_config(win2); + + return; +} + +void test_dup_threshold() +{ + /* clang-format off */ + xce_res_threshold_t* threshold[2] = { + &(xce_res_threshold_t) { + .name = "r15s", + .sched = 1.0, + .stop = 5.0 }, + &(xce_res_threshold_t) { + .name = "r1m", + .sched = 0.9, + .stop = 4.5 } + }; + /* clang-format on */ + xce_res_threshold_t** threshold2 = NULL; + + threshold2 = dup_resource_thresholds(threshold, 2); + + TEST_ASSERT_TRUE(threshold2 != NULL); + + TEST_ASSERT_TRUE(strcmp(threshold[0]->name, threshold2[0]->name) == 0); + TEST_ASSERT_TRUE(strcmp(threshold[1]->name, threshold2[1]->name) == 0); + TEST_ASSERT_TRUE(float_equal(threshold[0]->sched, + threshold2[0]->sched)); + TEST_ASSERT_TRUE(float_equal(threshold[0]->stop, + threshold2[0]->stop)); + TEST_ASSERT_TRUE(float_equal(threshold[1]->sched, + threshold2[1]->sched)); + TEST_ASSERT_TRUE(float_equal(threshold[1]->stop, + threshold2[1]->stop)); + + free_resource_thresholds(threshold2, 2); + return; +} + +void test_utils(void) +{ + printf("\n>> utils test\n\n"); + + RUN_TEST(test_timewindow_config_dup); + RUN_TEST(test_dup_threshold); +} diff --git a/src/lib/testsuite/test_xstring.c b/src/lib/testsuite/test_xstring.c new file mode 100644 index 00000000..2c20b70d --- /dev/null +++ b/src/lib/testsuite/test_xstring.c @@ -0,0 +1,128 @@ +#include +#include +#include + +#include "objmgr.h" +#include "unity.h" +#include "xstring.h" + +void test_xstring_create(void) +{ + objmgr_t mgr; + char* s1 = "Hello,world"; + char* s2 = NULL; + int rc = 0; + myobj_t* obj; + + objmgr_init(&mgr); + register_xstring(&mgr,4,4); + TEST_ASSERT_EQUAL(1, mgr.types.count); + + s2 = create_obj_by_typename(&mgr, "xstring", s1); + TEST_ASSERT_NOT_NULL(s2); + obj = TO_MYOBJ(s2); + TEST_ASSERT_EQUAL(1, XSTRING_OBJ_TYPE_STRINGS(obj).count); + + rc = strcmp(s1, s2); + TEST_ASSERT_EQUAL(0, rc); + + objmgr_fini(&mgr); +} + +void test_xstring_ref(void) +{ + objmgr_t mgr; + char* s1 = NULL; + char* s2 = NULL; + myobj_t* obj; + + objmgr_init(&mgr); + register_xstring(&mgr,4,4); + TEST_ASSERT_EQUAL(1, mgr.types.count); + + s1 = create_obj_by_typename(&mgr, "xstring", + "Hello,world"); + TEST_ASSERT_NOT_NULL(s1); + + obj = TO_MYOBJ(s1); + TEST_ASSERT_EQUAL(1, XSTRING_OBJ_TYPE_STRINGS(obj).count); + + s2 = (char*)obj_ref(s1, OBJREF_READ); + TEST_ASSERT_EQUAL(s1, s2); + + TEST_ASSERT_EQUAL(2, obj->nref); + objmgr_fini(&mgr); +} + +void test_xstring_deref(void) +{ + objmgr_t mgr; + char* s1 = "Hello,world"; + char* s2 = NULL; + int rc = 0; + myobj_t* obj; + + objmgr_init(&mgr); + register_xstring(&mgr,4,4); + TEST_ASSERT_EQUAL(1, mgr.types.count); + + s2 = create_obj_by_typename(&mgr, "xstring", s1); + TEST_ASSERT_NOT_NULL(s2); + + rc = strcmp(s1, s2); + + TEST_ASSERT_EQUAL(0, rc); + if (rc == 0) { + objtype_t *typeval; + + obj = TO_MYOBJ(s2); + typeval = obj->type; + + obj_deref(s2); + + TEST_ASSERT_EQUAL(0, XSTRING_TYPE_STRINGS(typeval).count); + } + + objmgr_fini(&mgr); +} + +void test_xstring_share(void) +{ + objmgr_t mgr; + char* s1 = "Hello,world"; + char* s2 = NULL; + char* s3 = NULL; + int rc = 0; + + objmgr_init(&mgr); + register_xstring(&mgr,4,4); + TEST_ASSERT_EQUAL(1, mgr.types.count); + + s2 = create_obj_by_typename(&mgr, "xstring", s1); + TEST_ASSERT_NOT_NULL(s2); + + rc = strcmp(s1, s2); + + TEST_ASSERT_EQUAL(0, rc); + s3 = create_obj_by_typename(&mgr, "xstring", s1); + TEST_ASSERT_EQUAL(s2, s3); + if (1) { + myobj_t* obj; + + obj = TO_MYOBJ(s3); + TEST_ASSERT_EQUAL(2, obj->nref); + } + + objmgr_fini(&mgr); +} + +void test_xstrings(void) +{ + printf("\n>> xstring test\n\n"); + RUN_TEST(test_xstring_create); + RUN_TEST(test_xstring_ref); + RUN_TEST(test_xstring_deref); + RUN_TEST(test_xstring_share); + + return; +} diff --git a/src/lib/testsuite/test_zarray.c b/src/lib/testsuite/test_zarray.c new file mode 100644 index 00000000..4a68cfb3 --- /dev/null +++ b/src/lib/testsuite/test_zarray.c @@ -0,0 +1,102 @@ +#include +#include +#include + +#include "unity.h" +#include "zarray.h" + +static void test_zarray_create(void) { + zarray_t array; + + zarray_init(&array, 8, NULL); + + TEST_ASSERT_EQUAL(0,array.count); + TEST_ASSERT_NULL(array.data); +} + +static void test_zarray_store(void) { + zarray_t array; + int idx; + char *s1 = "hello"; + char *s2 = NULL; + + zarray_init(&array, 8, NULL); + idx = zarray_store(&array, (void *)s1); + TEST_ASSERT_TRUE(idx >= 0); + s2 = (char *)zarray_get(&array, idx); + TEST_ASSERT_NOT_NULL(s2); + TEST_ASSERT_EQUAL(0, strcmp(s1, s2)); + + zarray_fini(&(array)); +} + +static void test_zarray_del(void) { + zarray_t array; + int idx; + char *s1 = "hello"; + + zarray_init(&array, 8, NULL); + idx = zarray_store(&array, (void *)s1); + TEST_ASSERT_TRUE(idx >= 0); + TEST_ASSERT_TRUE(array.count == 1); + zarray_del(&array, idx); + TEST_ASSERT_TRUE(zarray_get(&array, idx) == NULL); + TEST_ASSERT_TRUE(array.count == 0); + + zarray_fini(&array); +} + +static void test_zarray_put(void) { + zarray_t array; + int idx; + char *s1 = "hello"; + char *s2 = "test"; + + zarray_init(&array, 8, NULL); + idx = zarray_store(&array, (void *)s1); + TEST_ASSERT_TRUE(idx >= 0); + TEST_ASSERT_TRUE(array.count == 1); + TEST_ASSERT_TRUE(zarray_get(&array, idx) != NULL); + + TEST_ASSERT_TRUE(strcmp((char *)zarray_get(&array, idx), s1) == 0); + + zarray_put(&array, idx, (void *)s2); + TEST_ASSERT_TRUE(zarray_get(&array, idx) != NULL); + TEST_ASSERT_TRUE(strcmp((char *)zarray_get(&array, idx), s2) == 0); + + zarray_fini(&array); +} + +static int sum_(void *arg1, void *arg2) { + int *pv = (int *)arg1; + int x = (int)((long)arg2); + + (*pv) += x; + return 0; +} + +static void test_zarray_iter(void) { + zarray_t array; + int i; + int val = 0; + + zarray_init(&array, 10, NULL); + for(i = 0; i < 10; i ++) { + zarray_store(&array, (void *)(long)i); + } + + zarray_iter(&array, (zarray_iter_fn_t)sum_, &val); + + TEST_ASSERT_TRUE(val == 45); + + zarray_fini(&(array)); +} +void test_zarray(void) { + printf("\n>> zarray test\n\n"); + + RUN_TEST(test_zarray_create); + RUN_TEST(test_zarray_store); + RUN_TEST(test_zarray_del); + RUN_TEST(test_zarray_put); + RUN_TEST(test_zarray_iter); +} diff --git a/src/lib/threshold.c b/src/lib/threshold.c new file mode 100644 index 00000000..d574f994 --- /dev/null +++ b/src/lib/threshold.c @@ -0,0 +1,81 @@ +#include +#include + +#include "utils.h" +#include "xce/errnox.h" +#include "xce/types.h" + +static void kill_thresholds(xce_res_threshold_t** thresholds, + int count) +{ + int i; + + if (thresholds == NULL) { + return; + } + + if (count > 0) { + for (i = 0; i < count; i++) { + xce_res_threshold_t* it = thresholds[i]; + + if (it == NULL) { + continue; + } + + FREEUP(it->name); + FREEUP(it); + } + } + + FREEUP(thresholds); +} + +void free_resource_thresholds(xce_res_threshold_t** thresholds, + int count) +{ + kill_thresholds(thresholds, count); +} + +xce_res_threshold_t** dup_resource_thresholds(xce_res_threshold_t** src, + int count) +{ + xce_res_threshold_t** thresholds = NULL; + int i; + + if ((src == NULL) || (count <= 0)) { + errno = EINVAL; + return NULL; + } + + thresholds = (xce_res_threshold_t**)calloc(count, sizeof(xce_res_threshold_t*)); + if (thresholds == NULL) { + errno = ENOMEM; + return NULL; + } + + for (i = 0; i < count; i++) { + xce_res_threshold_t* it = (xce_res_threshold_t*)calloc(1, sizeof(*it)); + + if (it == NULL) { + kill_thresholds(thresholds, i); + errno = ENOMEM; + + return NULL; + } + + thresholds[i] = it; + + it->name = strdup(src[i]->name); + if (it->name == NULL) { + kill_thresholds(thresholds, i + 1); + errno = ENOMEM; + + return NULL; + } + + it->sched = src[i]->sched; + it->stop = src[i]->stop; + } + + return thresholds; +} diff --git a/src/lib/utils.c b/src/lib/utils.c new file mode 100755 index 00000000..b6aeafe2 --- /dev/null +++ b/src/lib/utils.c @@ -0,0 +1,371 @@ +#include +#include +#include +#include +#include +#if defined(__GLIBC__) && (__GLIBC__ == 2 && __GLIBC_MINOR__ < 28) +#include +#else +#include +#endif +#include +#include + +#if defined(__linux__) +#include +#endif + +#include "config.h" +#include "controller.capnp.h" +#include + +#include "utils.h" +#include "xce/errnox.h" +#include "xce/types.h" + +static capn_text chars_to_text_internal(const char* chars) +{ + capn_text data = { + .len = strlen(chars), + .str = chars, + .seg = NULL, + }; + + return data; +} + +capn_text chars_to_text(const char* chars) +{ + if (chars == NULL) { + chars = ""; + } + + return chars_to_text_internal(chars); +} + +#define ARGV_INCR_DELTA (16) + +#define FILL_ARGV(rc, argv, argc, maxargc, delta, s) \ + do { \ + (rc) = 0; \ + char* s1; \ + if (((argc) >= (maxargc))) { \ + char** p; \ + int nc, i; \ + nc = (maxargc) + (delta); \ + p = (char**)realloc((argv), nc * sizeof(char*)); \ + if (p == NULL) { \ + (rc) = -ENOMEM; \ + break; \ + } \ + for (i = (maxargc); i < nc; i++) { \ + p[i] = NULL; \ + } \ + (argv) = p; \ + (maxargc) = nc; \ + } \ + s1 = strdup(s); \ + if (s1 == NULL) { \ + (rc) = -ENOMEM; \ + break; \ + } \ + (argv)[argc] = s1; \ + (argc)++; \ + } while (0) + +#define FREE_ARGV(argv, argc) \ + do { \ + int i; \ + if ((argv) == NULL) { \ + break; \ + } \ + for (i = 0; i < (argc); i++) { \ + if ((argv)[i] != NULL) { \ + free((argv)[i]); \ + (argv)[i] = NULL; \ + } \ + } \ + free(argv); \ + } while (0) + +int parse_argv(char* input, + char*** argv) +{ + int max_argc = 0; + char* arg = NULL; + int i = 0; + int in_quotes = 0; + char quote_char = 0; + int argc = 0; + int rc = 0; + + rc = 0; + arg = (char*)malloc(strlen(input) + 1); + if (arg == NULL) { + return -ENOMEM; + } + + *argv = NULL; + while (*input) { + if (in_quotes) { + if (*input == quote_char) { + in_quotes = 0; + } else if (*input == '\\') { + input++; + if (*input) { + arg[i++] = *input; + } + } else { + arg[i++] = *input; + } + } else { + if (isspace(*input)) { + if (i > 0) { + arg[i] = '\0'; + FILL_ARGV(rc, *argv, argc, max_argc, + ARGV_INCR_DELTA, arg); + if (rc < 0) { + FREE_ARGV(*argv, argc); + free(arg); + return rc; + } + i = 0; + } + } else if ((*input == '"') || (*input == '\'')) { + in_quotes = 1; + quote_char = *input; + } else if (*input == '\\') { + input++; + if (*input) { + arg[i++] = *input; + } + } else { + arg[i++] = *input; + } + } + input++; + } + + if (i > 0) { + arg[i] = '\0'; + FILL_ARGV(rc, *argv, argc, max_argc, + ARGV_INCR_DELTA, arg); + if (rc < 0) { + FREE_ARGV(*argv, argc); + free(arg); + return rc; + } + } + + free(arg); + return argc; +} + +void free_argv(char** argv, int argc) +{ + FREE_ARGV(argv, argc); +} + +#if 0 +void freeup_kvs(int count, + xce_kv_t* vals) +{ + int i; + + if (vals == NULL) { + return; + } + + for (i = 0; i < count; i++) { + if (vals[i].value.which != XceFieldValue_data_svalue) { + continue; + } + + FREEUP(vals[i].value.u.svalue); + } + + FREEUP(vals); +} +#endif + +char* frame_symbol(int k) +{ +#if defined(__linux__) + void* array[k + 1]; + size_t size = backtrace(array, k + 1); + char** symbols = backtrace_symbols(array, size); + char* s = NULL; + + if (symbols == NULL) { + return NULL; + } + + s = strdup(symbols[MIN(size - 1, k)]); + free(symbols); + return s; +#else + return NULL; +#endif +} + +int xce_vprintf(const char* fmt, va_list ap) +{ + int rc = 0; + + /* FIXME: */ + return rc; +} + +static _Thread_local ectx_t ectx; + +void set_error(char* file, + char* func, + int line, + int code) +{ + ectx.file = file; + ectx.func = func; + ectx.line = line; + ectx.code = code; + errno = code; +} + +ectx_t* get_ectx() +{ + return &ectx; +} + +static char* xce_err_str[] = { + "invalid job", + "invalid worker", + "duplicated jobs", + "duplicated workers", + "bad opcode", + "unknown role", + "unknown resource", + "unknown queue", + "unknown group", + "internal error", + NULL +}; + +int xce_strerror_r(int errnum, + char* buf, + size_t bufsize) +{ + if (errnum < XCE_ERRNO_BASE) { + return strerror_r(errnum, buf, bufsize); + } + + if (errnum >= E_XCE_MAX) { + strncpy(buf, "unknown error", bufsize); + return -1; + } + + strncpy(buf, xce_err_str[errnum - XCE_ERRNO_BASE], + bufsize); + return 0; +} + +int copy_int_list(int** dst, + int* src, + int count) +{ + int i; + + FREEUP(*dst); + if (count == 0) { + return 0; + } + + *dst = (int*)calloc(count, sizeof(int)); + if ((*dst) == NULL) { + return -ENOMEM; + } + + for (i = 0; i < count; i++) { + (*dst)[i] = (int)src[i]; + } + + return count; +} + +int copy_strlist(xce_strlist_t* dst, + xce_strlist_t src) +{ + if (!dst) { + return -1; + } + for (int i = 0; i < dst->count; i++) { + FREEUP(dst->data[i]); + } + FREEUP(dst->data); + dst->count = src.count; + if (dst->count == 0) { + return 0; + } + + dst->data = (char**)calloc(dst->count, sizeof(char*)); + if (dst->data == NULL) { + return -ENOMEM; + } + for (int i = 0; i < src.count; i++) { + if (src.data[i]) { + dst->data[i] = strndup(src.data[i], strlen(src.data[i])); + if (dst->data[i] == NULL) { + return -ENOMEM; + } + } + } + return 0; +} +void free_resval_with_idx_list(xce_val_with_idx_t*** vals, + int count) +{ + xce_val_with_idx_t** resvals = *vals; + int i; + + if (resvals == NULL) { + return; + } + + if (count <= 0) { + return; + } + + for (i = 0; i < count; i++) { + xce_val_with_idx_t* val = resvals[i]; + + if (val == NULL) { + continue; + } + + if (val->val->which == Value_u_svalue) { + FREEUP(val->val->u.svalue); + } + + FREEUP(val->val); + FREEUP(val); + } + + FREEUP(resvals); + *vals = NULL; +} + +void free_strlist(xce_strlist_t *l) { + int i; + + if ( l == NULL) { + return; + } + + if ((l->count <= 0) || (l->data == NULL)) { + return; + } + + for(i = 0; i < l->count; i ++) { + FREEUP(l->data[i]); + } + + FREEUP(l->data); +} diff --git a/src/lib/vtaskmgr.c b/src/lib/vtaskmgr.c new file mode 100644 index 00000000..6020525b --- /dev/null +++ b/src/lib/vtaskmgr.c @@ -0,0 +1,362 @@ +#include +#include +#include +#include + +#include "mylock.h" +#include "netio.h" +#include "utils.h" +#include "vtaskmgr.h" + +static int bind_vtask(vtask_t*, vcpu_t*); + +vtask_t* vtask_alloc() +{ + vtask_t* task; + + task = calloc(1, sizeof(*task)); + return task; +} + +int vtask_init(vtask_t* task, + vtask_func_t entry, + endpoint_t* ep) +{ + int rc; + + task->entry = entry; + task->vcpu = -1; + task->ctx.ep = endpoint_ref(ep); + + rc = read_packet(ep->fd, &(task->ctx.pkt)); + if (rc < 0) { + free_packet(&(task->ctx.pkt)); + endpoint_deref(task->ctx.ep); + task->ctx.ep = NULL; + } + + return rc; +} + +void vtask_fini(vtask_t* task) +{ + if (task == NULL) { + return; + } + + ioctx_deref(&(task->ctx), 0); + + return; +} + +void vcpu_idle(vcpu_t* vcpu) +{ + vtaskmgr_t* vtaskmgr = (vtaskmgr_t*)vcpu->owner; + + vcpu->task = NULL; + cbuf_put(&(vtaskmgr->wbuf), + (void*)&(vcpu->cpuid)); + cbuf_get(&(vcpu->wbuf), + (void*)&(vcpu->task)); + return; +} + +void run_task(vtask_t* task) +{ + vtaskmgr_t *vtaskmgr; + + if (task->entry != NULL) { + (task->entry)(task); + } + + endpoint_unblock_tasks(task->ctx.ep); + vtaskmgr = (vtaskmgr_t *)task->owner; + if (vtaskmgr != NULL) { + /* wake up dispatcher */ + vtaskmgr_wakeup(vtaskmgr); + } + + return; +} + +static void* vcpu_entry(void* arg) +{ + vcpu_t* my = (vcpu_t*)arg; + + while (1) { + if (my->task != NULL) { + vtask_t* t = my->task; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + my->task = NULL; + run_task(t); + vtask_fini(t); + free(t); + my->state = VCPU_IDLE; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + } else { + vcpu_idle(my); + } + pthread_testcancel(); + } + return NULL; +} + +int vcpu_init(vcpu_t* vcpu, + int cpuid, + void* owner) +{ + vcpu->state = VCPU_IDLE; + vcpu->vcpu = 0; + vcpu->cpuid = cpuid; + vcpu->owner = owner; + vcpu->task = NULL; + cbuf_init(&(vcpu->wbuf), 1, sizeof(void*)); + + return 0; +} + +int vcpu_start(vcpu_t* vcpu) +{ + int rc; + + rc = pthread_create(&(vcpu->vcpu), NULL, + &vcpu_entry, vcpu); + if (rc != 0) { + vcpu->state = VCPU_ERR; + return -errno; + } + return rc; +} + +void vcpu_fini(vcpu_t* vcpu) +{ + int rc; + void* res; + + if (vcpu->vcpu) { + /* wakeup vcpu first */ + bind_vtask(NULL, vcpu); + rc = pthread_cancel(vcpu->vcpu); + if (rc != 0) { + cbuf_fini(&(vcpu->wbuf)); + return; + } + + rc = pthread_join(vcpu->vcpu, &res); + if (rc != 0) { + cbuf_fini(&(vcpu->wbuf)); + return; + } + } + + cbuf_fini(&(vcpu->wbuf)); + + return; +} + +static void taskq_item_killer(data_item_t* it) +{ + if (it != NULL) { + vtask_t* task = ITPTR_TO_VTASK(it); + vtask_fini(task); + free(task); + } +} + +int vtaskmgr_init(vtaskmgr_t* vtaskmgr, + int nvcpus) +{ + int i; + + if ((vtaskmgr == NULL) || (nvcpus <= 0)) { + return -EINVAL; + } + + vtaskmgr->dispatcher = 0; + vtaskmgr->n_vcpus = nvcpus; + vtaskmgr->vcpus = (vcpu_t*)calloc(nvcpus, + sizeof(vcpu_t)); + if (vtaskmgr->vcpus == NULL) { + return -ENOMEM; + } + for (i = 0; i < nvcpus; i++) { + vcpu_init(&(vtaskmgr->vcpus[i]), + i, vtaskmgr); + } + + cbuf_init(&(vtaskmgr->wbuf), + nvcpus, sizeof(int)); + cbuf_init(&(vtaskmgr->wtbuf), + 1, sizeof(int)); + + dataq_init(&(vtaskmgr->taskq), + taskq_item_killer); + + return 0; +} + +static vcpu_t* pick_idle_vcpu(vtaskmgr_t* vtaskmgr) +{ + int i; + + cbuf_get(&(vtaskmgr->wbuf), &i); + if ((i < 0) || (i >= vtaskmgr->n_vcpus)) { + return NULL; + } + + TRACE("%s pick idle cpu #%d", + __func__, i); + + return &(vtaskmgr->vcpus[i]); +} + +static int vtask_eligible(data_item_t* data) +{ + vtask_t* task = ITPTR_TO_VTASK(data); + int eligible = 0; + + if (task->ctx.ep == NULL) { + WARN("no endpoint for task 0x%p", task); + return 0; + } + + eligible = !(endpoint_is_task_blocked(task->ctx.ep)); + TRACE("%s vtask %p is %s", + __func__, task, + eligible?"eligible":"not eligible"); + + return eligible; +} + +static vtask_t* pick_eligible_task(vtaskmgr_t* vtaskmgr) +{ + data_item_t* data; + vtask_t* task = NULL; + + data = dataq_deq(&(vtaskmgr->taskq), vtask_eligible); + if (data == NULL) { + return NULL; + } + + task = ITPTR_TO_VTASK(data); + + return task; +} + +static int bind_vtask(vtask_t* task, + vcpu_t* vcpu) +{ + TRACE("binding task %p to cpu#%d\n", + task, vcpu->cpuid); + + if (task != NULL) { + endpoint_block_tasks(task->ctx.ep); + + task->vcpu = vcpu->cpuid; + } + + cbuf_put(&(vcpu->wbuf), (void*)&task); + + return 0; +} + +static void* vdispatcher_entry(void* arg) +{ + vtaskmgr_t* vtaskmgr = (vtaskmgr_t*)arg; + vcpu_t* vcpu = NULL; + vtask_t* task = NULL; + + while (1) { + pthread_testcancel(); + if (vcpu == NULL) { + vcpu = pick_idle_vcpu(vtaskmgr); + if (vcpu == NULL) { + continue; + } + } + + task = pick_eligible_task(vtaskmgr); + if (task != NULL) { + bind_vtask(task, vcpu); + vcpu = NULL; + task = NULL; + } + else { + vtaskmgr_wait(vtaskmgr); + } + } + return NULL; +} + +int vtaskmgr_start(vtaskmgr_t* vtaskmgr) +{ + int i, rc; + + rc = pthread_create(&(vtaskmgr->dispatcher), NULL, + &vdispatcher_entry, vtaskmgr); + if (rc != 0) { + return -errno; + } + + for (i = 0; i < vtaskmgr->n_vcpus; i++) { + vcpu_start(&(vtaskmgr->vcpus[i])); + } + + return 0; +} + +void vtaskmgr_wait(vtaskmgr_t *vtaskmgr) { + int dummy = 0; + + cbuf_get(&(vtaskmgr->wtbuf), &dummy); +} + +void vtaskmgr_wakeup(vtaskmgr_t *vtaskmgr) { + int dummy = 0; + + cbuf_tryput(&(vtaskmgr->wtbuf), &dummy); +} + +void vtaskmgr_fini(vtaskmgr_t* vtaskmgr) +{ + int i; + void* res; + + if (vtaskmgr->dispatcher != 0) { + pthread_cancel(vtaskmgr->dispatcher); + pthread_join(vtaskmgr->dispatcher, &res); + } + + if (vtaskmgr->vcpus != NULL) { + for (i = 0; i < vtaskmgr->n_vcpus; i++) { + vcpu_fini(&(vtaskmgr->vcpus[i])); + } + free(vtaskmgr->vcpus); + } + + dataq_fini(&(vtaskmgr->taskq)); + cbuf_fini(&(vtaskmgr->wtbuf)); + cbuf_fini(&(vtaskmgr->wbuf)); + + return; +} + +int vtask_enq(vtaskmgr_t* vtaskmgr, + vtask_t* task) +{ + int rc = 0; + ioctx_ref(&(task->ctx)); + + rc = dataq_enq(&(vtaskmgr->taskq), + &(task->ctx.link)); + if (rc >= 0) { + /* wake up task dispatcher */ + task->owner = vtaskmgr; + vtaskmgr_wakeup(vtaskmgr); + } + + return rc; +} diff --git a/src/lib/window.c b/src/lib/window.c new file mode 100644 index 00000000..a2afd906 --- /dev/null +++ b/src/lib/window.c @@ -0,0 +1,126 @@ +#include +#include + +#include "utils.h" +#include "xce/errnox.h" +#include "xce/types.h" + +static void kill_timewindow_time(xce_timewindow_time_t* t) +{ + FREEUP(t); +} + +static void kill_timewindow_seg_config(xce_timewindow_seg_config_t* s) +{ + if (s == NULL) { + return; + } + + FREEUP(s->tz); + + kill_timewindow_time(s->open); + kill_timewindow_time(s->close); + FREEUP(s); +} + +static void kill_timewindow_config(xce_timewindow_config_t* w) +{ + int i; + + if (w == NULL) { + return; + } + + if (w->segs != NULL) { + for (i = 0; i < w->nsegs; i++) { + xce_timewindow_seg_config_t* seg = w->segs[i]; + + kill_timewindow_seg_config(seg); + } + + FREEUP(w->segs); + } + + FREEUP(w); +} + +void free_timewindow_config(xce_timewindow_config_t* w) +{ + kill_timewindow_config(w); +} + +static xce_timewindow_seg_config_t* dup_timewindow_seg_config(xce_timewindow_seg_config_t* src) +{ + xce_timewindow_seg_config_t* seg = NULL; + + if (src == NULL) { + errno = EINVAL; + + return NULL; + } + + seg = (xce_timewindow_seg_config_t*)calloc(1, sizeof(*seg)); + if (seg == NULL) { + errno = ENOMEM; + return NULL; + } + + seg->tz = strdup(src->tz); + if (seg->tz == NULL) { + kill_timewindow_seg_config(seg); + errno = ENOMEM; + return NULL; + } + + seg->open = (xce_timewindow_time_t*)calloc(1, sizeof(xce_timewindow_time_t)); + seg->close = (xce_timewindow_time_t*)calloc(1, sizeof(xce_timewindow_time_t)); + if ((seg->open == NULL) || (seg->close == NULL)) { + kill_timewindow_seg_config(seg); + errno = ENOMEM; + + return NULL; + } + + memcpy(seg->open, src->open, sizeof(xce_timewindow_time_t)); + memcpy(seg->close, src->close, sizeof(xce_timewindow_time_t)); + + return seg; +} + +xce_timewindow_config_t* dup_timewindow_config(xce_timewindow_config_t* src) +{ + xce_timewindow_config_t* w; + int i; + + if (src == NULL) { + errno = EINVAL; + return NULL; + } + + w = (xce_timewindow_config_t*)calloc(1, sizeof(*w)); + if (w == NULL) { + errno = ENOMEM; + return NULL; + } + + w->segs = (xce_timewindow_seg_config_t**)calloc(src->nsegs, + sizeof(xce_timewindow_seg_config_t*)); + if (w->segs == NULL) { + kill_timewindow_config(w); + errno = ENOMEM; + + return NULL; + } + + for (i = 0; i < src->nsegs; i++) { + w->segs[i] = dup_timewindow_seg_config(src->segs[i]); + if (w->segs[i] == NULL) { + kill_timewindow_config(w); + return NULL; + } + } + + w->nsegs = src->nsegs; + + return w; +} diff --git a/src/lib/xceapi.c b/src/lib/xceapi.c new file mode 100644 index 00000000..70c0f804 --- /dev/null +++ b/src/lib/xceapi.c @@ -0,0 +1,667 @@ +#include + +#include "utils.h" +#include "xceapi.h" + +int xce_hello(xce_ctx_t* ctx, + char* msg) +{ + ioctx_t* ioctx; + int rc, status; + + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + rc = xce_hello_req(ioctx, msg); + if (rc < 0) { + return rc; + } + rc = cbuf_get(&(ctx->wbuf), &status); + if (rc < 0) { + return rc; + } + + return status; +} + +int xce_shutdown(xce_ctx_t* ctx) +{ + ioctx_t* ioctx; + int rc; + int status; + + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + rc = xce_shutdown_req(ioctx); + if (rc < 0) { + return rc; + } + + rc = cbuf_get(&(ctx->wbuf), &status); + if (rc < 0) { + return rc; + } + + return status; +} + +int xce_get(xce_ctx_t* ctx, + int table, + void*** data) +{ + ioctx_t* ioctx; + int rc; + int status; + xce_match_t condition = { + .type = MatchCondition_condition_matchall + }; + xce_get_t get = { + .table = table, + .condition = &condition + }; + dataset_t getreply = { + .table = table, + .nrows = 0, + .rows = NULL + }; + + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + ctx->reply.u.get = &getreply; + rc = xce_get_req(ioctx, &get); + if (rc < 0) { + return rc; + } + + rc = cbuf_get(&(ctx->wbuf), &status); + if (rc < 0) { + return rc; + } + + if (status >= 0) { + *data = getreply.rows; + rc = getreply.nrows; + } else { + rc = status; + } + + ctx->reply.u.get = NULL; + + return rc; +} + +int xce_reslist(xce_ctx_t* ctx, + xce_resource_t*** res) +{ + int table = Data_data_resources; + + return xce_get(ctx, table, (void***)res); +} + +int xce_resval(xce_ctx_t* ctx, + char* host, + char* res, + xce_resval_t*** vals) +{ + ioctx_t* ioctx; + int rc; + int status; + /* clang-format off */ + xce_reskey_t reskey = { + .resname = res, + .hostname = host + }; + xce_match_t condition = { + .type = MatchCondition_condition_matchreskey, + .condition = { + .reskey = &reskey + } + }; + xce_get_t get = { + .table = Data_data_resvals, + .condition = &condition + }; + dataset_t getreply = { + .table = Data_data_resvals, + .nrows = 0, + .rows = NULL + }; + /* clang-format on */ + + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + ctx->reply.u.get = &getreply; + rc = xce_get_req(ioctx, &get); + if (rc < 0) { + return rc; + } + + rc = cbuf_get(&(ctx->wbuf), &status); + if (rc < 0) { + return rc; + } + + if (status >= 0) { + *vals = (xce_resval_t**)getreply.rows; + rc = getreply.nrows; + } else { + rc = status; + } + + ctx->reply.u.get = NULL; + + return rc; +} + +int xce_join(xce_ctx_t* ctx, + int role, + hostattrs_t* attrs) +{ + ioctx_t* ioctx; + int rc, status; + + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + rc = xce_join_req(ioctx, role, attrs); + if (rc < 0) { + return rc; + } + rc = cbuf_get(&(ctx->wbuf), &status); + if (rc < 0) { + return rc; + } + + return status; +} + +int xce_workerlist(xce_ctx_t* ctx, + xce_worker_t*** workers) +{ + int table = Data_data_workers; + + return xce_get(ctx, table, (void***)workers); +} + +int xce_free_workers(int nworkers, + xce_worker_t* workers) +{ + return 0; +} + +int xce_jobdispatch(xce_ctx_t* ctx, + xce_job_dispatch_t* info) +{ + ioctx_t* ioctx; + int rc, status; + + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + rc = xce_jobdispatch_req(ioctx, info); + if (rc < 0) { + return rc; + } + + rc = cbuf_get(&(ctx->wbuf), &status); + if (rc < 0) { + return rc; + } + + return status; +} + +int xce_notify(xce_ctx_t* ctx, + xce_notify_data_t* data) +{ + ioctx_t* ioctx; + int rc; + + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + rc = xce_notify_req(ioctx, data); + + return rc; +} + +int xce_jobsubmit(xce_ctx_t* ctx, + xce_job_submit_t* submit, + uint64_t* jobid) +{ + ioctx_t* ioctx; + int rc, status; + + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + rc = xce_jobsubmit_req(ioctx, submit); + if (rc < 0) { + return rc; + } + + rc = cbuf_get(&(ctx->wbuf), &status); + if (rc < 0) { + return rc; + } + + if (status >= 0) { + *jobid = ctx->reply.u.jobid; + } + return status; +} + +int xce_joblist_ex(xce_ctx_t* ctx, + int sched, + xce_job_t*** jobs) +{ + int table; + + if (sched) { + table = Data_data_schedjobs; + } else { + table = Data_data_jobs; + } + + return xce_get(ctx, table, (void***)jobs); +} + +int xce_sched_joblist(xce_ctx_t* ctx, + xce_job_t*** jobs) +{ + return xce_joblist_ex(ctx, 1, jobs); +} + +int xce_joblist(xce_ctx_t* ctx, + xce_job_t*** jobs) +{ + return xce_joblist_ex(ctx, 0, jobs); +} + +int xce_varlist(xce_ctx_t* ctx, + xce_config_t*** vars) +{ +#if 0 + int table = XCETables_conf; + + return xce_get(ctx, table, (void***)vars); +#endif + return 0; +} + +int xce_queuelist(xce_ctx_t* ctx, + xce_queue_t*** queues) +{ +#if 0 + int table = XCETables_queues; + + return xce_get(ctx, table, (void***)queues); +#else + return 0; +#endif +} + +int xce_free_queues(int nqueues, + xce_queue_t* queues) +{ + int i; + + if (queues == NULL) { + return -EINVAL; + } + + for (i = 0; i < nqueues; i++) { + FREEUP(queues[i].resreq); + } + return 0; +} + +int xce_grouplist(xce_ctx_t* ctx, + int group_type, + xce_group_t*** groups) +{ +#if 0 + int table; + + switch (group_type) { + case 0: + table = XCETables_ugroups; + break; + default: + table = XCETables_hgroups; + break; + } + + return xce_get(ctx, table, (void***)groups); +#else + return 0; +#endif +} + +int xce_free_groups(int ngroups, + xce_group_t* groups) +{ + /* TODO */ + return 0; +} + +int xce_clusterconf(xce_ctx_t* ctx, + xce_clusterconf_t** conf) +{ + ioctx_t* ioctx; + int rc, status; + + if ((ctx == NULL) || (conf == NULL)) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + rc = xce_clusterconf_req(ioctx); + if (rc < 0) { + return rc; + } + + rc = cbuf_get(&(ctx->wbuf), &status); + if (rc < 0) { + return rc; + } + + if (status < 0) { + return status; + } + + MOVE_PTR((*conf), ctx->reply.u.clusterconf); + return 0; +} + +int xce_update_resvals(xce_ctx_t* ctx, + int count, + xce_resval_t** vals) +{ + ioctx_t* ioctx; + int rc; + int status; + + /* clang-format off */ + xce_resval_list_t valist = { + .count = count, + .vals = vals + }; + xce_update_data_t data = { + .table = Update_data_resvals, + .data = { + .resvals = &valist + } + }; + /* clang-format on */ + + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + rc = xce_update_req(ioctx, &data); + if (rc < 0) { + return rc; + } + + rc = cbuf_get(&(ctx->wbuf), &status); + if (rc < 0) { + return rc; + } + + return status; +} + +int xce_update_jusage(xce_ctx_t* ctx, + uint64_t jobid, + int npids, + int* pids, + int ngids, + int* pgids, + int nusage, + xce_rusage_t** usages) +{ + ioctx_t* ioctx; + int rc; + int status; + + /* clang-format off */ + xce_job_rusages_t rusages = { + .jobid = jobid, + .npids = npids, + .pids = pids, + .pgids = pgids, + .count = nusage, + .usages = usages + }; + xce_update_data_t data = { + .table = Update_data_jobrusages, + .data = { + .jobrusages = &rusages } + }; + /* clang-format on */ + + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + rc = xce_update_req(ioctx, &data); + if (rc < 0) { + return rc; + } + + rc = cbuf_get(&(ctx->wbuf), &status); + if (rc < 0) { + return rc; + } + + return status; +} + +int xce_jobctrl(xce_ctx_t* ctx, + xce_jobctrl_t* ctrl) +{ + ioctx_t* ioctx; + int rc; + int status; + + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + rc = xce_jobctrl_req(ioctx, ctrl); + if (rc < 0) { + return rc; + } + + rc = cbuf_get(&(ctx->wbuf), &status); + if (rc < 0) { + return rc; + } + + return status; +} + +int xce_queuectrl(xce_ctx_t* ctx, + xce_queuectrl_t* ctrl) +{ + ioctx_t* ioctx; + int rc; + int status; + + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + rc = xce_queuectrl_req(ioctx, ctrl); + if (rc < 0) { + return rc; + } + + rc = cbuf_get(&(ctx->wbuf), &status); + if (rc < 0) { + return rc; + } + + return status; +} + +int xce_runtask(xce_ctx_t* ctx, + xce_taskrun_t* runinfo) +{ + ioctx_t* ioctx; + int rc; + int status; + + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->state != XCE_CTX_RUN) { + return -EINVAL; + } + + ioctx = ioctx_alloc(ctx->ep, &(ctx->myinfo)); + if (ioctx == NULL) { + return -ENOMEM; + } + + rc = xce_runtask_req(ioctx, runinfo); + if (rc < 0) { + return rc; + } + + rc = cbuf_get(&(ctx->wbuf), &status); + if (rc < 0) { + return rc; + } + + return status; +} diff --git a/src/lib/xcectx.c b/src/lib/xcectx.c new file mode 100644 index 00000000..e209f510 --- /dev/null +++ b/src/lib/xcectx.c @@ -0,0 +1,371 @@ +#include +#include +#include + +#include "dataq.h" +#include "mylock.h" +#include "netio.h" +#include "typemap.h" +#include "utils.h" +#include "xcectx.h" + +static int handle_get_reply(xce_ctx_t* ctx, + xce_reply_t* reply) +{ + xce_data_t* getdata = reply->data.getdata; + dataset_t* dataset = ctx->reply.u.get; + + return extract_data(dataset, getdata); +} + +static int handle_sub_reply(xce_ctx_t* ctx, + xce_reply_t* reply) +{ + if (reply->data_which != RequestReply_data_jobid) { + return -1; + } + + ctx->reply.u.jobid = reply->data.jobid; + return 1; +} + +static int handle_reply(xce_ctx_t* ctx, + xce_reply_t* reply) +{ + int rc = 0; + + if (reply->status < 0) { + return reply->status; + } + + switch (reply->opcode) { + case OPCode_get: + rc = handle_get_reply(ctx, reply); + break; + case OPCode_jobsub: + rc = handle_sub_reply(ctx, reply); + break; + case OPCode_clusterconf: + rc = -1; + if (reply->data_which == RequestReply_data_clusterconf) { + MOVE_PTR(ctx->reply.u.clusterconf, + reply->data.clusterconf); + rc = 1; + } + break; + default: + rc = -ENOENT; + break; + } + + return rc; +} + +static int vtask_entry(vtask_t* task) +{ + endpoint_t* ep = task->ctx.ep; + xce_ctx_t* ctx = NULL; + int rc = 0; + xce_request_t request; + + if (ep == NULL) { + return -EINVAL; + } + + ctx = (xce_ctx_t*)ep->owner; + if (ctx == NULL) { + return -EINVAL; + } + + rc = ioctx_decode(&(task->ctx), &request); + if (rc < 0) { + return rc; + } + + if (request.opcode == OPCode_reply) { + int need_wake = 1; + int status = request.body.replymsg->status; + + need_wake = handle_reply(ctx, request.body.replymsg); + if (need_wake) { + rc = xce_wakeup(ctx, (int)status); + } + } else { + int callnext = 1; + + if ((request.opcode == OPCode_push) && (request.body_which == Request_body_pushmsg)) { + + if (ctx->dataset == NULL) { + ctx->dataset = (dataset_t*)calloc(1, sizeof(dataset_t)); + ctx->dataset->table = request.body.pushmsg->table; + } + + callnext = extract_data(ctx->dataset, + request.body.pushmsg); + if (callnext) { + FREEUP(request.body.pushmsg); + request.body_which = Request_body_datamsg; + MOVE_PTR(request.body.datamsg, ctx->dataset); + } + } + + if (callnext) { + rc = (ctx->handler)(&request); + } + } + + free_Request(&request); + + return 0; +} +static int handle_input(endpoint_t* ep) +{ + xce_ctx_t* ctx = (xce_ctx_t*)ep->owner; + vtask_t* task; + int rc = 0; + + task = vtask_alloc(); + if (task == NULL) { + return -ENOMEM; + } + + rc = vtask_init(task, (vtask_func_t)&vtask_entry, ep); + if (rc < 0) { + SET_ERROR(-rc); + + if (rc == -EPIPE) { + /* connection broken */ + TRACE("broken pipe, ep %p", ep); + } + + FREEUP(task); + return rc; + } + + rc = vtask_enq(&(ctx->vtaskmgr), task); + if (rc < 0) { + return rc; + } + + return 0; +} + +static int handle_output(endpoint_t* ep) +{ + data_item_t* it; + ioctx_t* ctx; + int rc; + + it = endpoint_deq(ep); + if (it == NULL) { + return 0; + } + + ctx = ITPTR_TO_IOCTX(it); + + rc = ioctx_flush(ctx, ep->fd); + ioctx_deref(ctx, 1); + + return rc; +} + +static int handle_io(struct epoll_event* p) +{ + endpoint_t* ep = (endpoint_t*)p->data.ptr; + int rc = 0; + + if ((p->events & EPOLLIN) != 0) { + rc = handle_input(ep); + } + + if (rc >= 0) { + if ((p->events & EPOLLOUT) != 0) { + rc = handle_output(ep); + } + } + + if (rc < 0) { + xce_ctx_t* ctx = (xce_ctx_t*)ep->owner; + iomgr_t* iomgr = &(ctx->iomgr); + iomgr_unmonitor(iomgr, ep); + endpoint_deref(ep); + + xce_try_wakeup(ctx, -EIO); + + ctx->state = XCE_CTX_DOWN; + + return rc; + } + + return 0; +} + +int xce_ctx_init(xce_ctx_t* ctx, + char* name, + char* key) +{ + int rc; + + if ((ctx == NULL) || (name == NULL) || (key == NULL)) { + return -EINVAL; + } + + memset(ctx, 0x0, sizeof(*ctx)); + ctx->state = XCE_CTX_ERR; + ctx->myinfo.name = strdup(name); + ctx->myinfo.key = strdup(key); + + if ((ctx->myinfo.name == NULL) || (ctx->myinfo.key == NULL)) { + FREEUP(ctx->myinfo.name); + FREEUP(ctx->myinfo.key); + return -ENOMEM; + } + + rc = cbuf_init(&(ctx->wbuf), 1, sizeof(int)); + if (rc < 0) { + FREEUP(ctx->myinfo.name); + FREEUP(ctx->myinfo.key); + return rc; + } + + iomgr_init(&(ctx->iomgr)); + vtaskmgr_init(&(ctx->vtaskmgr), 4); + + ctx->ep = NULL; + ctx->state = XCE_CTX_INIT; + return 0; +} + +void xce_ctx_fini(xce_ctx_t* ctx) +{ + if (ctx == NULL) { + return; + } + + xce_ctx_stop(ctx); + + vtaskmgr_fini(&(ctx->vtaskmgr)); + iomgr_fini(&(ctx->iomgr)); + cbuf_fini(&(ctx->wbuf)); + + FREEUP(ctx->myinfo.name); + FREEUP(ctx->myinfo.key); + + return; +} + +int xce_ctx_set_handler(xce_ctx_t* ctx, + xce_request_handler_t handler) +{ + if ((ctx == NULL) || (handler == NULL)) { + return -EINVAL; + } + + ctx->handler = handler; + return 0; +} + +int xce_ctx_set_endpoint(xce_ctx_t* ctx, + endpoint_t* ep) +{ + if ((ctx == NULL) || (ep == NULL)) { + return -EINVAL; + } + + ctx->ep = ep; + return 0; +} + +int xce_ctx_start(xce_ctx_t* ctx) +{ + int rc; + + if (ctx == NULL) { + return -EINVAL; + } + + if ((ctx->state != XCE_CTX_INIT) || (ctx->ep == NULL)) { + return -EINVAL; + } + + endpoint_set_handler(ctx->ep, + handle_io, ctx); + rc = iomgr_monitor(&(ctx->iomgr), + ctx->ep); + if (rc < 0) { + ctx->state = XCE_CTX_ERR; + return rc; + } + + iomgr_start(&(ctx->iomgr)); + vtaskmgr_start(&(ctx->vtaskmgr)); + + ctx->state = XCE_CTX_RUN; + + return 0; +} + +int xce_ctx_stop(xce_ctx_t* ctx) +{ + if (ctx == NULL) { + return -EINVAL; + } + + if (ctx->ep != NULL) { + iomgr_unmonitor(&(ctx->iomgr), + ctx->ep); + ctx->ep = NULL; + } + iomgr_stop(&(ctx->iomgr)); + + ctx->state = XCE_CTX_DOWN; + + return 0; +} + +int xce_wakeup(xce_ctx_t* ctx, + int status) +{ + int rc = 0; + + if (ctx == NULL) { + return -EINVAL; + } + + rc = cbuf_tryput(&(ctx->wbuf), &status); + if (rc == -EAGAIN) { + /* pending data in wbuf, this is normal */ + rc = 0; + } + + return rc; +} + +int xce_try_wakeup(xce_ctx_t* ctx, + int status) +{ + if (ctx == NULL) { + return -EINVAL; + } + + return cbuf_tryput(&(ctx->wbuf), &status); +} + +void xce_block_tasks(xce_ctx_t* ctx) +{ + if (ctx == NULL) { + return; + } + + endpoint_block_tasks(ctx->ep); +} + +void xce_unblock_tasks(xce_ctx_t* ctx) +{ + if (ctx == NULL) { + return; + } + + endpoint_unblock_tasks(ctx->ep); + vtaskmgr_wakeup(&(ctx->vtaskmgr)); +} diff --git a/src/lib/xlist.c b/src/lib/xlist.c new file mode 100644 index 00000000..0a60b72c --- /dev/null +++ b/src/lib/xlist.c @@ -0,0 +1,99 @@ +#include +#include + +#include "utils.h" +#include "xlist.h" + +int xlist_init(xlist_t* l, + int delta) +{ + if ((l == NULL) || (delta <= 0)) { + return -EINVAL; + } + + l->delta = delta; + l->data = NULL; + l->count = 0; + l->caps = 0; + + return 0; +} + +static int xlist_ensure(xlist_t* l) +{ + void* p; + int nc, i; + + if (l->count < l->caps) { + return 1; + } + + nc = l->caps + l->delta; + p = (void*)realloc(l->data, nc * sizeof(void*)); + if (p == NULL) { + return -ENOMEM; + } + + l->data = p; + for(i = l->caps; i < nc; i ++) { + l->data[i] = NULL; + } + + l->caps = nc; + + return 1; +} + +int xlist_store(xlist_t* l, + void* data) +{ + int rc; + + if (l == NULL) { + return -EINVAL; + } + + rc = xlist_ensure(l); + if (rc < 0) { + return rc; + } + + l->data[l->count] = data; + l->count++; + + return 1; +} + +void xlist_clear(xlist_t *l) { + if (l == NULL) { + return; + } + + l->count = 0; +} + +int xlist_iter(xlist_t *l, + xlist_iter_fn_t fn, + void *data) { + int i; + + if ((l == NULL) || (fn == NULL)) { + return -EINVAL; + } + + for(i = 0; i < l->count; i ++) { + (*fn)((void *)l->data[i], data); + } + + return 0; +} + +void xlist_fini(xlist_t* l) +{ + if (l == NULL) { + return; + } + + FREEUP(l->data); + return; +} diff --git a/src/lib/xstring.c b/src/lib/xstring.c new file mode 100644 index 00000000..224175aa --- /dev/null +++ b/src/lib/xstring.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include + +#include "htab.h" +#include "utils.h" +#include "xstring.h" + +static void* xstring_create(objmgr_t*, objtype_t*, va_list); +static void xstring_fini(void*); +static void xstring_type_fini(objtype_t*); + +static xstring_typedata_t xstring_typedata; + +static objtype_t xstring = { + .type = "xstring", + .fn_create = (obj_create_fn_t)xstring_create, + .fn_fini = xstring_fini, + .fn_type_fini = (objtype_fini_fn_t)xstring_type_fini, + .typedata = &xstring_typedata +}; + +static void xstring_obj_killer(myobj_t* obj) +{ + if (obj == NULL) { + return; + } + + memset(obj, 0x0, sizeof(*obj)); + free(obj); +} + +int register_xstring(objmgr_t* mgr, + int nslots, + int delta) +{ + ht_init(&(xstring_typedata.tab), nslots, + string_hash_key); + zarray_init(&(xstring_typedata.strings), delta, + (zarray_item_killer_t)xstring_obj_killer); + + return objmgr_register(mgr, &xstring); +} + +static void* xstring_create(objmgr_t* mgr, + objtype_t* type, + va_list ap) +{ + char* s = va_arg(ap, char*); + char* p = NULL; + myobj_t* obj = NULL; + hent_t* e = NULL; + xstring_typedata_t* typedata = NULL; + int32_t idx; + + if (s == NULL) { + SET_ERROR(EINVAL); + return NULL; + } + + typedata = (xstring_typedata_t*)type->typedata; + + e = ht_get((htab_t*)&(typedata->tab), (void*)s); + if (e != NULL) { + idx = e->data; + obj = (myobj_t*)zarray_get(&(typedata->strings), idx); + + if (obj != NULL) { + p = MYOBJ_TO_OBJ(char*, obj); + return obj_ref(p, OBJREF_NOP); + } + + SET_ERROR(EINVAL); + return NULL; + } + + obj = (myobj_t*)calloc(1, sizeof(*obj) + strlen(s) + 1); + if (obj == NULL) { + return NULL; + } + + idx = zarray_store(&(typedata->strings), obj); + if (idx < 0) { + free(obj); + SET_ERROR(-idx); + return NULL; + } + + obj_init(mgr, type, idx, obj); + + p = MYOBJ_TO_OBJ(char*, obj); + + strcpy(p, s); + + e = ht_add((htab_t*)&(typedata->tab), (void*)s); + if (e == NULL) { + obj_deref(p); + return NULL; + } + + e->data = idx; + + return p; +} + +/* this will ONLY be called by obj_deref() */ +static void xstring_fini(void* s) +{ + myobj_t* myobj; + objtype_t* typeval; + xstring_typedata_t* typedata; + int32_t idx; + + if (s == NULL) { + return; + } + + myobj = TO_MYOBJ(s); + typeval = myobj->type; + typedata = (xstring_typedata_t*)typeval->typedata; + + if (typedata == NULL) { + return; + } + + ht_del(&(typedata->tab), (void*)s); + + idx = (int32_t)myobj->exdata; + if (idx >= 0) { + zarray_del(&(typedata->strings), idx); + } + + return; +} + +static void xstring_type_fini(objtype_t* typeval) +{ + xstring_typedata_t* typedata = (xstring_typedata_t*)typeval->typedata; + + if (typedata == NULL) { + return; + } + + ht_fini(&(typedata->tab)); + zarray_fini(&(typedata->strings)); +} diff --git a/src/lib/zarray.c b/src/lib/zarray.c new file mode 100644 index 00000000..6d3758ea --- /dev/null +++ b/src/lib/zarray.c @@ -0,0 +1,277 @@ +#include +#include +#include + +#include "utils.h" +#include "zarray.h" + +int zarray_init(zarray_t* array, + int delta, + zarray_item_killer_t killer) +{ + if ((array == NULL) || (delta <= 0)) { + return -EINVAL; + } + + mylock_init(&(array->lock)); + + array->delta = delta; + array->data = NULL; + array->killer = killer; + array->count = 0; + array->caps = 0; + array->pos = 0; + return 0; +} + +static int zarray_ensure_items(zarray_t* array, + int mincap) +{ + int nc, i; + void* p; + + if (mincap < array->caps) { + return 1; + } + + nc = mincap; + if (nc < array->caps + array->delta) { + nc = array->caps + array->delta; + } + + p = (void*)realloc(array->data, nc * sizeof(void*)); + if (p == NULL) { + return -ENOMEM; + } + + array->data = p; + for (i = array->caps; i < nc; i++) { + array->data[i] = NULL; + } + + /* this will make we can get next free + * location quickly + */ + array->pos = array->caps; + array->caps = nc; + + return 1; +} + +int zarray_store(zarray_t* array, + void* data) +{ + int rc, i; + + if (array == NULL) { + return -EINVAL; + } + + mylock_lock(&(array->lock)); + rc = zarray_ensure_items(array, array->count + 1); + + if (rc >= 0) { + int idx; + + rc = -ENOMEM; + idx = array->pos; + + for (i = 0; i < array->caps; i++) { + if (array->data[idx] == NULL) { + array->data[idx] = data; + array->count++; + rc = idx; + break; + } + + idx++; + if (idx >= array->caps) { + idx = 0; + } + } + if (rc >= 0) { + array->pos = (rc + 1) % array->caps; + } + } + + mylock_unlock(&(array->lock)); + + return rc; +} + +int zarray_clear(zarray_t* array, + int idx) +{ + if (array == NULL) { + return -EINVAL; + } + + if ((idx < 0) || (idx >= array->caps)) { + return -EINVAL; + } + + mylock_lock(&(array->lock)); + array->data[idx] = NULL; + mylock_unlock(&(array->lock)); + + return 0; +} + +void zarray_fini(zarray_t* array) +{ + if (array == NULL) { + return; + } + + if (array->data != NULL) { + int i; + + if (array->killer != NULL) { + for (i = 0; i < array->caps; i++) { + if (array->data[i] != NULL) { + void* ptr = array->data[i]; + array->data[i] = NULL; + (array->killer)(ptr); + } + } + } + + free(array->data); + array->data = NULL; + } +} + +int zarray_iter_ex(zarray_t* array, + xlist_t* l, + void* arg) +{ + int i, j; + + if ((array == NULL) || (l == NULL)) { + return -EINVAL; + } + + mylock_lock(&(array->lock)); + + for (j = 0; j < l->count; j++) { + zarray_iter_fn_t f = (zarray_iter_fn_t)l->data[j]; + + if (f == NULL) { + continue; + } + + for (i = 0; i < array->caps; i++) { + (*f)(arg, array->data[i]); + } + } + mylock_unlock(&(array->lock)); + + return 0; +} + +int zarray_iter(zarray_t* array, + zarray_iter_fn_t f, + void* arg) +{ + int rc; + xlist_t l; + + if ((array == NULL) || (f == NULL)) { + return -EINVAL; + } + + xlist_init(&l, 2); + xlist_store(&l, f); + + rc = zarray_iter_ex(array, &l, arg); + + xlist_fini(&l); + return rc; +} + +int zarray_del(zarray_t* array, + int idx) +{ + void* ptr = NULL; + + if (array == NULL) { + return -EINVAL; + } + + if ((idx < 0) && (idx >= array->caps)) { + return -EINVAL; + } + + mylock_lock(&(array->lock)); + ptr = array->data[idx]; + array->data[idx] = NULL; + if (ptr != NULL) { + array->count--; + } + + /* idx will be a usable position */ + array->pos = idx; + mylock_unlock(&(array->lock)); + + if (array->killer != NULL) { + if (ptr != NULL) { + (array->killer)(ptr); + } + } + + return 0; +} + +int zarray_put(zarray_t* array, + int idx, + void* data) +{ + int rc = 0; + + /* clang-format off */ + if ((array == NULL) || + (idx < 0) || + (data == NULL)) { + return -EINVAL; + } + /* clang-format on */ + + mylock_lock(&(array->lock)); + rc = zarray_ensure_items(array, idx + 1); + if (rc >= 0) { + void* ptr = array->data[idx]; + array->data[idx] = data; + rc = 0; + if (ptr != NULL) { + if (array->killer != NULL) { + array->killer(ptr); + } + } else { + array->count++; + } + } + mylock_unlock(&(array->lock)); + + return rc; +} + +void* zarray_get(zarray_t* array, + int idx) +{ + void* ptr = NULL; + + /* clang-format off */ + if ((array == NULL) || + (idx < 0) || + (idx >= array->caps)) { + SET_ERROR(EINVAL); + return NULL; + } + /* clang-format on */ + + mylock_lock(&(array->lock)); + ptr = array->data[idx]; + mylock_unlock(&(array->lock)); + + return ptr; +} diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 00000000..bfebe346 --- /dev/null +++ b/src/meson.build @@ -0,0 +1,28 @@ +project('xce', + ['c'], + version: '0.0.1', + meson_version: '>=1.5', + default_options: [ + 'c_std=gnu17', + 'c_args=-DDEBUG -O1']) + +with_debug=false + +if get_option('with_debug') + # add -DWITH_DEBUG=1 + add_project_arguments('-DWITH_DEBUG=1', language: 'c') + with_debug=true +endif + +if get_option('without_db') + add_project_arguments('-DWITHOUT_DB=1', language: 'c') +endif + +add_project_arguments('-DVERSION_COMMIT_ID='+get_option('commit_id'), language: 'c') + +include_dir = include_directories('include', 'include/xce') + +subdir('lib') +# subdir('controller') +# subdir('worker') +# subdir('scheduler') diff --git a/src/meson.options b/src/meson.options new file mode 100644 index 00000000..12dd6735 --- /dev/null +++ b/src/meson.options @@ -0,0 +1,3 @@ +option('with_debug', type: 'boolean', value: false, yield: true) +option('without_db', type: 'boolean', value: false, yield: true) +option('commit_id', type: 'string', value:'', yield: true) diff --git a/src/schema/c.capnp b/src/schema/c.capnp new file mode 100644 index 00000000..7dcc53b5 --- /dev/null +++ b/src/schema/c.capnp @@ -0,0 +1,69 @@ +# Copyright (c) 2016 NetDEF, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +@0xc0183dd65ffef0f3; + +annotation nameinfix @0x85a8d86d736ba637 (file): Text; +# add an infix (middle insert) for output file names +# +# "make" generally has implicit rules for compiling "foo.c" => "foo". This +# is very annoying with capnp since the rule will be "foo" => "foo.c", leading +# to a loop. $nameinfix (recommended parameter: "-gen") inserts its parameter +# before the ".c", so the filename becomes "foo-gen.c" +# +# Alternatively, add this Makefile rule to disable compiling "foo.capnp.c" -> "foo.capnp": +# %.capnp: ; +# +# +# ("foo" is really "foo.capnp", so it's foo.capnp-gen.c) + +annotation fieldgetset @0xf72bc690355d66de (file): Void; +# generate getter & setter functions for accessing fields +# +# allows grabbing/putting values without de-/encoding the entire struct. + +annotation donotinclude @0x8c99797357b357e9 (file): UInt64; +# do not generate an include directive for an import statement for the file with +# the given ID + +annotation typedefto @0xcefaf27713042144 (struct, enum): Text; +# generate a typedef for the annotated struct or enum declaration + +annotation namespace @0xf2c035025fec7c2b (file): Text; +# prefix structs with a name space string + +annotation extraheader @0xbadb496d09cf4612 (file): Text; +# add extra preprocessor directives to the header + +annotation extendedattribute @0xd187bca5c6844c24 (file): Text; +# add an extended attribute to each generated function + +annotation codecgen @0xcccaac86283e2609 (file): Void; +# generate codec(encode/decode) to each type + +annotation mapname @0xb9edf6fc2d8972b8 (*): Text; +# the mapped type name which will be encoded + +annotation maplistcount @0xb6ea49eb8a9b0f9e (field): Text; +# the mapped list count field which will be encoded + +annotation mapuniontag @0xdce06d41858f91ac (union, struct): Text; +# the mapped tag (which) of union diff --git a/src/schema/controller.capnp b/src/schema/controller.capnp new file mode 100644 index 00000000..e0c3a378 --- /dev/null +++ b/src/schema/controller.capnp @@ -0,0 +1,590 @@ +@0xdefcdf6377db2e8e; + +using C = import "/c.capnp"; + +$C.fieldgetset; +$C.codecgen; +$C.extraheader("#include \"clusterconfig.h\""); +$C.extraheader("#include \"typemap.h\""); + +enum OPCode { + nop @0; + reply @1; + hello @2; + join @3; + shutdown @4; + get @5; + push @6; + update @7; + jobdispatch @8; + startjob @9; + notify @10; + jobsub @11; + jobstatus @12; + jobrusage @13; + hostcontrol @14; + jobcontrol @15; + newschedjobs @16; + clusterconf @17; + queuecontrol @18; + runtasks @19; +} + +struct PeerInfo $C.mapname("xce_peerinfo_t") { + host @0: Text $C.mapname("name"); + key @1: Text; +} + +struct StrList $C.mapname("xce_strlist_t") { + data @0: List(Text) $C.mapname("data") $C.maplistcount("count"); +} + +struct TimeWindowTime $C.mapname("xce_timewindow_time_t") { + day @0: UInt32 $C.mapname("day"); + hour @1: UInt32 $C.mapname("hour"); + min @2: UInt32 $C.mapname("min"); +} + +struct TimeWindowSeg $C.mapname("xce_timewindow_seg_config_t") { + timezone @0: Text $C.mapname("tz"); + open @1: TimeWindowTime $C.mapname("open"); + close @2: TimeWindowTime $C.mapname("close"); +} + +struct TimeWindow $C.mapname("xce_timewindow_config_t") { + segs @0: List(TimeWindowSeg) $C.mapname("segs") $C.maplistcount("nsegs"); +} + +struct Group $C.mapname("xce_group_t") { + name @0: Text $C.mapname("name"); + members @1: List(Text) $C.mapname("members.data") $C.maplistcount("members.count"); + exmembers @2: List(Text) $C.mapname("ex_members.data") $C.maplistcount("ex_members.count"); +} + +# This data structure will not be transfer in wire +# directly, it will be assembled by multiple Data packet +struct Dataset $C.mapname("dataset_t") { + table @0: UInt32; + nrows @1: UInt32; + rows @2: Void; # do NOT change this, it's place holder +} + +struct ResKey $C.mapname("xce_reskey_t") { + resname @0: Text; + hostname @1: Text; +} + +struct MatchCondition $C.mapname("xce_match_t") { + condition :union $C.mapuniontag("type") { + matchall @0: Void; + matchjid @1: UInt64 $C.mapname("jobid"); + matchwname @2: Text $C.mapname("wname"); + matchreskey @3: ResKey $C.mapname("reskey"); + } +} + +struct HostAttrs $C.mapname("hostattrs_t") { + type @0: Text $C.mapname("hosttype"); + model @1: Text $C.mapname("hostmodel"); + cpufactor @2: Float64; + maxcpus @3: Int32; + maxmem @4: Float64; + maxswap @5: Float64; + maxtmp @6: Float64; + ndisks @7: Int32; +} + +struct Worker $C.mapname("xce_worker_t"){ + name @0: Text; + attrs @1: HostAttrs; + status @2: UInt32; + dispatchWindow @3: TimeWindow $C.mapname("dispatch_window_config"); + thresholds @4: List(Threshold) $C.mapname("thresholds") $C.maplistcount("nthresholds"); + resvals @5: List(ValueWithIdx) $C.mapname("resvals_to_sched") $C.maplistcount("nresvals_to_sched"); +} + +enum HostRole { + client @0; + worker @1; + scheduler @2; + controller @3; +} + +struct JoinData $C.mapname("xce_joindata_t") { + role @0: HostRole; + data :union { + nodata @1: Void; + attrs @2: HostAttrs; + } +} + +struct Value $C.mapname("xce_val_t"){ + u :union $C.mapuniontag("which") { + ivalue32 @0: Int32; + uvalue32 @1: UInt32; + ivalue64 @2: Int64; + uvalue64 @3: UInt64; + svalue @4: Text; + fvalue @5: Float64; + bvalue @6: Bool; + } +} + +struct ValueWithIdx $C.mapname("xce_val_with_idx_t") { + idx @0: UInt32; + val @1: Value $C.mapname("val"); +} + +struct ConfigVar $C.mapname("xce_config_t") { + name @0: Text; + value @1: Text; +} + +struct ResourceDistribution $C.mapname("res_distribution_t") { + value @0: Value; + hosts @1: List(Text) $C.maplistcount("nhosts"); +} + +struct Resource $C.mapname("xce_resource_t"){ + name @0: Text; + desc @1: Text; + idx @2: Int32; + valtype @3: Int32; + ordtype @4: Int32; + flags @5: Int32; + interval @6: Int32; + lastReport @7: UInt64 $C.mapname("last_report"); + distributions @8: List(ResourceDistribution) $C.maplistcount("ndistributions"); + hostBased @9: Value $C.mapname("hbased_defined"); +} + +struct Threshold $C.mapname("xce_res_threshold_t"){ + name @0: Text; + sched @1: Float64; + stop @2: Float64; +} + +struct QueueConf $C.mapname("xce_queue_t") { + name @0: Text $C.mapname("queue"); + attrs @1: UInt32; + status @2: UInt32; + priority @3: Int32; + acceptIntervals @4: Int32 $C.mapname("accept_interval"); + schedDelay @5: Int32 $C.mapname("sched_delay"); + resreq @6: Text; + users @7: Group $C.mapname("users"); + hosts @8: Group $C.mapname("hosts"); + thresholds @9: List(Threshold) $C.maplistcount("nthresholds"); + preExec @10: Text $C.mapname("pre_exec"); + postExec @11: Text $C.mapname("post_exec"); + runWindow @12: TimeWindow $C.mapname("runwindow_config"); + dispatchWindow @13: TimeWindow $C.mapname("dispatchwindow_config"); +} + +struct Conf4Sched $C.mapname("xce_conf4sched_t"){ + clustername @0: Text; + configvars @1: List(ConfigVar) $C.mapname("confvars") $C.maplistcount("n_confvars"); + resources @2: List(Resource) $C.maplistcount("n_resources"); + queues @3: List(QueueConf) $C.maplistcount("n_queues"); + ugroups @4: List(Group) $C.maplistcount("n_ugroups"); + hgroups @5: List(Group) $C.maplistcount("n_hgroups"); + resvals @6: List(ValueWithIdx) $C.mapname("resvals") $C.maplistcount("nresvals"); +} + +struct Conf4Worker $C.mapname("xce_conf4worker_t") { + clustername @0: Text; + configvars @1: List(ConfigVar) $C.mapname("confvars") $C.maplistcount("n_confvars"); +} + +struct ConfigData $C.mapname("xce_configdata_t") { + data :union $C.mapuniontag("data_which") { + schedconfig @0: Conf4Sched $C.mapname("conf4sched"); + workerconfig @1: Conf4Worker $C.mapname("conf4worker"); + } +} + +struct JobPIDInfo $C.mapname("job_pidinfo_t"){ + jobId @0: UInt64 $C.mapname("jobid"); + pids @1: List(UInt32) $C.mapname("pids") $C.maplistcount("npids"); + pgids @2: List(UInt32) $C.mapname("pgids") $C.maplistcount("npgids"); + exdata @3: Text $C.mapname("exdata"); +} + +struct JobFail $C.mapname("job_failinfo_t"){ + jobId @0: UInt64 $C.mapname("jobid"); + code @1: Int32 $C.mapname("code"); + desc @2: Text $C.mapname("detail"); + stage @3: UInt32 $C.mapname("stage"); +} + +struct JobStartInfo $C.mapname("job_startinfo_t"){ + exechome @0: Text; + execcwd @1: Text; + execuser @2: Text; + cmdline @3: Text; + exdata @4: Text; + launchtype @5: Text $C.mapname("launch_type"); + qPreExec @6: Text $C.mapname("q_pre_exec"); + qPostExec @7: Text $C.mapname("q_post_exec"); + preExec @8: Text $C.mapname("job_pre_exec"); + postExec @9: Text $C.mapname("job_post_exec"); +} + +struct Job $C.mapname("xce_job_t"){ + jobid @0: UInt64; + queue @1: Text; + user @2: Text; + idx @3: UInt64; + subtime @4: UInt64 $C.mapname("sub_time"); + queuetime @5: UInt64 $C.mapname("queue_time"); + starttime @6: UInt64 $C.mapname("start_time"); + finishtime @7: UInt64 $C.mapname("finish_time"); + state @8: UInt32; + jobname @9: Text $C.mapname("job_name"); + projectname @10: Text $C.mapname("project_name"); + usergroup @11: Text $C.mapname("user_group"); + desc @12: Text $C.mapname("job_description"); + resreq @13: Text; + allocs @14: JobAlloc $C.mapname("allocs"); + runtime @15: UInt32 $C.mapname("run_time"); + pidinfo @16: JobPIDInfo; + startinfo @17: JobStartInfo $C.mapname("start_info"); + mintasks @18: UInt32 $C.mapname("mintasks"); + maxtasks @19: UInt32 $C.mapname("maxtasks"); +} + +struct SchedJob $C.mapname("xce_job_t"){ + jobid @0: UInt64; + queue @1: Text; + user @2: Text; + idx @3: UInt64; + subtime @4: UInt64 $C.mapname("sub_time"); + queuetime @5: UInt64 $C.mapname("queue_time"); + starttime @6: UInt64 $C.mapname("start_time"); + finishtime @7: UInt64 $C.mapname("finish_time"); + state @8: UInt32; + jobname @9: Text $C.mapname("job_name"); + projectname @10: Text $C.mapname("project_name"); + usergroup @11: Text $C.mapname("user_group"); + resreq @12: Text; + allocs @13: JobAlloc $C.mapname("allocs"); + runtime @14: UInt32 $C.mapname("run_time"); + mintasks @15: UInt32 $C.mapname("mintasks"); + maxtasks @16: UInt32 $C.mapname("maxtasks"); +} + +struct JobData $C.mapname("xce_jobs_data_t") { + ntotal @0: UInt32 $C.mapname("n_total"); + pos @1: UInt32; + jobs @2: List(Job) $C.maplistcount("count"); +} + +struct SchedJobData $C.mapname("xce_jobs_data_t") { + ntotal @0: UInt32 $C.mapname("n_total"); + pos @1: UInt32; + jobs @2: List(SchedJob) $C.maplistcount("count"); +} + +struct WorkerData $C.mapname("xce_workers_data_t"){ + ntotal @0: UInt32 $C.mapname("n_total"); + pos @1: UInt32; + workers @2: List(Worker) $C.maplistcount("count"); +} + +struct ResourceData $C.mapname("xce_resource_data_t") { + ntotal @0: UInt32 $C.mapname("n_total"); + pos @1: UInt32; + resources @2: List(Resource) $C.maplistcount("count"); +} + +struct ResourceVal $C.mapname("xce_resval_t") { + name @0: Text $C.mapname("name"); + host @1: Text $C.mapname("host"); + val @2: Value $C.mapname("val"); +} + +struct ResourceVals $C.mapname("xce_resval_data_t") { + ntotal @0: UInt32 $C.mapname("n_total"); + pos @1: UInt32; + vals @2: List(ResourceVal) $C.mapname("vals") $C.maplistcount("count"); +} + +struct Data $C.mapname("xce_data_t"){ + data :union $C.mapuniontag("table") { + schedjobs @0: SchedJobData $C.mapname("jobs"); + schedworkers @1: WorkerData $C.mapname("workers"); + jobs @2: JobData $C.mapname("jobs"); + workers @3: WorkerData $C.mapname("workers"); + resources @4: ResourceData $C.mapname("resources"); + resvals @5: ResourceVals $C.mapname("resvals"); + } +} + +struct Get $C.mapname("xce_get_t") { + table @0: UInt32; + condition @1: MatchCondition; +} + +struct ResValList $C.mapname("xce_resval_list_t") { + vals @0: List(ResourceVal) $C.mapname("vals") $C.maplistcount("count"); +} + +struct ResUsage $C.mapname("xce_rusage_t") { + name @0: Text $C.mapname("resname"); + value @1: Float64 $C.mapname("value"); +} + +struct JobRusages $C.mapname("xce_job_rusages_t") { + jobid @0: UInt64 $C.mapname("jobid"); + pids @1: List(Int32) $C.mapname("pids") $C.maplistcount("npids"); + pgids @2: List(Int32) $C.mapname("pgids") $C.maplistcount("npgids"); + usages @3: List(ResUsage) $C.mapname("usages") $C.maplistcount("count"); +} + +struct Update $C.mapname("xce_update_data_t") { + data :union $C.mapuniontag("table") { + nodata @0: Void; + resvals @1: ResValList $C.mapname("resvals"); + jobrusages @2: JobRusages $C.mapname("jobrusages"); + } +} + +struct ResAlloc $C.mapname("xce_alloc_t"){ + name @0: Text $C.mapname("resname"); + resvId @1: Text $C.mapname("reserve"); + instid @2: UInt32; + value @3: Float64; + from @4: UInt64; # alloc start time + duration @5: Int64; +} + +struct HostAlloc $C.mapname("xce_host_alloc_t"){ + host @0: Text; + allocs @1: List(ResAlloc) $C.mapname("allocs") $C.maplistcount("nallocs"); +} + +struct JobAlloc $C.mapname("xce_job_alloc_t"){ + jobid @0: UInt64; + allocs @1: List(HostAlloc) $C.mapname("allocs") $C.maplistcount("nhosts"); +} + +struct JobDispatch $C.mapname("xce_job_dispatch_t"){ + allocs @0: List(JobAlloc) $C.maplistcount("njobs"); +} + +struct HostLaunch $C.mapname("xce_host_launch_t") { + host @0: Text $C.mapname("host"); + nranks @1: UInt32 $C.mapname("nranks"); +} + +struct JobLaunch $C.mapname("xce_launch_t") { + hosts @0: List(HostLaunch) $C.mapname("hosts") $C.maplistcount("nhosts"); +} + +struct JobExecInfo $C.mapname("xce_job_exec_t"){ + jobid @0: UInt64; + startinfo @1: JobStartInfo $C.mapname("start_info"); + launchinfo @2: JobLaunch $C.mapname("launchinfo"); +} + +struct JobFinishInfo $C.mapname("xce_jobfinish_t") { + jobid @0: UInt64; + code @1: Int32 $C.mapname("exit_code"); +} + +struct TaskPidInfo $C.mapname("xce_task_pidinfo_t") { + jobid @0: UInt64 $C.mapname("jobid"); + host @1: Text $C.mapname("host"); + taskidx @2: Int32 $C.mapname("taskidx"); + pids @3: List(UInt32) $C.mapname("pids") $C.maplistcount("npids"); + pgids @4: List(UInt32) $C.mapname("pgids") $C.maplistcount("npgids"); + exdata @5: Text $C.mapname("exdata"); + clientidx @6: UInt32 $C.mapname("clientidx"); +} + +struct TaskFailInfo $C.mapname("xce_task_failinfo_t") { + jobid @0: UInt64 $C.mapname("jobid"); + host @1: Text $C.mapname("host"); + taskidx @2: Int32 $C.mapname("taskidx"); + code @3: Int32 $C.mapname("code"); + detail @4: Text $C.mapname("detail"); + clientidx @5: Int32 $C.mapname("clientidx"); +} + +struct TaskFinish $C.mapname("xce_task_finish_t") { + jobid @0: UInt64 $C.mapname("jobid"); + host @1: Text $C.mapname("host"); + taskidx @2: UInt32 $C.mapname("taskidx"); + exitcode @3: Int32 $C.mapname("exit_code"); + clientidx @4: Int32 $C.mapname("clientidx"); +} + +struct NotifyData $C.mapname("xce_notify_data_t"){ + data :union $C.mapuniontag("event") $C.mapname("data"){ + jobPidInfo @0: JobPIDInfo $C.mapname("pidinfo"); + jobFailInfo @1: JobFail $C.mapname("failinfo"); + jobDispatchFail @2: JobFail $C.mapname("dispatchfail"); + jobFinishInfo @3: JobFinishInfo $C.mapname("finishinfo"); + schedStartJob @4: UInt64 $C.mapname("sched_start_job"); + schedExitJob @5: UInt64 $C.mapname("sched_exit_job"); + schedFailJob @6: UInt64 $C.mapname("sched_fail_job"); + schedUpdateJob @7: SchedJob $C.mapname("sched_update_job"); + schedUpdateResvals @8: ResValList $C.mapname("sched_update_resvals"); + stoppedJob @9: UInt64 $C.mapname("stopped_job"); + resumedJob @10: UInt64 $C.mapname("resumed_job"); + ckptinfo @11: CheckpointInfo $C.mapname("ckptinfo"); + schedUpdateQueue @12: QueueConf $C.mapname("sched_update_queue"); + taskPidInfo @13: TaskPidInfo $C.mapname("taskinfo"); + taskFailInfo @14: TaskFailInfo $C.mapname("taskfailinfo"); + taskFinish @15: TaskFinish $C.mapname("taskfinish"); + postDoneJob @16: UInt64 $C.mapname("pdone_job"); + } +} + +struct ClusterConf $C.mapname("xce_clusterconf_t") { + name @0: Text; + resources @1: List(Resource) $C.mapname("reslist.res") $C.maplistcount("reslist.count"); + queues @2: List(QueueConf) $C.mapname("qlist.queues") $C.maplistcount("qlist.count"); + workers @3: List(Worker) $C.mapname("wlist.workers") $C.maplistcount("wlist.count"); +} + +struct JobSubmit $C.mapname("xce_job_submit_t") { + queue @0: Text; + user @1: Text; + cmdline @2: Text; + resreq @3: Text; + exdata @4: Text; + mintasks @5: UInt32; + maxtasks @6: UInt32; +} + +struct JobSignal $C.mapname("xce_signal_t") { + signo @0: UInt32 $C.mapname("signo"); + force @1: Int32 $C.mapname("force"); +} + +struct CheckpointOptions $C.mapname("xce_ckpt_options_t"){ + kill @0: UInt32 $C.mapname("kill"); + method @1: Text $C.mapname("method"); +} + +struct CheckpointInfo $C.mapname("xce_ckptinfo_t") { + jobid @0: UInt64; + ckptinfo @1: Text; +} + +struct JobControl $C.mapname("xce_jobctrl_t") { + jobid @0: UInt64 $C.mapname("jobid"); + u :union $C.mapuniontag("action") $C.mapname("u") { + siginfo @1: JobSignal; + ckptoption @2: CheckpointOptions; + } +} + +struct QueueControl $C.mapname("xce_queuectrl_t") { + action @0: UInt32 $C.mapname("action"); + queue @1: Text $C.mapname("queue"); +} + +struct RequestReply $C.mapname("xce_reply_t"){ + seq @0: UInt64; + opcode @1: OPCode; + status @2: Int32; + + data : union { + nodata @3: Void; + debugmsg @4: Text; + getdata @5: Data; + jobid @6: UInt64; + clusterconf @7: ClusterConf; + } +} + +struct TaskHost $C.mapname("xce_taskhost_t") { + host @0: Text; + ntasks @1: UInt32; + exechome @2: Text; + execcwd @3: Text; + execuser @4: Text; + cmdline @5: Text; + exdata @6: Text; + launchtype @7: Text $C.mapname("launch_type"); +} + +struct RunTask $C.mapname("xce_taskrun_t") { + clientidx @0: Int32 $C.mapname("clientidx"); + hosts @1: List(TaskHost) $C.mapname("taskhosts") $C.maplistcount("nhosts"); + jobid @2: UInt64 $C.mapname("jobid"); +} + +struct Request $C.mapname("xce_request_t"){ + opcode @0: OPCode; + seq @1: UInt64; + from @2: PeerInfo; + body : union { + nomsg @3: Void; + replymsg @4: RequestReply; + hellomsg @5: Text; + joinmsg @6: JoinData; + configpushmsg @7: ConfigData; + pushmsg @8: Data; + getmsg @9: Get; + datamsg @10: Dataset; + dispatchmsg @11: JobDispatch; + jobstartmsg @12: JobExecInfo; + notifymsg @13: NotifyData; + jobsubmsg @14: JobSubmit; + updatemsg @15: Update; + jobctrlmsg @16: JobControl; + queuectrlmsg @17: QueueControl; + runtaskmsg @18: RunTask; + } +} + +struct HashZArrayConfig $C.mapname("hash_zarray_config_t") { + nHashSlots @0: UInt32 $C.mapname("nhash_slots"); + delta @1: UInt32 $C.mapname("delta"); +} + +struct ResmgrConfig $C.mapname("resmgr_config_t") { + nHashSlots @0: UInt32 $C.mapname("nhash_slots"); + delta @1: UInt32 $C.mapname("delta"); + instDelta @2: UInt32 $C.mapname("inst_delta"); +} + +struct MasterCandidate $C.mapname("master_candidate_t") { + name @0: Text $C.mapname("name"); + host @1: Text $C.mapname("host"); + port @2: UInt32 $C.mapname("port"); +} + +struct HostConfig $C.mapname("xce_hostconfig_t") { + name @0: Text $C.mapname("name"); + model @1: Text $C.mapname("hostmodel"); + type @2: Text $C.mapname("hosttype"); + mxj @3: UInt32 $C.mapname("mxj"); + resources @4: List(ConfigVar) $C.mapname("resources") $C.maplistcount("nresources"); + thresholds @5: List(Threshold) $C.mapname("thresholds") $C.maplistcount("nthresholds"); + dispatchwindows @6: TimeWindow $C.mapname("dispatchwindow"); +} + +struct ClusterConfig $C.mapname("cluster_config_t") { + clusterName @0: Text $C.mapname("clustername"); + port @1: UInt32 $C.mapname("port"); + candidates @2: List(MasterCandidate) $C.mapname("candidates") $C.maplistcount("ncandidates"); + heartbeatInterval @3: UInt32 $C.mapname("heartbeat_interval"); + inactiveHeartbeatCount @4: UInt32 $C.mapname("inactive_heartbeat_count"); + fetchJobInterval @5: UInt32 $C.mapname("fetch_job_interval"); + netioTimeout @6: UInt32 $C.mapname("netio_timeout"); + vcpus @7: UInt32 $C.mapname("vcpus"); + resources @8: List(Resource) $C.mapname("resources") $C.maplistcount("nres"); + queues @9: List(QueueConf) $C.mapname("queues") $C.maplistcount("nqueues"); + ugroups @10: List(Group) $C.mapname("ugroups") $C.maplistcount("nugroups"); + hgroups @11: List(Group) $C.mapname("hgroups") $C.maplistcount("nhgroups"); + hostConfigs @12: List(HostConfig) $C.mapname("hconfigs") $C.maplistcount("nhconfigs"); + jobmgr @13: HashZArrayConfig; + workermgr @14: HashZArrayConfig; + qmgr @15: HashZArrayConfig; + resmgr @16: ResmgrConfig; + xstrings @17: HashZArrayConfig; +} diff --git a/src/unity/unity.c b/src/unity/unity.c new file mode 100644 index 00000000..04d716d7 --- /dev/null +++ b/src/unity/unity.c @@ -0,0 +1,2501 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-24 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" + +#ifndef UNITY_PROGMEM +#define UNITY_PROGMEM +#endif + +/* If omitted from header, declare overrideable prototypes here so they're ready for use */ +#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION +void UNITY_OUTPUT_CHAR(int); +#endif + +/* Helpful macros for us to use here in Assert functions */ +#define UNITY_FAIL_AND_BAIL do { Unity.CurrentTestFailed = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define UNITY_IGNORE_AND_BAIL do { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define RETURN_IF_FAIL_OR_IGNORE do { if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) { TEST_ABORT(); } } while (0) + +struct UNITY_STORAGE_T Unity; + +#ifdef UNITY_OUTPUT_COLOR +const char UNITY_PROGMEM UnityStrOk[] = "\033[42mOK\033[0m"; +const char UNITY_PROGMEM UnityStrPass[] = "\033[42mPASS\033[0m"; +const char UNITY_PROGMEM UnityStrFail[] = "\033[41mFAIL\033[0m"; +const char UNITY_PROGMEM UnityStrIgnore[] = "\033[43mIGNORE\033[0m"; +#else +const char UNITY_PROGMEM UnityStrOk[] = "OK"; +const char UNITY_PROGMEM UnityStrPass[] = "PASS"; +const char UNITY_PROGMEM UnityStrFail[] = "FAIL"; +const char UNITY_PROGMEM UnityStrIgnore[] = "IGNORE"; +#endif +static const char UNITY_PROGMEM UnityStrNull[] = "NULL"; +static const char UNITY_PROGMEM UnityStrSpacer[] = ". "; +static const char UNITY_PROGMEM UnityStrExpected[] = " Expected "; +static const char UNITY_PROGMEM UnityStrWas[] = " Was "; +static const char UNITY_PROGMEM UnityStrGt[] = " to be greater than "; +static const char UNITY_PROGMEM UnityStrLt[] = " to be less than "; +static const char UNITY_PROGMEM UnityStrOrEqual[] = "or equal to "; +static const char UNITY_PROGMEM UnityStrNotEqual[] = " to be not equal to "; +static const char UNITY_PROGMEM UnityStrElement[] = " Element "; +static const char UNITY_PROGMEM UnityStrByte[] = " Byte "; +static const char UNITY_PROGMEM UnityStrMemory[] = " Memory Mismatch."; +static const char UNITY_PROGMEM UnityStrDelta[] = " Values Not Within Delta "; +static const char UNITY_PROGMEM UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless."; +static const char UNITY_PROGMEM UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; +static const char UNITY_PROGMEM UnityStrNullPointerForActual[] = " Actual pointer was NULL"; +#ifndef UNITY_EXCLUDE_FLOAT +static const char UNITY_PROGMEM UnityStrNot[] = "Not "; +static const char UNITY_PROGMEM UnityStrInf[] = "Infinity"; +static const char UNITY_PROGMEM UnityStrNegInf[] = "Negative Infinity"; +static const char UNITY_PROGMEM UnityStrNaN[] = "NaN"; +static const char UNITY_PROGMEM UnityStrDet[] = "Determinate"; +static const char UNITY_PROGMEM UnityStrInvalidFloatTrait[] = "Invalid Float Trait"; +#endif +const char UNITY_PROGMEM UnityStrErrShorthand[] = "Unity Shorthand Support Disabled"; +const char UNITY_PROGMEM UnityStrErrFloat[] = "Unity Floating Point Disabled"; +const char UNITY_PROGMEM UnityStrErrDouble[] = "Unity Double Precision Disabled"; +const char UNITY_PROGMEM UnityStrErr64[] = "Unity 64-bit Support Disabled"; +static const char UNITY_PROGMEM UnityStrBreaker[] = "-----------------------"; +static const char UNITY_PROGMEM UnityStrResultsTests[] = " Tests "; +static const char UNITY_PROGMEM UnityStrResultsFailures[] = " Failures "; +static const char UNITY_PROGMEM UnityStrResultsIgnored[] = " Ignored "; +#ifndef UNITY_EXCLUDE_DETAILS +static const char UNITY_PROGMEM UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; +static const char UNITY_PROGMEM UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; +#endif +/*----------------------------------------------- + * Pretty Printers & Test Result Output Handlers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +/* Local helper function to print characters. */ +static void UnityPrintChar(const char* pch) +{ + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } +} + +/*-----------------------------------------------*/ +/* Local helper function to print ANSI escape strings e.g. "\033[42m". */ +#ifdef UNITY_OUTPUT_COLOR +static UNITY_UINT UnityPrintAnsiEscapeString(const char* string) +{ + const char* pch = string; + UNITY_UINT count = 0; + + while (*pch && (*pch != 'm')) + { + UNITY_OUTPUT_CHAR(*pch); + pch++; + count++; + } + UNITY_OUTPUT_CHAR('m'); + count++; + + return count; +} +#endif + +/*-----------------------------------------------*/ +void UnityPrint(const char* string) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch) + { +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + UnityPrintChar(pch); + pch++; + } + } +} +/*-----------------------------------------------*/ +void UnityPrintLen(const char* string, const UNITY_UINT32 length) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch && ((UNITY_UINT32)(pch - string) < length)) + { + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } + pch++; + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style) +{ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (style == UNITY_DISPLAY_STYLE_CHAR) + { + /* printable characters plus CR & LF are printed */ + UNITY_OUTPUT_CHAR('\''); + if ((number <= 126) && (number >= 32)) + { + UNITY_OUTPUT_CHAR((int)number); + } + /* write escaped carriage returns */ + else if (number == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (number == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, 2); + } + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrintNumber(number); + } + } + else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT) + { + UnityPrintNumberUnsigned((UNITY_UINT)number); + } + else + { + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2)); + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumber(const UNITY_INT number_to_print) +{ + UNITY_UINT number = (UNITY_UINT)number_to_print; + + if (number_to_print < 0) + { + /* A negative number, including MIN negative */ + UNITY_OUTPUT_CHAR('-'); + number = (~number) + 1; + } + UnityPrintNumberUnsigned(number); +} + +/*----------------------------------------------- + * basically do an itoa using as little ram as possible */ +void UnityPrintNumberUnsigned(const UNITY_UINT number) +{ + UNITY_UINT divisor = 1; + + /* figure out initial divisor */ + while (number / divisor > 9) + { + divisor *= 10; + } + + /* now mod and print, then divide divisor */ + do + { + UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10))); + divisor /= 10; + } while (divisor > 0); +} + +/*-----------------------------------------------*/ +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print) +{ + int nibble; + char nibbles = nibbles_to_print; + + if ((unsigned)nibbles > UNITY_MAX_NIBBLES) + { + nibbles = UNITY_MAX_NIBBLES; + } + + while (nibbles > 0) + { + nibbles--; + nibble = (int)(number >> (nibbles * 4)) & 0x0F; + if (nibble <= 9) + { + UNITY_OUTPUT_CHAR((char)('0' + nibble)); + } + else + { + UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble)); + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number) +{ + UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1); + UNITY_INT32 i; + + for (i = 0; i < UNITY_INT_WIDTH; i++) + { + if (current_bit & mask) + { + if (current_bit & number) + { + UNITY_OUTPUT_CHAR('1'); + } + else + { + UNITY_OUTPUT_CHAR('0'); + } + } + else + { + UNITY_OUTPUT_CHAR('X'); + } + current_bit = current_bit >> 1; + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +/* + * This function prints a floating-point value in a format similar to + * printf("%.7g") on a single-precision machine or printf("%.9g") on a + * double-precision machine. The 7th digit won't always be totally correct + * in single-precision operation (for that level of accuracy, a more + * complicated algorithm would be needed). + */ +void UnityPrintFloat(const UNITY_DOUBLE input_number) +{ +#ifdef UNITY_INCLUDE_DOUBLE + static const int sig_digits = 9; + static const UNITY_INT32 min_scaled = 100000000; + static const UNITY_INT32 max_scaled = 1000000000; +#else + static const int sig_digits = 7; + static const UNITY_INT32 min_scaled = 1000000; + static const UNITY_INT32 max_scaled = 10000000; +#endif + + UNITY_DOUBLE number = input_number; + + /* print minus sign (does not handle negative zero) */ + if (number < 0.0f) + { + UNITY_OUTPUT_CHAR('-'); + number = -number; + } + + /* handle zero, NaN, and +/- infinity */ + if (number == 0.0f) + { + UnityPrint("0"); + } + else if (UNITY_IS_NAN(number)) + { + UnityPrint("nan"); + } + else if (UNITY_IS_INF(number)) + { + UnityPrint("inf"); + } + else + { + UNITY_INT32 n_int = 0; + UNITY_INT32 n; + int exponent = 0; + int decimals; + int digits; + char buf[16] = {0}; + + /* + * Scale up or down by powers of 10. To minimize rounding error, + * start with a factor/divisor of 10^10, which is the largest + * power of 10 that can be represented exactly. Finally, compute + * (exactly) the remaining power of 10 and perform one more + * multiplication or division. + */ + if (number < 1.0f) + { + UNITY_DOUBLE factor = 1.0f; + + while (number < (UNITY_DOUBLE)max_scaled / 1e10f) { number *= 1e10f; exponent -= 10; } + while (number * factor < (UNITY_DOUBLE)min_scaled) { factor *= 10.0f; exponent--; } + + number *= factor; + } + else if (number > (UNITY_DOUBLE)max_scaled) + { + UNITY_DOUBLE divisor = 1.0f; + + while (number > (UNITY_DOUBLE)min_scaled * 1e10f) { number /= 1e10f; exponent += 10; } + while (number / divisor > (UNITY_DOUBLE)max_scaled) { divisor *= 10.0f; exponent++; } + + number /= divisor; + } + else + { + /* + * In this range, we can split off the integer part before + * doing any multiplications. This reduces rounding error by + * freeing up significant bits in the fractional part. + */ + UNITY_DOUBLE factor = 1.0f; + n_int = (UNITY_INT32)number; + number -= (UNITY_DOUBLE)n_int; + + while (n_int < min_scaled) { n_int *= 10; factor *= 10.0f; exponent--; } + + number *= factor; + } + + /* round to nearest integer */ + n = ((UNITY_INT32)(number + number) + 1) / 2; + +#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO + /* round to even if exactly between two integers */ + if ((n & 1) && (((UNITY_DOUBLE)n - number) == 0.5f)) + n--; +#endif + + n += n_int; + + if (n >= max_scaled) + { + n = min_scaled; + exponent++; + } + + /* determine where to place decimal point */ + decimals = ((exponent <= 0) && (exponent >= -(sig_digits + 3))) ? (-exponent) : (sig_digits - 1); + exponent += decimals; + + /* truncate trailing zeroes after decimal point */ + while ((decimals > 0) && ((n % 10) == 0)) + { + n /= 10; + decimals--; + } + + /* build up buffer in reverse order */ + digits = 0; + while ((n != 0) || (digits <= decimals)) + { + buf[digits++] = (char)('0' + n % 10); + n /= 10; + } + + /* print out buffer (backwards) */ + while (digits > 0) + { + if (digits == decimals) + { + UNITY_OUTPUT_CHAR('.'); + } + UNITY_OUTPUT_CHAR(buf[--digits]); + } + + /* print exponent if needed */ + if (exponent != 0) + { + UNITY_OUTPUT_CHAR('e'); + + if (exponent < 0) + { + UNITY_OUTPUT_CHAR('-'); + exponent = -exponent; + } + else + { + UNITY_OUTPUT_CHAR('+'); + } + + digits = 0; + while ((exponent != 0) || (digits < 2)) + { + buf[digits++] = (char)('0' + exponent % 10); + exponent /= 10; + } + while (digits > 0) + { + UNITY_OUTPUT_CHAR(buf[--digits]); + } + } + } +} +#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line) +{ +#ifdef UNITY_OUTPUT_FOR_ECLIPSE + UNITY_OUTPUT_CHAR('('); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(')'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else +#ifdef UNITY_OUTPUT_FOR_IAR_WORKBENCH + UnityPrint("'); + UnityPrint(Unity.CurrentTestName); + UnityPrint(" "); +#else +#ifdef UNITY_OUTPUT_FOR_QT_CREATOR + UnityPrint("file://"); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(':'); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#endif +#endif +#endif +} + +/*-----------------------------------------------*/ +static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + UNITY_OUTPUT_CHAR(':'); +} + +/*-----------------------------------------------*/ +void UnityConcludeTest(void) +{ + if (Unity.CurrentTestIgnored) + { + Unity.TestIgnores++; + } + else if (!Unity.CurrentTestFailed) + { + UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber); + UnityPrint(UnityStrPass); + } + else + { + Unity.TestFailures++; + } + + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + UNITY_PRINT_EXEC_TIME(); + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); +} + +/*-----------------------------------------------*/ +static void UnityAddMsgIfSpecified(const char* msg) +{ +#ifdef UNITY_PRINT_TEST_CONTEXT + UnityPrint(UnityStrSpacer); + UNITY_PRINT_TEST_CONTEXT(); +#endif +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrSpacer); + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + } +#endif + if (msg) + { + UnityPrint(UnityStrSpacer); + UnityPrint(msg); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(expected); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(actual); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStringsLen(const char* expected, + const char* actual, + const UNITY_UINT32 length) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(expected, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(actual, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*----------------------------------------------- + * Assertion & Control Helpers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_LINE_TYPE lineNumber, + const char* msg) +{ + /* Both are NULL or same pointer */ + if (expected == actual) { return 0; } + + /* print and return true if just expected is NULL */ + if (expected == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForExpected); + UnityAddMsgIfSpecified(msg); + return 1; + } + + /* print and return true if just actual is NULL */ + if (actual == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForActual); + UnityAddMsgIfSpecified(msg); + return 1; + } + + return 0; /* return false if neither is NULL */ +} + +/*----------------------------------------------- + * Assertion Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((mask & expected) != (mask & actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected); + UnityPrint(UnityStrWas); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (expected != actual) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + int failed = 0; + RETURN_IF_FAIL_OR_IGNORE; + + if ((threshold == actual) && (compare & UNITY_EQUAL_TO)) { return; } + if ((threshold == actual)) { failed = 1; } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if ((actual > threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if ((actual < threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + } + else /* UINT or HEX */ + { + if (((UNITY_UINT)actual > (UNITY_UINT)threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (((UNITY_UINT)actual < (UNITY_UINT)threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(actual, style); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + if (compare == UNITY_NOT_EQUAL) { UnityPrint(UnityStrNotEqual); } + UnityPrintNumberByStyle(threshold, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#define UnityPrintPointlessAndBail() \ +do { \ + UnityTestResultsFailBegin(lineNumber); \ + UnityPrint(UnityStrPointless); \ + UnityAddMsgIfSpecified(msg); \ + UNITY_FAIL_AND_BAIL; \ +} while (0) + +/*-----------------------------------------------*/ +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x000000FF; + actual_val &= 0x000000FF; + } + increment = sizeof(UNITY_INT8); + break; + + case 2: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x0000FFFF; + actual_val &= 0x0000FFFF; + } + increment = sizeof(UNITY_INT16); + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; +#ifdef UNITY_SUPPORT_64 + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x00000000FFFFFFFF; + actual_val &= 0x00000000FFFFFFFF; + } +#endif + increment = sizeof(UNITY_INT32); + length = 4; + break; + } + + if (expect_val != actual_val) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT +/* Wrap this define in a function with variable types as float or double */ +#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \ + if (UNITY_IS_INF(expected) && UNITY_IS_INF(actual) && (((expected) < 0) == ((actual) < 0))) return 1; \ + if (UNITY_NAN_CHECK) return 1; \ + (diff) = (actual) - (expected); \ + if ((diff) < 0) (diff) = -(diff); \ + if ((delta) < 0) (delta) = -(delta); \ + return !(UNITY_IS_NAN(diff) || UNITY_IS_INF(diff) || ((diff) > (delta))) + /* This first part of this condition will catch any NaN or Infinite values */ +#ifndef UNITY_NAN_NOT_EQUAL_NAN + #define UNITY_NAN_CHECK UNITY_IS_NAN(expected) && UNITY_IS_NAN(actual) +#else + #define UNITY_NAN_CHECK 0 +#endif + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + do { \ + UnityPrint(UnityStrExpected); \ + UnityPrintFloat(expected); \ + UnityPrint(UnityStrWas); \ + UnityPrintFloat(actual); \ + } while (0) +#else + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + UnityPrint(UnityStrDelta) +#endif /* UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual) +{ + UNITY_FLOAT diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual; + UNITY_FLOAT in_delta = delta; + UNITY_FLOAT current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (UNITY_IS_INF(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (UNITY_IS_NAN(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_FLOAT_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityFloatsWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + + if (!UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityFloatsWithin(threshold * UNITY_FLOAT_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = UNITY_IS_INF(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = UNITY_IS_INF(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = UNITY_IS_NAN(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !UNITY_IS_INF(actual) && !UNITY_IS_NAN(actual); + break; + + case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */ + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat((UNITY_DOUBLE)actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_FLOAT */ + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_DOUBLE +static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual) +{ + UNITY_DOUBLE diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual; + UNITY_DOUBLE in_delta = delta; + UNITY_DOUBLE current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (UNITY_IS_INF(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (UNITY_IS_NAN(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_DOUBLE_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityDoublesWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (!UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityDoublesWithin(threshold * UNITY_DOUBLE_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = UNITY_IS_INF(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = UNITY_IS_INF(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = UNITY_IS_NAN(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !UNITY_IS_INF(actual) && !UNITY_IS_NAN(actual); + break; + + case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */ + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat(actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_DOUBLE */ + +/*-----------------------------------------------*/ +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual > expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + else + { + if ((UNITY_UINT)actual > (UNITY_UINT)expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + increment = sizeof(UNITY_INT8); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)actual; + increment = sizeof(UNITY_UINT8); + } + break; + + case 2: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + increment = sizeof(UNITY_INT16); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)actual; + increment = sizeof(UNITY_UINT16); + } + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)actual; + increment = sizeof(UNITY_UINT64); + } + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; + increment = sizeof(UNITY_INT32); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)actual; + increment = sizeof(UNITY_UINT32); + } + length = 4; + break; + } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual_val > expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + else + { + if ((UNITY_UINT)actual_val > (UNITY_UINT)expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; expected[i] || actual[i]; i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* fail if either null but not if both */ + if (expected || actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStrings(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; (i < length) && (expected[i] || actual[i]); i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* fail if either null but not if both */ + if (expected || actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStringsLen(expected, actual, length); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 i = 0; + UNITY_UINT32 j = 0; + const char* expd = NULL; + const char* act = NULL; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if no elements, it's an error */ + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if ((const void*)expected == (const void*)actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + if (flags != UNITY_ARRAY_TO_ARRAY) + { + expd = (const char*)expected; + } + + do + { + act = actual[j]; + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expd = ((const char* const*)expected)[j]; + } + + /* if both pointers not null compare the strings */ + if (expd && act) + { + for (i = 0; expd[i] || act[i]; i++) + { + if (expd[i] != act[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expd != act) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(j); + } + UnityPrintExpectedAndActualStrings(expd, act); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + } while (++j < num_elements); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual; + UNITY_UINT32 elements = num_elements; + UNITY_UINT32 bytes; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + if (length == 0) + { + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while (elements--) + { + bytes = length; + while (bytes--) + { + if (*ptr_exp != *ptr_act) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrMemory); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + } + UnityPrint(UnityStrByte); + UnityPrintNumberUnsigned(length - bytes - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_exp++; + ptr_act++; + } + if (flags == UNITY_ARRAY_TO_VAL) + { + ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + } + } +} + +/*-----------------------------------------------*/ + +static union +{ + UNITY_INT8 i8; + UNITY_INT16 i16; + UNITY_INT32 i32; +#ifdef UNITY_SUPPORT_64 + UNITY_INT64 i64; +#endif +#ifndef UNITY_EXCLUDE_FLOAT + float f; +#endif +#ifndef UNITY_EXCLUDE_DOUBLE + double d; +#endif +} UnityQuickCompare; + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size) +{ + switch(size) + { + case 1: + UnityQuickCompare.i8 = (UNITY_INT8)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8); + + case 2: + UnityQuickCompare.i16 = (UNITY_INT16)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16); + +#ifdef UNITY_SUPPORT_64 + case 8: + UnityQuickCompare.i64 = (UNITY_INT64)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64); +#endif + + default: /* 4 bytes */ + UnityQuickCompare.i32 = (UNITY_INT32)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32); + } +} + +#ifndef UNITY_EXCLUDE_FLOAT +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num) +{ + UnityQuickCompare.f = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f); +} +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) +{ + UnityQuickCompare.d = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d); +} +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED + +/*----------------------------------------------- + * printf length modifier helpers + *-----------------------------------------------*/ + +enum UnityLengthModifier { + UNITY_LENGTH_MODIFIER_NONE, + UNITY_LENGTH_MODIFIER_LONG_LONG, + UNITY_LENGTH_MODIFIER_LONG, +}; + +#define UNITY_EXTRACT_ARG(NUMBER_T, NUMBER, LENGTH_MOD, VA, ARG_T) \ +do { \ + switch (LENGTH_MOD) \ + { \ + case UNITY_LENGTH_MODIFIER_LONG_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_NONE: \ + default: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, ARG_T); \ + break; \ + } \ + } \ +} while (0) + +static enum UnityLengthModifier UnityLengthModifierGet(const char *pch, int *length) +{ + enum UnityLengthModifier length_mod; + switch (pch[0]) + { + case 'l': + { + if (pch[1] == 'l') + { + *length = 2; + length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG; + } + else + { + *length = 1; + length_mod = UNITY_LENGTH_MODIFIER_LONG; + } + break; + } + case 'h': + { + // short and char are converted to int + length_mod = UNITY_LENGTH_MODIFIER_NONE; + if (pch[1] == 'h') + { + *length = 2; + } + else + { + *length = 1; + } + break; + } + case 'j': + case 'z': + case 't': + case 'L': + { + // Not supported, but should gobble up the length specifier anyway + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 1; + break; + } + default: + { + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 0; + } + } + return length_mod; +} + +/*----------------------------------------------- + * printf helper function + *-----------------------------------------------*/ +static void UnityPrintFVA(const char* format, va_list va) +{ + const char* pch = format; + if (pch != NULL) + { + while (*pch) + { + /* format identification character */ + if (*pch == '%') + { + pch++; + + if (pch != NULL) + { + int length_mod_size; + enum UnityLengthModifier length_mod = UnityLengthModifierGet(pch, &length_mod_size); + pch += length_mod_size; + + switch (*pch) + { + case 'd': + case 'i': + { + UNITY_INT number; + UNITY_EXTRACT_ARG(UNITY_INT, number, length_mod, va, int); + UnityPrintNumber((UNITY_INT)number); + break; + } +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + case 'f': + case 'g': + { + const double number = va_arg(va, double); + UnityPrintFloat((UNITY_DOUBLE)number); + break; + } +#endif + case 'u': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UnityPrintNumberUnsigned(number); + break; + } + case 'b': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1; + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('b'); + UnityPrintMask(mask, number); + break; + } + case 'x': + case 'X': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex(number, UNITY_MAX_NIBBLES); + break; + } + case 'p': + { + UNITY_UINT number; + char nibbles_to_print = 8; + if (UNITY_POINTER_WIDTH == 64) + { + length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG; + nibbles_to_print = 16; + } + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, nibbles_to_print); + break; + } + case 'c': + { + const int ch = va_arg(va, int); + UnityPrintChar((const char *)&ch); + break; + } + case 's': + { + const char * string = va_arg(va, const char *); + UnityPrint(string); + break; + } + case '%': + { + UnityPrintChar(pch); + break; + } + default: + { + /* print the unknown format character */ + UNITY_OUTPUT_CHAR('%'); + UnityPrintChar(pch); + break; + } + } + } + } +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + else if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + else if (*pch == '\n') + { + UNITY_PRINT_EOL(); + } + else + { + UnityPrintChar(pch); + } + + pch++; + } + } +} + +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if(format != NULL) + { + UnityPrint(": "); + va_list va; + va_start(va, format); + UnityPrintFVA(format, va); + va_end(va); + } + UNITY_PRINT_EOL(); +} +#endif /* ! UNITY_INCLUDE_PRINT_FORMATTED */ + + +/*----------------------------------------------- + * Control Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityFail(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + +#ifdef UNITY_PRINT_TEST_CONTEXT + UNITY_PRINT_TEST_CONTEXT(); +#endif +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + UnityPrint(UnityStrSpacer); + } +#endif + if (msg[0] != ' ') + { + UNITY_OUTPUT_CHAR(' '); + } + UnityPrint(msg); + } + + UNITY_FAIL_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrIgnore); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_IGNORE_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityMessage(const char* msg, const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_PRINT_EOL(); +} + +/*-----------------------------------------------*/ +/* If we have not defined our own test runner, then include our default test runner to make life easier */ +#ifndef UNITY_SKIP_DEFAULT_RUNNER +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum) +{ + Unity.CurrentTestName = FuncName; + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum; + Unity.NumberOfTests++; + UNITY_CLR_DETAILS(); + UNITY_EXEC_TIME_START(); + if (TEST_PROTECT()) + { + setUp(); + Func(); + } + if (TEST_PROTECT()) + { + tearDown(); + } + UNITY_EXEC_TIME_STOP(); + UnityConcludeTest(); +} +#endif + +/*-----------------------------------------------*/ +void UnitySetTestFile(const char* filename) +{ + Unity.TestFile = filename; +} + +/*-----------------------------------------------*/ +void UnityBegin(const char* filename) +{ + Unity.TestFile = filename; + Unity.CurrentTestName = NULL; + Unity.CurrentTestLineNumber = 0; + Unity.NumberOfTests = 0; + Unity.TestFailures = 0; + Unity.TestIgnores = 0; + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + + UNITY_CLR_DETAILS(); + UNITY_OUTPUT_START(); +} + +/*-----------------------------------------------*/ +int UnityEnd(void) +{ + UNITY_PRINT_EOL(); + UnityPrint(UnityStrBreaker); + UNITY_PRINT_EOL(); + UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests)); + UnityPrint(UnityStrResultsTests); + UnityPrintNumber((UNITY_INT)(Unity.TestFailures)); + UnityPrint(UnityStrResultsFailures); + UnityPrintNumber((UNITY_INT)(Unity.TestIgnores)); + UnityPrint(UnityStrResultsIgnored); + UNITY_PRINT_EOL(); + if (Unity.TestFailures == 0U) + { + UnityPrint(UnityStrOk); + } + else + { + UnityPrint(UnityStrFail); +#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL + UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D'); +#endif + } + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); + UNITY_OUTPUT_COMPLETE(); + return (int)(Unity.TestFailures); +} + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ +#ifdef UNITY_USE_COMMAND_LINE_ARGS + +char* UnityOptionIncludeNamed = NULL; +char* UnityOptionExcludeNamed = NULL; +int UnityVerbosity = 1; +int UnityStrictMatch = 0; + +/*-----------------------------------------------*/ +int UnityParseOptions(int argc, char** argv) +{ + int i; + UnityOptionIncludeNamed = NULL; + UnityOptionExcludeNamed = NULL; + UnityStrictMatch = 0; + + for (i = 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'l': /* list tests */ + return -1; + case 'n': /* include tests with name including this string */ + case 'f': /* an alias for -n */ + UnityStrictMatch = (argv[i][1] == 'n'); /* strictly match this string if -n */ + if (argv[i][2] == '=') + { + UnityOptionIncludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionIncludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Include Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + case 'q': /* quiet */ + UnityVerbosity = 0; + break; + case 'v': /* verbose */ + UnityVerbosity = 2; + break; + case 'x': /* exclude tests with name including this string */ + if (argv[i][2] == '=') + { + UnityOptionExcludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionExcludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Exclude Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + default: + UnityPrint("ERROR: Unknown Option "); + UNITY_OUTPUT_CHAR(argv[i][1]); + UNITY_PRINT_EOL(); + /* Now display help */ + /* FALLTHRU */ + case 'h': + UnityPrint("Options: "); UNITY_PRINT_EOL(); + UnityPrint("-l List all tests and exit"); UNITY_PRINT_EOL(); + UnityPrint("-f NAME Filter to run only tests whose name includes NAME"); UNITY_PRINT_EOL(); + UnityPrint("-n NAME Run only the test named NAME"); UNITY_PRINT_EOL(); + UnityPrint("-h show this Help menu"); UNITY_PRINT_EOL(); + UnityPrint("-q Quiet/decrease verbosity"); UNITY_PRINT_EOL(); + UnityPrint("-v increase Verbosity"); UNITY_PRINT_EOL(); + UnityPrint("-x NAME eXclude tests whose name includes NAME"); UNITY_PRINT_EOL(); + UNITY_OUTPUT_FLUSH(); + return 1; + } + } + } + + return 0; +} + +/*-----------------------------------------------*/ +static int IsStringInBiggerString(const char* longstring, const char* shortstring) +{ + const char* lptr = longstring; + const char* sptr = shortstring; + const char* lnext = lptr; + + if (*sptr == '*') + { + return UnityStrictMatch ? 0 : 1; + } + + while (*lptr) + { + lnext = lptr + 1; + + /* If they current bytes match, go on to the next bytes */ + while (*lptr && *sptr && (*lptr == *sptr)) + { + lptr++; + sptr++; + + switch (*sptr) + { + case '*': /* we encountered a wild-card */ + return UnityStrictMatch ? 0 : 1; + + case ',': /* we encountered the end of match string */ + case '"': + case '\'': + case 0: + return (!UnityStrictMatch || (*lptr == 0)) ? 1 : 0; + + case ':': /* we encountered the end of a partial match */ + return 2; + + default: + break; + } + } + + // If we didn't match and we're on strict matching, we already know we failed + if (UnityStrictMatch) + { + return 0; + } + + /* Otherwise we start in the long pointer 1 character further and try again */ + lptr = lnext; + sptr = shortstring; + } + + return 0; +} + +/*-----------------------------------------------*/ +static int UnityStringArgumentMatches(const char* str) +{ + int retval; + const char* ptr1; + const char* ptr2; + const char* ptrf; + + /* Go through the options and get the substrings for matching one at a time */ + ptr1 = str; + while (ptr1[0] != 0) + { + if ((ptr1[0] == '"') || (ptr1[0] == '\'')) + { + ptr1++; + } + + /* look for the start of the next partial */ + ptr2 = ptr1; + ptrf = 0; + do + { + ptr2++; + if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')) + { + ptrf = &ptr2[1]; + } + } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')); + + while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ','))) + { + ptr2++; + } + + /* done if complete filename match */ + retval = IsStringInBiggerString(Unity.TestFile, ptr1); + if (retval == 1) + { + return retval; + } + + /* done if testname match after filename partial match */ + if ((retval == 2) && (ptrf != 0)) + { + if (IsStringInBiggerString(Unity.CurrentTestName, ptrf)) + { + return 1; + } + } + + /* done if complete testname match */ + if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1) + { + return 1; + } + + ptr1 = ptr2; + } + + /* we couldn't find a match for any substrings */ + return 0; +} + +/*-----------------------------------------------*/ +int UnityTestMatches(void) +{ + /* Check if this test name matches the included test pattern */ + int retval; + if (UnityOptionIncludeNamed) + { + retval = UnityStringArgumentMatches(UnityOptionIncludeNamed); + } + else + { + retval = 1; + } + + /* Check if this test name matches the excluded test pattern */ + if (UnityOptionExcludeNamed) + { + if (UnityStringArgumentMatches(UnityOptionExcludeNamed)) + { + retval = 0; + } + } + + return retval; +} + +#endif /* UNITY_USE_COMMAND_LINE_ARGS */ +/*-----------------------------------------------*/ diff --git a/src/unity/unity.h b/src/unity/unity.h new file mode 100644 index 00000000..8337c8c6 --- /dev/null +++ b/src/unity/unity.h @@ -0,0 +1,698 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-24 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_FRAMEWORK_H +#define UNITY_FRAMEWORK_H +#define UNITY + +#define UNITY_VERSION_MAJOR 2 +#define UNITY_VERSION_MINOR 6 +#define UNITY_VERSION_BUILD 0 +#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD) + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + +/*------------------------------------------------------- + * Test Setup / Teardown + *-------------------------------------------------------*/ + +/* These functions are intended to be called before and after each test. + * If using unity directly, these will need to be provided for each test + * executable built. If you are using the test runner generator and/or + * Ceedling, these are optional. */ +void setUp(void); +void tearDown(void); + +/* These functions are intended to be called at the beginning and end of an + * entire test suite. suiteTearDown() is passed the number of tests that + * failed, and its return value becomes the exit code of main(). If using + * Unity directly, you're in charge of calling these if they are desired. + * If using Ceedling or the test runner generator, these will be called + * automatically if they exist. */ +void suiteSetUp(void); +int suiteTearDown(int num_failures); + +/*------------------------------------------------------- + * Test Reset and Verify + *-------------------------------------------------------*/ + +/* These functions are intended to be called before during tests in order + * to support complex test loops, etc. Both are NOT built into Unity. Instead + * the test runner generator will create them. resetTest will run teardown and + * setup again, verifying any end-of-test needs between. verifyTest will only + * run the verification. */ +void resetTest(void); +void verifyTest(void); + +/*------------------------------------------------------- + * Configuration Options + *------------------------------------------------------- + * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. + + * Integers/longs/pointers + * - Unity attempts to automatically discover your integer sizes + * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in + * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in + * - If you cannot use the automatic methods above, you can force Unity by using these options: + * - define UNITY_SUPPORT_64 + * - set UNITY_INT_WIDTH + * - set UNITY_LONG_WIDTH + * - set UNITY_POINTER_WIDTH + + * Floats + * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons + * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT + * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats + * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons + * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) + * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE + * - define UNITY_DOUBLE_TYPE to specify something other than double + * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors + + * Output + * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired + * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure + + * Optimization + * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge + * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. + + * Test Cases + * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script + + * Parameterized Tests + * - you'll want to create a define of TEST_CASE(...), TEST_RANGE(...) and/or TEST_MATRIX(...) which basically evaluates to nothing + + * Tests with Arguments + * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity + + *------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message)) +#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL) +#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message)) +#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL) +#define TEST_MESSAGE(message) UnityMessage((message), __LINE__) +#define TEST_ONLY() +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), ##__VA_ARGS__) +#endif + +/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. + * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ +#define TEST_PASS() TEST_ABORT() +#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0) + +/*------------------------------------------------------- + * Build Directives + *------------------------------------------------------- + + * These macros do nothing, but they are useful for additional build context. + * Tools (like Ceedling) can scan for these directives and make use of them for + * per-test-executable #include search paths and linking. */ + +/* Add source files to a test executable's compilation and linking. Ex: TEST_SOURCE_FILE("sandwiches.c") */ +#define TEST_SOURCE_FILE(a) + +/* Customize #include search paths for a test executable's compilation. Ex: TEST_INCLUDE_PATH("src/module_a/inc") */ +#define TEST_INCLUDE_PATH(a) + +/*------------------------------------------------------- + * Test Asserts (simple) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE") +#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE") +#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE") +#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE") +#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL") +#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") +#define TEST_ASSERT_EMPTY(pointer) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, " Expected Empty") +#define TEST_ASSERT_NOT_EMPTY(pointer) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, " Expected Non-Empty") + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR(expected, actual) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(0), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(0), (actual), __LINE__, NULL) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) + +/* Arrays Compared To Single Value */ +#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal") +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/*------------------------------------------------------- + * Test Asserts (with additional messages) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) +#define TEST_ASSERT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, (message)) + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message)) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message)) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) + +/* Arrays Compared To Single Value*/ +#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message)) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message) +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/* end of UNITY_FRAMEWORK_H */ +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/unity/unity_internals.h b/src/unity/unity_internals.h new file mode 100644 index 00000000..562f5b6d --- /dev/null +++ b/src/unity/unity_internals.h @@ -0,0 +1,1183 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_INTERNALS_H +#define UNITY_INTERNALS_H + +#ifdef UNITY_INCLUDE_CONFIG_H +#include "unity_config.h" +#endif + +#ifndef UNITY_EXCLUDE_SETJMP_H +#include +#endif + +#ifndef UNITY_EXCLUDE_MATH_H +#include +#endif + +#ifndef UNITY_EXCLUDE_STDDEF_H +#include +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#include +#endif + +/* Unity Attempts to Auto-Detect Integer Types + * Attempt 1: UINT_MAX, ULONG_MAX in , or default to 32 bits + * Attempt 2: UINTPTR_MAX in , or default to same size as long + * The user may override any of these derived constants: + * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */ +#ifndef UNITY_EXCLUDE_STDINT_H +#include +#endif + +#ifndef UNITY_EXCLUDE_LIMITS_H +#include +#endif + +#if defined(__GNUC__) || defined(__clang__) + #define UNITY_FUNCTION_ATTR(a) __attribute__((a)) +#else + #define UNITY_FUNCTION_ATTR(a) /* ignore */ +#endif + +/* UNITY_NORETURN is only required if we have setjmp.h. */ +#ifndef UNITY_EXCLUDE_SETJMP_H + #ifndef UNITY_NORETURN + #if defined(__cplusplus) + #if __cplusplus >= 201103L + #define UNITY_NORETURN [[ noreturn ]] + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && __STDC_VERSION__ < 202311L + /* _Noreturn keyword is used from C11 but deprecated in C23. */ + #if defined(_WIN32) && defined(_MSC_VER) + /* We are using MSVC compiler on Windows platform. */ + /* Not all Windows SDKs supports , but compiler can support C11: */ + /* https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ */ + /* Not sure, that Mingw compilers has Windows SDK headers at all. */ + #include + #endif + + /* Using Windows SDK predefined macro for detecting supported SDK with MSVC compiler. */ + /* Mingw GCC should work without that fixes. */ + /* Based on: */ + /* https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 */ + /* NTDDI_WIN10_FE is equal to Windows 10 SDK 2104 */ + #if defined(_MSC_VER) && ((!defined(NTDDI_WIN10_FE)) || WDK_NTDDI_VERSION < NTDDI_WIN10_FE) + /* Based on tests and: */ + /* https://docs.microsoft.com/en-us/cpp/c-language/noreturn?view=msvc-170 */ + /* https://en.cppreference.com/w/c/language/_Noreturn */ + #define UNITY_NORETURN _Noreturn + #else /* Using newer Windows SDK or not MSVC compiler */ + #if defined(__GNUC__) + /* The header collides with __attribute(noreturn)__ from GCC. */ + #define UNITY_NORETURN _Noreturn + #else + #include + #define UNITY_NORETURN noreturn + #endif + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L + /* Since C23, the keyword _Noreturn has been replaced by the attribute noreturn, based on: */ + /* https://en.cppreference.com/w/c/language/attributes/noreturn */ + #define UNITY_NORETURN [[ noreturn ]] + #endif + #endif + #ifndef UNITY_NORETURN + #define UNITY_NORETURN UNITY_FUNCTION_ATTR(__noreturn__) + #endif +#endif + +/*------------------------------------------------------- + * Guess Widths If Not Specified + *-------------------------------------------------------*/ + +/* Determine the size of an int, if not already specified. + * We cannot use sizeof(int), because it is not yet defined + * at this stage in the translation of the C program. + * Also sizeof(int) does return the size in addressable units on all platforms, + * which may not necessarily be the size in bytes. + * Therefore, infer it from UINT_MAX if possible. */ +#ifndef UNITY_INT_WIDTH + #ifdef UINT_MAX + #if (UINT_MAX == 0xFFFF) + #define UNITY_INT_WIDTH (16) + #elif (UINT_MAX == 0xFFFFFFFF) + #define UNITY_INT_WIDTH (32) + #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_INT_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_INT_WIDTH (32) + #endif /* UINT_MAX */ +#endif + +/* Determine the size of a long, if not already specified. */ +#ifndef UNITY_LONG_WIDTH + #ifdef ULONG_MAX + #if (ULONG_MAX == 0xFFFF) + #define UNITY_LONG_WIDTH (16) + #elif (ULONG_MAX == 0xFFFFFFFF) + #define UNITY_LONG_WIDTH (32) + #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_LONG_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_LONG_WIDTH (32) + #endif /* ULONG_MAX */ +#endif + +/* Determine the size of a pointer, if not already specified. */ +#ifndef UNITY_POINTER_WIDTH + #ifdef UINTPTR_MAX + #if (UINTPTR_MAX <= 0xFFFF) + #define UNITY_POINTER_WIDTH (16) + #elif (UINTPTR_MAX <= 0xFFFFFFFF) + #define UNITY_POINTER_WIDTH (32) + #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF) + #define UNITY_POINTER_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH + #endif /* UINTPTR_MAX */ +#endif + +/*------------------------------------------------------- + * Int Support (Define types based on detected sizes) + *-------------------------------------------------------*/ + +#if (UNITY_INT_WIDTH == 32) + typedef unsigned char UNITY_UINT8; + typedef unsigned short UNITY_UINT16; + typedef unsigned int UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed short UNITY_INT16; + typedef signed int UNITY_INT32; +#elif (UNITY_INT_WIDTH == 16) + typedef unsigned char UNITY_UINT8; + typedef unsigned int UNITY_UINT16; + typedef unsigned long UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed int UNITY_INT16; + typedef signed long UNITY_INT32; +#else + #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) +#endif + +/*------------------------------------------------------- + * 64-bit Support + *-------------------------------------------------------*/ + +/* Auto-detect 64 Bit Support */ +#ifndef UNITY_SUPPORT_64 + #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 + #define UNITY_SUPPORT_64 + #endif +#endif + +/* 64-Bit Support Dependent Configuration */ +#ifndef UNITY_SUPPORT_64 + /* No 64-bit Support */ + typedef UNITY_UINT32 UNITY_UINT; + typedef UNITY_INT32 UNITY_INT; + #define UNITY_MAX_NIBBLES (8) /* Maximum number of nibbles in a UNITY_(U)INT */ +#else + /* 64-bit Support */ + #if (UNITY_LONG_WIDTH == 32) + typedef unsigned long long UNITY_UINT64; + typedef signed long long UNITY_INT64; + #elif (UNITY_LONG_WIDTH == 64) + typedef unsigned long UNITY_UINT64; + typedef signed long UNITY_INT64; + #else + #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) + #endif + typedef UNITY_UINT64 UNITY_UINT; + typedef UNITY_INT64 UNITY_INT; + #define UNITY_MAX_NIBBLES (16) /* Maximum number of nibbles in a UNITY_(U)INT */ +#endif + +/*------------------------------------------------------- + * Pointer Support + *-------------------------------------------------------*/ + +#if (UNITY_POINTER_WIDTH == 32) + #define UNITY_PTR_TO_INT UNITY_INT32 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 +#elif (UNITY_POINTER_WIDTH == 64) + #define UNITY_PTR_TO_INT UNITY_INT64 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 +#elif (UNITY_POINTER_WIDTH == 16) + #define UNITY_PTR_TO_INT UNITY_INT16 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 +#else + #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) +#endif + +#ifndef UNITY_PTR_ATTRIBUTE + #define UNITY_PTR_ATTRIBUTE +#endif + +#ifndef UNITY_INTERNAL_PTR + #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* +#endif + +/* optionally define UNITY_COMPARE_PTRS_ON_ZERO_ARRAY */ + +/*------------------------------------------------------- + * Float Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_FLOAT + +/* No Floating Point Support */ +#ifndef UNITY_EXCLUDE_DOUBLE +#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */ +#endif +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +#define UNITY_EXCLUDE_FLOAT_PRINT +#endif + +#else + +/* Floating Point Support */ +#ifndef UNITY_FLOAT_PRECISION +#define UNITY_FLOAT_PRECISION (0.00001f) +#endif +#ifndef UNITY_FLOAT_TYPE +#define UNITY_FLOAT_TYPE float +#endif +typedef UNITY_FLOAT_TYPE UNITY_FLOAT; + +/* isnan macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_NAN +#ifndef isnan +/* NaN is the only floating point value that does NOT equal itself. + * Therefore if n != n, then it is NaN. */ +#define UNITY_IS_NAN(n) ((n != n) ? 1 : 0) +#else +#define UNITY_IS_NAN(n) isnan(n) +#endif +#endif + +/* isinf macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_INF +#ifndef isinf +/* The value of Inf - Inf is NaN */ +#define UNITY_IS_INF(n) (UNITY_IS_NAN((n) - (n)) && !UNITY_IS_NAN(n)) +#else +#define UNITY_IS_INF(n) isinf(n) +#endif +#endif + +#endif + +/*------------------------------------------------------- + * Double Float Support + *-------------------------------------------------------*/ + +/* unlike float, we DON'T include by default */ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE) + + /* No Floating Point Support */ + #ifndef UNITY_EXCLUDE_DOUBLE + #define UNITY_EXCLUDE_DOUBLE + #else + #undef UNITY_INCLUDE_DOUBLE + #endif + + #ifndef UNITY_EXCLUDE_FLOAT + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_FLOAT UNITY_DOUBLE; + /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */ + #endif + +#else + + /* Double Floating Point Support */ + #ifndef UNITY_DOUBLE_PRECISION + #define UNITY_DOUBLE_PRECISION (1e-12) + #endif + + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE; + +#endif + +/*------------------------------------------------------- + * Output Method: stdout (DEFAULT) + *-------------------------------------------------------*/ +#ifndef UNITY_OUTPUT_CHAR + /* Default to using putchar, which is defined in stdio.h */ + #include + #define UNITY_OUTPUT_CHAR(a) (void)putchar(a) +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION + extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH + #ifdef UNITY_USE_FLUSH_STDOUT + /* We want to use the stdout flush utility */ + #include + #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) + #else + /* We've specified nothing, therefore flush should just be ignored */ + #define UNITY_OUTPUT_FLUSH() (void)0 + #endif +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION + extern void UNITY_OUTPUT_FLUSH_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +#define UNITY_FLUSH_CALL() +#else +#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() +#endif + +#ifndef UNITY_PRINT_EOL +#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') +#endif + +#ifndef UNITY_OUTPUT_START +#define UNITY_OUTPUT_START() +#endif + +#ifndef UNITY_OUTPUT_COMPLETE +#define UNITY_OUTPUT_COMPLETE() +#endif + +#ifdef UNITY_INCLUDE_EXEC_TIME + #if !defined(UNITY_EXEC_TIME_START) && \ + !defined(UNITY_EXEC_TIME_STOP) && \ + !defined(UNITY_PRINT_EXEC_TIME) && \ + !defined(UNITY_TIME_TYPE) + /* If none any of these macros are defined then try to provide a default implementation */ + + #if defined(UNITY_CLOCK_MS) + /* This is a simple way to get a default implementation on platforms that support getting a millisecond counter */ + #define UNITY_TIME_TYPE UNITY_UINT + #define UNITY_EXEC_TIME_START() Unity.CurrentTestStartTime = UNITY_CLOCK_MS() + #define UNITY_EXEC_TIME_STOP() Unity.CurrentTestStopTime = UNITY_CLOCK_MS() + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(_WIN32) + #include + #define UNITY_TIME_TYPE clock_t + #define UNITY_GET_TIME(t) t = (clock_t)((clock() * 1000) / CLOCKS_PER_SEC) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(__unix__) || defined(__APPLE__) + #include + #define UNITY_TIME_TYPE struct timespec + #define UNITY_GET_TIME(t) clock_gettime(CLOCK_MONOTONIC, &t) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = ((Unity.CurrentTestStopTime.tv_sec - Unity.CurrentTestStartTime.tv_sec) * 1000L); \ + execTimeMs += ((Unity.CurrentTestStopTime.tv_nsec - Unity.CurrentTestStartTime.tv_nsec) / 1000000L); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #endif + #endif +#endif + +#ifndef UNITY_EXEC_TIME_START +#define UNITY_EXEC_TIME_START() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_EXEC_TIME_STOP +#define UNITY_EXEC_TIME_STOP() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_TIME_TYPE +#define UNITY_TIME_TYPE UNITY_UINT +#endif + +#ifndef UNITY_PRINT_EXEC_TIME +#define UNITY_PRINT_EXEC_TIME() do { /* nothing*/ } while (0) +#endif + +/*------------------------------------------------------- + * Footprint + *-------------------------------------------------------*/ + +#ifndef UNITY_LINE_TYPE +#define UNITY_LINE_TYPE UNITY_UINT +#endif + +#ifndef UNITY_COUNTER_TYPE +#define UNITY_COUNTER_TYPE UNITY_UINT +#endif + +/*------------------------------------------------------- + * Internal Structs Needed + *-------------------------------------------------------*/ + +typedef void (*UnityTestFunction)(void); + +#define UNITY_DISPLAY_RANGE_INT (0x10) +#define UNITY_DISPLAY_RANGE_UINT (0x20) +#define UNITY_DISPLAY_RANGE_HEX (0x40) +#define UNITY_DISPLAY_RANGE_CHAR (0x80) + +typedef enum +{ + UNITY_DISPLAY_STYLE_INT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT, +#endif + + UNITY_DISPLAY_STYLE_UINT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT, +#endif + + UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX, +#endif + + UNITY_DISPLAY_STYLE_CHAR = 1 + UNITY_DISPLAY_RANGE_CHAR + UNITY_DISPLAY_RANGE_INT, + + UNITY_DISPLAY_STYLE_UNKNOWN +} UNITY_DISPLAY_STYLE_T; + +typedef enum +{ + UNITY_WITHIN = 0x0, + UNITY_EQUAL_TO = 0x1, + UNITY_GREATER_THAN = 0x2, + UNITY_GREATER_OR_EQUAL = 0x2 + UNITY_EQUAL_TO, + UNITY_SMALLER_THAN = 0x4, + UNITY_SMALLER_OR_EQUAL = 0x4 + UNITY_EQUAL_TO, + UNITY_NOT_EQUAL = 0x0, + UNITY_UNKNOWN +} UNITY_COMPARISON_T; + +#ifndef UNITY_EXCLUDE_FLOAT +typedef enum UNITY_FLOAT_TRAIT +{ + UNITY_FLOAT_IS_NOT_INF = 0, + UNITY_FLOAT_IS_INF, + UNITY_FLOAT_IS_NOT_NEG_INF, + UNITY_FLOAT_IS_NEG_INF, + UNITY_FLOAT_IS_NOT_NAN, + UNITY_FLOAT_IS_NAN, + UNITY_FLOAT_IS_NOT_DET, + UNITY_FLOAT_IS_DET, + UNITY_FLOAT_INVALID_TRAIT +} UNITY_FLOAT_TRAIT_T; +#endif + +typedef enum +{ + UNITY_ARRAY_TO_VAL = 0, + UNITY_ARRAY_TO_ARRAY, + UNITY_ARRAY_UNKNOWN +} UNITY_FLAGS_T; + +struct UNITY_STORAGE_T +{ + const char* TestFile; + const char* CurrentTestName; +#ifndef UNITY_EXCLUDE_DETAILS + const char* CurrentDetail1; + const char* CurrentDetail2; +#endif + UNITY_LINE_TYPE CurrentTestLineNumber; + UNITY_COUNTER_TYPE NumberOfTests; + UNITY_COUNTER_TYPE TestFailures; + UNITY_COUNTER_TYPE TestIgnores; + UNITY_COUNTER_TYPE CurrentTestFailed; + UNITY_COUNTER_TYPE CurrentTestIgnored; +#ifdef UNITY_INCLUDE_EXEC_TIME + UNITY_TIME_TYPE CurrentTestStartTime; + UNITY_TIME_TYPE CurrentTestStopTime; +#endif +#ifndef UNITY_EXCLUDE_SETJMP_H + jmp_buf AbortFrame; +#endif +}; + +extern struct UNITY_STORAGE_T Unity; + +/*------------------------------------------------------- + * Test Suite Management + *-------------------------------------------------------*/ + +void UnityBegin(const char* filename); +int UnityEnd(void); +void UnitySetTestFile(const char* filename); +void UnityConcludeTest(void); + +#ifndef RUN_TEST +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum); +#else +#define UNITY_SKIP_DEFAULT_RUNNER +#endif + +/*------------------------------------------------------- + * Details Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_DETAILS +#define UNITY_CLR_DETAILS() +#define UNITY_SET_DETAIL(d1) +#define UNITY_SET_DETAILS(d1,d2) +#else +#define UNITY_CLR_DETAILS() do { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAIL(d1) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAILS(d1,d2) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = (d2); } while (0) + +#ifndef UNITY_DETAIL1_NAME +#define UNITY_DETAIL1_NAME "Function" +#endif + +#ifndef UNITY_DETAIL2_NAME +#define UNITY_DETAIL2_NAME "Argument" +#endif +#endif + +#ifdef UNITY_PRINT_TEST_CONTEXT +void UNITY_PRINT_TEST_CONTEXT(void); +#endif + +/*------------------------------------------------------- + * Test Output + *-------------------------------------------------------*/ + +void UnityPrint(const char* string); + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...); +#endif + +void UnityPrintLen(const char* string, const UNITY_UINT32 length); +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number); +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style); +void UnityPrintNumber(const UNITY_INT number_to_print); +void UnityPrintNumberUnsigned(const UNITY_UINT number); +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print); + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +void UnityPrintFloat(const UNITY_DOUBLE input_number); +#endif + +/*------------------------------------------------------- + * Test Assertion Functions + *------------------------------------------------------- + * Use the macros below this section instead of calling + * these directly. The macros have a consistent naming + * convention and will pull in file and line information + * for you. */ + +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +#ifndef UNITY_EXCLUDE_SETJMP_H +UNITY_NORETURN void UnityFail(const char* message, const UNITY_LINE_TYPE line); +UNITY_NORETURN void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#else +void UnityFail(const char* message, const UNITY_LINE_TYPE line); +void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#endif + +void UnityMessage(const char* message, const UNITY_LINE_TYPE line); + +#ifndef UNITY_EXCLUDE_FLOAT +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +/*------------------------------------------------------- + * Helpers + *-------------------------------------------------------*/ + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size); +#ifndef UNITY_EXCLUDE_FLOAT +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num); +#endif +#ifndef UNITY_EXCLUDE_DOUBLE +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num); +#endif + +/*------------------------------------------------------- + * Error Strings We Might Need + *-------------------------------------------------------*/ + +extern const char UnityStrOk[]; +extern const char UnityStrPass[]; +extern const char UnityStrFail[]; +extern const char UnityStrIgnore[]; + +extern const char UnityStrErrFloat[]; +extern const char UnityStrErrDouble[]; +extern const char UnityStrErr64[]; +extern const char UnityStrErrShorthand[]; + +/*------------------------------------------------------- + * Test Running Macros + *-------------------------------------------------------*/ + +#ifdef UNITY_TEST_PROTECT +#define TEST_PROTECT() UNITY_TEST_PROTECT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) +#else +#define TEST_PROTECT() 1 +#endif +#endif + +#ifdef UNITY_TEST_ABORT +#define TEST_ABORT() UNITY_TEST_ABORT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_ABORT() longjmp(Unity.AbortFrame, 1) +#else +#define TEST_ABORT() return +#endif +#endif + +/* Automatically enable variadic macros support, if it not enabled before */ +#ifndef UNITY_SUPPORT_VARIADIC_MACROS + #ifdef __STDC_VERSION__ + #if __STDC_VERSION__ >= 199901L + #define UNITY_SUPPORT_VARIADIC_MACROS + #endif + #endif +#endif + +/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ +#ifndef RUN_TEST +#ifdef UNITY_SUPPORT_VARIADIC_MACROS +#define RUN_TEST(...) RUN_TEST_AT_LINE(__VA_ARGS__, __LINE__, throwaway) +#define RUN_TEST_AT_LINE(func, line, ...) UnityDefaultTestRun(func, #func, line) +#endif +#endif + +/* Enable default macros for masking param tests test cases */ +#ifdef UNITY_SUPPORT_TEST_CASES + #ifdef UNITY_SUPPORT_VARIADIC_MACROS + #if !defined(TEST_CASE) && !defined(UNITY_EXCLUDE_TEST_CASE) + #define TEST_CASE(...) + #endif + #if !defined(TEST_RANGE) && !defined(UNITY_EXCLUDE_TEST_RANGE) + #define TEST_RANGE(...) + #endif + #if !defined(TEST_MATRIX) && !defined(UNITY_EXCLUDE_TEST_MATRIX) + #define TEST_MATRIX(...) + #endif + #endif +#endif + +/* If we can't do the tricky version, we'll just have to require them to always include the line number */ +#ifndef RUN_TEST +#ifdef CMOCK +#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) +#else +#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) +#endif +#endif + +#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) +#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) +#define UNITY_NEW_TEST(a) \ + Unity.CurrentTestName = (a); \ + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ + Unity.NumberOfTests++; + +#ifndef UNITY_BEGIN +#define UNITY_BEGIN() UnityBegin(__FILE__) +#endif + +#ifndef UNITY_END +#define UNITY_END() UnityEnd() +#endif + +#ifndef UNITY_SHORTHAND_AS_INT +#ifndef UNITY_SHORTHAND_AS_MEM +#ifndef UNITY_SHORTHAND_AS_NONE +#ifndef UNITY_SHORTHAND_AS_RAW +#define UNITY_SHORTHAND_AS_OLD +#endif +#endif +#endif +#endif + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ + +#ifdef UNITY_USE_COMMAND_LINE_ARGS +int UnityParseOptions(int argc, char** argv); +int UnityTestMatches(void); +#endif + +/*------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line)) + +/*------------------------------------------------------- + * Test Asserts + *-------------------------------------------------------*/ + +#define UNITY_TEST_ASSERT(condition, line, message) do { if (condition) { /* nothing*/ } else { UNITY_TEST_FAIL((line), (message)); } } while (0) +#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (line), (message)) +#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (line), (message)) +#define UNITY_TEST_ASSERT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) == 0), (line), (message)) +#define UNITY_TEST_ASSERT_NOT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) != 0), (line), (message)) + +#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_EQUAL_CHAR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) +#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line)) + +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16) (threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32) (threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16) (expected), (UNITY_INT)(UNITY_INT16) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32) (expected), (UNITY_INT)(UNITY_INT32) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_CHAR_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + + +#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) +#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) (expected), (UNITY_POINTER_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_VAL) + +#ifdef UNITY_SUPPORT_64 +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#else +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#endif + +#ifdef UNITY_EXCLUDE_FLOAT +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#else +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsNotWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)(delta), (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, UnityFloatToPtr(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +#ifdef UNITY_EXCLUDE_DOUBLE +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#else +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesNotWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)(delta), (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, UnityDoubleToPtr(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +/* End of UNITY_INTERNALS_H */ +#endif diff --git a/src/xce.nix b/src/xce.nix new file mode 100644 index 00000000..be13426b --- /dev/null +++ b/src/xce.nix @@ -0,0 +1,56 @@ +{ + lib, + stdenv, + pkgs, + myCommitId, + withDebug? false, + withAsan? false, + withoutDb? false, + ... +}: + +stdenv.mkDerivation { + + pname = "xce"; + version = "0.0.1"; + + src = ./.; + + nativeBuildInputs = [ + pkgs.meson + pkgs.ninja + pkgs.capnproto + pkgs.pkg-config + pkgs.cmake + pkgs.go + pkgs.openssl + pkgs.libtirpc + pkgs.readline + pkgs.ncurses + pkgs.capnpc + pkgs.which + pkgs.findutils + pkgs.libuv + pkgs.elogind + pkgs.sqlite + pkgs.hwloc + pkgs.linux-pam + pkgs.zlog_with_pkgconf + pkgs.unity-test + ]; + + build-system = [ pkgs.meson ]; + + dontStrip = (withDebug || withAsan); + separateDebugInfo = (withDebug || withAsan); + + impureEnvVars = [ "HOME" ]; + + mesonFlags =[ + (lib.optional withDebug "-Dwith_debug=true") + (lib.optional withAsan "-Db_sanitize=address") + (lib.optional withoutDb "-Dwithout_db=true") + ("-Dcommit_id=" + myCommitId) + # (lib.optional (!with_debug) "-Dbuildtype=release") + ]; +}