Adicionar primeiro
This commit is contained in:
493
components/api/lib/cAT/.clang-format
Executable file
493
components/api/lib/cAT/.clang-format
Executable file
@@ -0,0 +1,493 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# clang-format configuration file. Intended for clang-format >= 4.
|
||||
#
|
||||
# For more information, see:
|
||||
#
|
||||
# Documentation/process/clang-format.rst
|
||||
# https://clang.llvm.org/docs/ClangFormat.html
|
||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
#
|
||||
---
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
#AfterExternBlock: false # Unknown to clang-format-5.0
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
#SplitEmptyFunction: true # Unknown to clang-format-4.0
|
||||
#SplitEmptyRecord: true # Unknown to clang-format-4.0
|
||||
#SplitEmptyNamespace: true # Unknown to clang-format-4.0
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 160
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
#CompactNamespaces: false # Unknown to clang-format-4.0
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
#FixNamespaceComments: false # Unknown to clang-format-4.0
|
||||
|
||||
# Taken from:
|
||||
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
|
||||
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
|
||||
# | sort | uniq
|
||||
ForEachMacros:
|
||||
- 'apei_estatus_for_each_section'
|
||||
- 'ata_for_each_dev'
|
||||
- 'ata_for_each_link'
|
||||
- '__ata_qc_for_each'
|
||||
- 'ata_qc_for_each'
|
||||
- 'ata_qc_for_each_raw'
|
||||
- 'ata_qc_for_each_with_internal'
|
||||
- 'ax25_for_each'
|
||||
- 'ax25_uid_for_each'
|
||||
- '__bio_for_each_bvec'
|
||||
- 'bio_for_each_bvec'
|
||||
- 'bio_for_each_integrity_vec'
|
||||
- '__bio_for_each_segment'
|
||||
- 'bio_for_each_segment'
|
||||
- 'bio_for_each_segment_all'
|
||||
- 'bio_list_for_each'
|
||||
- 'bip_for_each_vec'
|
||||
- 'blkg_for_each_descendant_post'
|
||||
- 'blkg_for_each_descendant_pre'
|
||||
- 'blk_queue_for_each_rl'
|
||||
- 'bond_for_each_slave'
|
||||
- 'bond_for_each_slave_rcu'
|
||||
- 'bpf_for_each_spilled_reg'
|
||||
- 'btree_for_each_safe128'
|
||||
- 'btree_for_each_safe32'
|
||||
- 'btree_for_each_safe64'
|
||||
- 'btree_for_each_safel'
|
||||
- 'card_for_each_dev'
|
||||
- 'cgroup_taskset_for_each'
|
||||
- 'cgroup_taskset_for_each_leader'
|
||||
- 'cpufreq_for_each_entry'
|
||||
- 'cpufreq_for_each_entry_idx'
|
||||
- 'cpufreq_for_each_valid_entry'
|
||||
- 'cpufreq_for_each_valid_entry_idx'
|
||||
- 'css_for_each_child'
|
||||
- 'css_for_each_descendant_post'
|
||||
- 'css_for_each_descendant_pre'
|
||||
- 'device_for_each_child_node'
|
||||
- 'drm_atomic_crtc_for_each_plane'
|
||||
- 'drm_atomic_crtc_state_for_each_plane'
|
||||
- 'drm_atomic_crtc_state_for_each_plane_state'
|
||||
- 'drm_atomic_for_each_plane_damage'
|
||||
- 'drm_connector_for_each_possible_encoder'
|
||||
- 'drm_for_each_connector_iter'
|
||||
- 'drm_for_each_crtc'
|
||||
- 'drm_for_each_encoder'
|
||||
- 'drm_for_each_encoder_mask'
|
||||
- 'drm_for_each_fb'
|
||||
- 'drm_for_each_legacy_plane'
|
||||
- 'drm_for_each_plane'
|
||||
- 'drm_for_each_plane_mask'
|
||||
- 'drm_for_each_privobj'
|
||||
- 'drm_mm_for_each_hole'
|
||||
- 'drm_mm_for_each_node'
|
||||
- 'drm_mm_for_each_node_in_range'
|
||||
- 'drm_mm_for_each_node_safe'
|
||||
- 'flow_action_for_each'
|
||||
- 'for_each_active_drhd_unit'
|
||||
- 'for_each_active_iommu'
|
||||
- 'for_each_available_child_of_node'
|
||||
- 'for_each_bio'
|
||||
- 'for_each_board_func_rsrc'
|
||||
- 'for_each_bvec'
|
||||
- 'for_each_card_components'
|
||||
- 'for_each_card_links'
|
||||
- 'for_each_card_links_safe'
|
||||
- 'for_each_card_prelinks'
|
||||
- 'for_each_card_rtds'
|
||||
- 'for_each_card_rtds_safe'
|
||||
- 'for_each_cgroup_storage_type'
|
||||
- 'for_each_child_of_node'
|
||||
- 'for_each_clear_bit'
|
||||
- 'for_each_clear_bit_from'
|
||||
- 'for_each_cmsghdr'
|
||||
- 'for_each_compatible_node'
|
||||
- 'for_each_component_dais'
|
||||
- 'for_each_component_dais_safe'
|
||||
- 'for_each_comp_order'
|
||||
- 'for_each_console'
|
||||
- 'for_each_cpu'
|
||||
- 'for_each_cpu_and'
|
||||
- 'for_each_cpu_not'
|
||||
- 'for_each_cpu_wrap'
|
||||
- 'for_each_dev_addr'
|
||||
- 'for_each_dma_cap_mask'
|
||||
- 'for_each_dpcm_be'
|
||||
- 'for_each_dpcm_be_rollback'
|
||||
- 'for_each_dpcm_be_safe'
|
||||
- 'for_each_dpcm_fe'
|
||||
- 'for_each_drhd_unit'
|
||||
- 'for_each_dss_dev'
|
||||
- 'for_each_efi_memory_desc'
|
||||
- 'for_each_efi_memory_desc_in_map'
|
||||
- 'for_each_element'
|
||||
- 'for_each_element_extid'
|
||||
- 'for_each_element_id'
|
||||
- 'for_each_endpoint_of_node'
|
||||
- 'for_each_evictable_lru'
|
||||
- 'for_each_fib6_node_rt_rcu'
|
||||
- 'for_each_fib6_walker_rt'
|
||||
- 'for_each_free_mem_range'
|
||||
- 'for_each_free_mem_range_reverse'
|
||||
- 'for_each_func_rsrc'
|
||||
- 'for_each_hstate'
|
||||
- 'for_each_if'
|
||||
- 'for_each_iommu'
|
||||
- 'for_each_ip_tunnel_rcu'
|
||||
- 'for_each_irq_nr'
|
||||
- 'for_each_link_codecs'
|
||||
- 'for_each_lru'
|
||||
- 'for_each_matching_node'
|
||||
- 'for_each_matching_node_and_match'
|
||||
- 'for_each_memblock'
|
||||
- 'for_each_memblock_type'
|
||||
- 'for_each_memcg_cache_index'
|
||||
- 'for_each_mem_pfn_range'
|
||||
- 'for_each_mem_range'
|
||||
- 'for_each_mem_range_rev'
|
||||
- 'for_each_migratetype_order'
|
||||
- 'for_each_msi_entry'
|
||||
- 'for_each_msi_entry_safe'
|
||||
- 'for_each_net'
|
||||
- 'for_each_netdev'
|
||||
- 'for_each_netdev_continue'
|
||||
- 'for_each_netdev_continue_rcu'
|
||||
- 'for_each_netdev_feature'
|
||||
- 'for_each_netdev_in_bond_rcu'
|
||||
- 'for_each_netdev_rcu'
|
||||
- 'for_each_netdev_reverse'
|
||||
- 'for_each_netdev_safe'
|
||||
- 'for_each_net_rcu'
|
||||
- 'for_each_new_connector_in_state'
|
||||
- 'for_each_new_crtc_in_state'
|
||||
- 'for_each_new_mst_mgr_in_state'
|
||||
- 'for_each_new_plane_in_state'
|
||||
- 'for_each_new_private_obj_in_state'
|
||||
- 'for_each_node'
|
||||
- 'for_each_node_by_name'
|
||||
- 'for_each_node_by_type'
|
||||
- 'for_each_node_mask'
|
||||
- 'for_each_node_state'
|
||||
- 'for_each_node_with_cpus'
|
||||
- 'for_each_node_with_property'
|
||||
- 'for_each_of_allnodes'
|
||||
- 'for_each_of_allnodes_from'
|
||||
- 'for_each_of_cpu_node'
|
||||
- 'for_each_of_pci_range'
|
||||
- 'for_each_old_connector_in_state'
|
||||
- 'for_each_old_crtc_in_state'
|
||||
- 'for_each_old_mst_mgr_in_state'
|
||||
- 'for_each_oldnew_connector_in_state'
|
||||
- 'for_each_oldnew_crtc_in_state'
|
||||
- 'for_each_oldnew_mst_mgr_in_state'
|
||||
- 'for_each_oldnew_plane_in_state'
|
||||
- 'for_each_oldnew_plane_in_state_reverse'
|
||||
- 'for_each_oldnew_private_obj_in_state'
|
||||
- 'for_each_old_plane_in_state'
|
||||
- 'for_each_old_private_obj_in_state'
|
||||
- 'for_each_online_cpu'
|
||||
- 'for_each_online_node'
|
||||
- 'for_each_online_pgdat'
|
||||
- 'for_each_pci_bridge'
|
||||
- 'for_each_pci_dev'
|
||||
- 'for_each_pci_msi_entry'
|
||||
- 'for_each_populated_zone'
|
||||
- 'for_each_possible_cpu'
|
||||
- 'for_each_present_cpu'
|
||||
- 'for_each_prime_number'
|
||||
- 'for_each_prime_number_from'
|
||||
- 'for_each_process'
|
||||
- 'for_each_process_thread'
|
||||
- 'for_each_property_of_node'
|
||||
- 'for_each_registered_fb'
|
||||
- 'for_each_reserved_mem_region'
|
||||
- 'for_each_rtd_codec_dai'
|
||||
- 'for_each_rtd_codec_dai_rollback'
|
||||
- 'for_each_rtdcom'
|
||||
- 'for_each_rtdcom_safe'
|
||||
- 'for_each_set_bit'
|
||||
- 'for_each_set_bit_from'
|
||||
- 'for_each_sg'
|
||||
- 'for_each_sg_dma_page'
|
||||
- 'for_each_sg_page'
|
||||
- 'for_each_sibling_event'
|
||||
- 'for_each_subelement'
|
||||
- 'for_each_subelement_extid'
|
||||
- 'for_each_subelement_id'
|
||||
- '__for_each_thread'
|
||||
- 'for_each_thread'
|
||||
- 'for_each_zone'
|
||||
- 'for_each_zone_zonelist'
|
||||
- 'for_each_zone_zonelist_nodemask'
|
||||
- 'fwnode_for_each_available_child_node'
|
||||
- 'fwnode_for_each_child_node'
|
||||
- 'fwnode_graph_for_each_endpoint'
|
||||
- 'gadget_for_each_ep'
|
||||
- 'genradix_for_each'
|
||||
- 'genradix_for_each_from'
|
||||
- 'hash_for_each'
|
||||
- 'hash_for_each_possible'
|
||||
- 'hash_for_each_possible_rcu'
|
||||
- 'hash_for_each_possible_rcu_notrace'
|
||||
- 'hash_for_each_possible_safe'
|
||||
- 'hash_for_each_rcu'
|
||||
- 'hash_for_each_safe'
|
||||
- 'hctx_for_each_ctx'
|
||||
- 'hlist_bl_for_each_entry'
|
||||
- 'hlist_bl_for_each_entry_rcu'
|
||||
- 'hlist_bl_for_each_entry_safe'
|
||||
- 'hlist_for_each'
|
||||
- 'hlist_for_each_entry'
|
||||
- 'hlist_for_each_entry_continue'
|
||||
- 'hlist_for_each_entry_continue_rcu'
|
||||
- 'hlist_for_each_entry_continue_rcu_bh'
|
||||
- 'hlist_for_each_entry_from'
|
||||
- 'hlist_for_each_entry_from_rcu'
|
||||
- 'hlist_for_each_entry_rcu'
|
||||
- 'hlist_for_each_entry_rcu_bh'
|
||||
- 'hlist_for_each_entry_rcu_notrace'
|
||||
- 'hlist_for_each_entry_safe'
|
||||
- '__hlist_for_each_rcu'
|
||||
- 'hlist_for_each_safe'
|
||||
- 'hlist_nulls_for_each_entry'
|
||||
- 'hlist_nulls_for_each_entry_from'
|
||||
- 'hlist_nulls_for_each_entry_rcu'
|
||||
- 'hlist_nulls_for_each_entry_safe'
|
||||
- 'i3c_bus_for_each_i2cdev'
|
||||
- 'i3c_bus_for_each_i3cdev'
|
||||
- 'ide_host_for_each_port'
|
||||
- 'ide_port_for_each_dev'
|
||||
- 'ide_port_for_each_present_dev'
|
||||
- 'idr_for_each_entry'
|
||||
- 'idr_for_each_entry_continue'
|
||||
- 'idr_for_each_entry_ul'
|
||||
- 'inet_bind_bucket_for_each'
|
||||
- 'inet_lhash2_for_each_icsk_rcu'
|
||||
- 'key_for_each'
|
||||
- 'key_for_each_safe'
|
||||
- 'klp_for_each_func'
|
||||
- 'klp_for_each_func_safe'
|
||||
- 'klp_for_each_func_static'
|
||||
- 'klp_for_each_object'
|
||||
- 'klp_for_each_object_safe'
|
||||
- 'klp_for_each_object_static'
|
||||
- 'kvm_for_each_memslot'
|
||||
- 'kvm_for_each_vcpu'
|
||||
- 'list_for_each'
|
||||
- 'list_for_each_codec'
|
||||
- 'list_for_each_codec_safe'
|
||||
- 'list_for_each_entry'
|
||||
- 'list_for_each_entry_continue'
|
||||
- 'list_for_each_entry_continue_rcu'
|
||||
- 'list_for_each_entry_continue_reverse'
|
||||
- 'list_for_each_entry_from'
|
||||
- 'list_for_each_entry_from_rcu'
|
||||
- 'list_for_each_entry_from_reverse'
|
||||
- 'list_for_each_entry_lockless'
|
||||
- 'list_for_each_entry_rcu'
|
||||
- 'list_for_each_entry_reverse'
|
||||
- 'list_for_each_entry_safe'
|
||||
- 'list_for_each_entry_safe_continue'
|
||||
- 'list_for_each_entry_safe_from'
|
||||
- 'list_for_each_entry_safe_reverse'
|
||||
- 'list_for_each_prev'
|
||||
- 'list_for_each_prev_safe'
|
||||
- 'list_for_each_safe'
|
||||
- 'llist_for_each'
|
||||
- 'llist_for_each_entry'
|
||||
- 'llist_for_each_entry_safe'
|
||||
- 'llist_for_each_safe'
|
||||
- 'media_device_for_each_entity'
|
||||
- 'media_device_for_each_intf'
|
||||
- 'media_device_for_each_link'
|
||||
- 'media_device_for_each_pad'
|
||||
- 'mp_bvec_for_each_page'
|
||||
- 'mp_bvec_for_each_segment'
|
||||
- 'nanddev_io_for_each_page'
|
||||
- 'netdev_for_each_lower_dev'
|
||||
- 'netdev_for_each_lower_private'
|
||||
- 'netdev_for_each_lower_private_rcu'
|
||||
- 'netdev_for_each_mc_addr'
|
||||
- 'netdev_for_each_uc_addr'
|
||||
- 'netdev_for_each_upper_dev_rcu'
|
||||
- 'netdev_hw_addr_list_for_each'
|
||||
- 'nft_rule_for_each_expr'
|
||||
- 'nla_for_each_attr'
|
||||
- 'nla_for_each_nested'
|
||||
- 'nlmsg_for_each_attr'
|
||||
- 'nlmsg_for_each_msg'
|
||||
- 'nr_neigh_for_each'
|
||||
- 'nr_neigh_for_each_safe'
|
||||
- 'nr_node_for_each'
|
||||
- 'nr_node_for_each_safe'
|
||||
- 'of_for_each_phandle'
|
||||
- 'of_property_for_each_string'
|
||||
- 'of_property_for_each_u32'
|
||||
- 'pci_bus_for_each_resource'
|
||||
- 'ping_portaddr_for_each_entry'
|
||||
- 'plist_for_each'
|
||||
- 'plist_for_each_continue'
|
||||
- 'plist_for_each_entry'
|
||||
- 'plist_for_each_entry_continue'
|
||||
- 'plist_for_each_entry_safe'
|
||||
- 'plist_for_each_safe'
|
||||
- 'pnp_for_each_card'
|
||||
- 'pnp_for_each_dev'
|
||||
- 'protocol_for_each_card'
|
||||
- 'protocol_for_each_dev'
|
||||
- 'queue_for_each_hw_ctx'
|
||||
- 'radix_tree_for_each_slot'
|
||||
- 'radix_tree_for_each_tagged'
|
||||
- 'rbtree_postorder_for_each_entry_safe'
|
||||
- 'rdma_for_each_port'
|
||||
- 'resource_list_for_each_entry'
|
||||
- 'resource_list_for_each_entry_safe'
|
||||
- 'rhl_for_each_entry_rcu'
|
||||
- 'rhl_for_each_rcu'
|
||||
- 'rht_for_each'
|
||||
- 'rht_for_each_from'
|
||||
- 'rht_for_each_entry'
|
||||
- 'rht_for_each_entry_from'
|
||||
- 'rht_for_each_entry_rcu'
|
||||
- 'rht_for_each_entry_rcu_from'
|
||||
- 'rht_for_each_entry_safe'
|
||||
- 'rht_for_each_rcu'
|
||||
- 'rht_for_each_rcu_from'
|
||||
- '__rq_for_each_bio'
|
||||
- 'rq_for_each_bvec'
|
||||
- 'rq_for_each_segment'
|
||||
- 'scsi_for_each_prot_sg'
|
||||
- 'scsi_for_each_sg'
|
||||
- 'sctp_for_each_hentry'
|
||||
- 'sctp_skb_for_each'
|
||||
- 'shdma_for_each_chan'
|
||||
- '__shost_for_each_device'
|
||||
- 'shost_for_each_device'
|
||||
- 'sk_for_each'
|
||||
- 'sk_for_each_bound'
|
||||
- 'sk_for_each_entry_offset_rcu'
|
||||
- 'sk_for_each_from'
|
||||
- 'sk_for_each_rcu'
|
||||
- 'sk_for_each_safe'
|
||||
- 'sk_nulls_for_each'
|
||||
- 'sk_nulls_for_each_from'
|
||||
- 'sk_nulls_for_each_rcu'
|
||||
- 'snd_array_for_each'
|
||||
- 'snd_pcm_group_for_each_entry'
|
||||
- 'snd_soc_dapm_widget_for_each_path'
|
||||
- 'snd_soc_dapm_widget_for_each_path_safe'
|
||||
- 'snd_soc_dapm_widget_for_each_sink_path'
|
||||
- 'snd_soc_dapm_widget_for_each_source_path'
|
||||
- 'tb_property_for_each'
|
||||
- 'tcf_exts_for_each_action'
|
||||
- 'udp_portaddr_for_each_entry'
|
||||
- 'udp_portaddr_for_each_entry_rcu'
|
||||
- 'usb_hub_for_each_child'
|
||||
- 'v4l2_device_for_each_subdev'
|
||||
- 'v4l2_m2m_for_each_dst_buf'
|
||||
- 'v4l2_m2m_for_each_dst_buf_safe'
|
||||
- 'v4l2_m2m_for_each_src_buf'
|
||||
- 'v4l2_m2m_for_each_src_buf_safe'
|
||||
- 'virtio_device_for_each_vq'
|
||||
- 'xa_for_each'
|
||||
- 'xa_for_each_marked'
|
||||
- 'xa_for_each_start'
|
||||
- 'xas_for_each'
|
||||
- 'xas_for_each_conflict'
|
||||
- 'xas_for_each_marked'
|
||||
- 'zorro_for_each_dev'
|
||||
|
||||
#IncludeBlocks: Preserve # Unknown to clang-format-5.0
|
||||
IncludeCategories:
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
#IndentPPDirectives: None # Unknown to clang-format-5.0
|
||||
IndentWidth: 8
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: Inner
|
||||
#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
|
||||
ObjCBlockIndentWidth: 8
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
|
||||
# Taken from git's rules
|
||||
#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
|
||||
PenaltyBreakBeforeFirstCallParameter: 30
|
||||
PenaltyBreakComment: 10
|
||||
PenaltyBreakFirstLessLess: 0
|
||||
PenaltyBreakString: 10
|
||||
PenaltyExcessCharacter: 100
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
#SortUsingDeclarations: false # Unknown to clang-format-4.0
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
|
||||
#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
|
||||
SpaceBeforeParens: ControlStatements
|
||||
#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp03
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
...
|
||||
17
components/api/lib/cAT/.gitignore
vendored
Executable file
17
components/api/lib/cAT/.gitignore
vendored
Executable file
@@ -0,0 +1,17 @@
|
||||
.vscode
|
||||
lib
|
||||
bin
|
||||
dist
|
||||
build
|
||||
CMakeLists.txt.user
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Testing
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
|
||||
11
components/api/lib/cAT/.travis.yml
Executable file
11
components/api/lib/cAT/.travis.yml
Executable file
@@ -0,0 +1,11 @@
|
||||
language: c
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
|
||||
before_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
|
||||
script: make && make test
|
||||
148
components/api/lib/cAT/CMakeLists.txt
Executable file
148
components/api/lib/cAT/CMakeLists.txt
Executable file
@@ -0,0 +1,148 @@
|
||||
cmake_minimum_required( VERSION 3.0 )
|
||||
|
||||
project( libcat LANGUAGES C )
|
||||
|
||||
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
|
||||
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
|
||||
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
|
||||
|
||||
enable_testing( )
|
||||
|
||||
include_directories( ${PROJECT_SOURCE_DIR}/src )
|
||||
|
||||
file( GLOB SRC_FILES src/*.c )
|
||||
add_library( cat SHARED ${SRC_FILES} )
|
||||
set_target_properties( cat PROPERTIES VERSION 0.11.1 SOVERSION 1 )
|
||||
target_compile_options( cat PRIVATE -Werror -Wall -Wextra -pedantic )
|
||||
|
||||
install( TARGETS cat DESTINATION lib )
|
||||
install( FILES src/cat.h DESTINATION include/cat )
|
||||
|
||||
add_executable( demo example/demo.c )
|
||||
target_link_libraries( demo cat )
|
||||
|
||||
add_executable( basic example/basic.c )
|
||||
target_link_libraries( basic cat )
|
||||
|
||||
add_executable( unsolicited example/unsolicited.c )
|
||||
target_link_libraries( unsolicited cat )
|
||||
|
||||
add_executable( test_parse tests/test_parse.c )
|
||||
target_link_libraries( test_parse cat )
|
||||
add_test( test_parse ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_parse )
|
||||
|
||||
add_executable( test_run tests/test_run.c )
|
||||
target_link_libraries( test_run cat )
|
||||
add_test( test_run ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_run )
|
||||
|
||||
add_executable( test_read tests/test_read.c )
|
||||
target_link_libraries( test_read cat )
|
||||
add_test( test_read ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_read )
|
||||
|
||||
add_executable( test_write tests/test_write.c )
|
||||
target_link_libraries( test_write cat )
|
||||
add_test( test_write ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_write )
|
||||
|
||||
add_executable( test_write_parse tests/test_write_parse.c )
|
||||
target_link_libraries( test_write_parse cat )
|
||||
add_test( test_write_parse ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_write_parse )
|
||||
|
||||
add_executable( test_write_int_range tests/test_write_int_range.c )
|
||||
target_link_libraries( test_write_int_range cat )
|
||||
add_test( test_write_int_range ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_write_int_range )
|
||||
|
||||
add_executable( test_write_uint_range tests/test_write_uint_range.c )
|
||||
target_link_libraries( test_write_uint_range cat )
|
||||
add_test( test_write_uint_range ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_write_uint_range )
|
||||
|
||||
add_executable( test_write_hex_range tests/test_write_hex_range.c )
|
||||
target_link_libraries( test_write_hex_range cat )
|
||||
add_test( test_write_hex_range ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_write_hex_range )
|
||||
|
||||
add_executable( test_write_hex_buffer tests/test_write_hex_buffer.c )
|
||||
target_link_libraries( test_write_hex_buffer cat )
|
||||
add_test( test_write_hex_buffer ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_write_hex_buffer )
|
||||
|
||||
add_executable( test_write_string_buffer tests/test_write_string_buffer.c )
|
||||
target_link_libraries( test_write_string_buffer cat )
|
||||
add_test( test_write_string_buffer ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_write_string_buffer )
|
||||
|
||||
add_executable( test_read_args tests/test_read_args.c )
|
||||
target_link_libraries( test_read_args cat )
|
||||
add_test( test_read_args ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_read_args )
|
||||
|
||||
add_executable( test_test tests/test_test.c )
|
||||
target_link_libraries( test_test cat )
|
||||
add_test( test_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_test )
|
||||
|
||||
add_executable( test_test_args tests/test_test_args.c )
|
||||
target_link_libraries( test_test_args cat )
|
||||
add_test( test_test_args ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_test_args )
|
||||
|
||||
add_executable( test_mutex tests/test_mutex.c )
|
||||
target_link_libraries( test_mutex cat )
|
||||
add_test( test_mutex ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_mutex )
|
||||
|
||||
add_executable( test_unsolicited_read tests/test_unsolicited_read.c )
|
||||
target_link_libraries( test_unsolicited_read cat )
|
||||
add_test( test_unsolicited_read ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_unsolicited_read )
|
||||
|
||||
add_executable( test_unsolicited_read_stress tests/test_unsolicited_read_stress.c )
|
||||
target_link_libraries( test_unsolicited_read_stress cat )
|
||||
add_test( test_unsolicited_read_stress ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_unsolicited_read_stress )
|
||||
|
||||
add_executable( test_unsolicited_read_buffer tests/test_unsolicited_read_buffer.c ${SRC_FILES})
|
||||
set_target_properties( test_unsolicited_read_buffer PROPERTIES COMPILE_DEFINITIONS "CAT_UNSOLICITED_CMD_BUFFER_SIZE=2" )
|
||||
add_test( test_unsolicited_read_buffer ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_unsolicited_read_buffer )
|
||||
|
||||
add_executable( test_hold_state tests/test_hold_state.c )
|
||||
target_link_libraries( test_hold_state cat )
|
||||
add_test( test_hold_state ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_hold_state )
|
||||
|
||||
add_executable( test_return_read tests/test_return_read.c )
|
||||
target_link_libraries( test_return_read cat )
|
||||
add_test( test_return_read ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_return_read )
|
||||
|
||||
add_executable( test_return_write tests/test_return_write.c )
|
||||
target_link_libraries( test_return_write cat )
|
||||
add_test( test_return_write ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_return_write )
|
||||
|
||||
add_executable( test_unsolicited_test tests/test_unsolicited_test.c )
|
||||
target_link_libraries( test_unsolicited_test cat )
|
||||
add_test( test_unsolicited_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_unsolicited_test )
|
||||
|
||||
add_executable( test_return_test tests/test_return_test.c )
|
||||
target_link_libraries( test_return_test cat )
|
||||
add_test( test_return_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_return_test )
|
||||
|
||||
add_executable( test_return_run tests/test_return_run.c )
|
||||
target_link_libraries( test_return_run cat )
|
||||
add_test( test_return_run ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_return_run )
|
||||
|
||||
add_executable( test_test_only tests/test_test_only.c )
|
||||
target_link_libraries( test_test_only cat )
|
||||
add_test( test_test_only ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_test_only )
|
||||
|
||||
add_executable( test_search_cmd tests/test_search_cmd.c )
|
||||
target_link_libraries( test_search_cmd cat )
|
||||
add_test( test_search_cmd ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_search_cmd )
|
||||
|
||||
add_executable( test_order tests/test_order.c )
|
||||
target_link_libraries( test_order cat )
|
||||
add_test( test_order ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_order )
|
||||
|
||||
add_executable( test_cmd_list tests/test_cmd_list.c )
|
||||
target_link_libraries( test_cmd_list cat )
|
||||
add_test( test_cmd_list ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_cmd_list )
|
||||
|
||||
add_executable( test_var_access tests/test_var_access.c )
|
||||
target_link_libraries( test_var_access cat )
|
||||
add_test( test_var_access ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_var_access )
|
||||
|
||||
add_executable( test_shortcuts tests/test_shortcuts.c )
|
||||
target_link_libraries( test_shortcuts cat )
|
||||
add_test( test_shortcuts ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_shortcuts )
|
||||
|
||||
add_custom_target( check COMMAND ${CMAKE_CTEST_COMMAND} --verbose )
|
||||
add_custom_target( cleanall COMMAND rm -rf Makefile CMakeCache.txt CMakeFiles/ bin/ lib/ cmake_install.cmake CTestTestfile.cmake Testing/ )
|
||||
add_custom_target( uninstall COMMAND xargs rm < install_manifest.txt )
|
||||
21
components/api/lib/cAT/LICENSE
Executable file
21
components/api/lib/cAT/LICENSE
Executable file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
211
components/api/lib/cAT/README.md
Executable file
211
components/api/lib/cAT/README.md
Executable file
@@ -0,0 +1,211 @@
|
||||
[](https://travis-ci.org/marcinbor85/cat)
|
||||
# libcat (cAT)
|
||||
Plain C library for parsing AT commands for use in host devices.
|
||||
|
||||
## Features
|
||||
* blazing fast, non-blocking, robust implementation
|
||||
* 100% static implementation (without any dynamic memory allocation)
|
||||
* very small footprint (both RAM and ROM)
|
||||
* support for READ, WRITE, TEST and RUN type commands
|
||||
* commands shortcuts (auto select best command candidate)
|
||||
* single request - multiple responses
|
||||
* unsolicited read/test command support
|
||||
* hold state for delayed responses for time-consuming tasks
|
||||
* high-level memory variables mapping arguments parsing
|
||||
* variables accessors (read and write, read only, write only)
|
||||
* automatic arguments types validating
|
||||
* automatic format test responses for commands with variables
|
||||
* CRLF and LF compatible
|
||||
* case-insensitive
|
||||
* dedicated for embedded systems
|
||||
* object-oriented architecture
|
||||
* separated interface for low-level layer
|
||||
* fully asynchronous input/output operations
|
||||
* multiplatform and portable
|
||||
* asynchronous api with event callbacks
|
||||
* print registered commands list feature
|
||||
* only two source files
|
||||
* wide unit tests
|
||||
|
||||
## Build
|
||||
|
||||
Build and install:
|
||||
|
||||
```sh
|
||||
cmake .
|
||||
make
|
||||
make test
|
||||
sudo make install
|
||||
```
|
||||
|
||||
## Example basic demo posibilities
|
||||
|
||||
```console
|
||||
AT+PRINT=? # TEST command
|
||||
+PRINT=<X:UINT8[RW]>,<Y:UINT8[RW]>,<MESSAGE:STRING[RW]> # Automatic response
|
||||
Printing something special at (X,Y). # Automatic response
|
||||
OK # Automatic acknowledge
|
||||
|
||||
AT+PRINT? # READ command
|
||||
+PRINT=0,0,"" # Automatic response
|
||||
OK # Automatic acknowledge
|
||||
|
||||
AT+PRINT=xyz,-2 # WRITE command
|
||||
ERROR # Automatic acknowledge
|
||||
|
||||
AT+PRINT=1,2,"test" # WRITE command
|
||||
OK # Automatic acknowledge
|
||||
|
||||
AT+PRINT # RUN command
|
||||
some printing at (1,2) with text "test" # Manual response
|
||||
OK # Automatic acknowledge
|
||||
```
|
||||
|
||||
## Example unsolicited demo posibilities
|
||||
|
||||
```console
|
||||
AT+START=? # TEST command
|
||||
+START=<MODE:UINT32[WO]> # Automatic response
|
||||
Start scanning after write (0 - wifi, 1 - bluetooth). # Automatic response
|
||||
OK # Automatic acknowledge
|
||||
|
||||
AT+START=0 # WRITE command
|
||||
+SCAN=-10,"wifi1" # Unsolicited read response
|
||||
+SCAN=-50,"wifi2" # Unsolicited read response
|
||||
+SCAN=-20,"wifi3" # Unsolicited read response
|
||||
OK # Unsolicited acknowledge
|
||||
|
||||
AT+START=1 # WRITE command
|
||||
+SCAN=-20,"bluetooth1" # Unsolicited read response
|
||||
OK # Unsolicited acknowledge
|
||||
|
||||
AT+SCAN=? # TEST command
|
||||
+SCAN=<RSSI:INT32[RO]>,<SSID:STRING[RO]> # Automatic response
|
||||
Scan result record. # Automatic response
|
||||
OK # Automatic acknowledge
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Define High-Level variables:
|
||||
|
||||
```c
|
||||
|
||||
static uint8_t x;
|
||||
static uint8_t y;
|
||||
static char msg[32];
|
||||
|
||||
static struct cat_variable go_vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC, /* unsigned int variable */
|
||||
.data = &x,
|
||||
.data_size = sizeof(x),
|
||||
.write = x_write,
|
||||
.name = "X",
|
||||
.access = CAT_VAR_ACCESS_READ_WRITE,
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC, /* unsigned int variable */
|
||||
.data = &y,
|
||||
.data_size = sizeof(y),
|
||||
.write = y_write,
|
||||
.access = CAT_VAR_ACCESS_READ_WRITE,
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_STRING, /* string variable */
|
||||
.data = msg,
|
||||
.data_size = sizeof(msg),
|
||||
.write = msg_write,
|
||||
.access = CAT_VAR_ACCESS_READ_WRITE,
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Define AT commands descriptor:
|
||||
|
||||
```c
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "TEST",
|
||||
.read = test_read, /* read handler for ATTEST? command */
|
||||
.write = test_write, /* write handler for ATTEST={val} command */
|
||||
.run = test_run /* run handler for ATTEST command */
|
||||
},
|
||||
{
|
||||
.name = "+NUM",
|
||||
.write = num_write, /* write handler for AT+NUM={val} command */
|
||||
.read = num_read /* read handler for AT+NUM? command */
|
||||
},
|
||||
{
|
||||
.name = "+GO",
|
||||
.write = go_write, /* write handler for AT+GO={x},{y},{msg} command */
|
||||
.var = go_vars, /* attach variables to command */
|
||||
.var_num = sizeof(go_vars) / sizeof(go_vars[0]),
|
||||
.need_all_vars = true
|
||||
},
|
||||
{
|
||||
.name = "RESTART",
|
||||
.run = restart_run /* run handler for ATRESTART command */
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Define AT command parser descriptor:
|
||||
|
||||
```c
|
||||
|
||||
static char working_buf[128]; /* working buffer, must be declared manually */
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = working_buf,
|
||||
.buf_size = sizeof(working_buf),
|
||||
};
|
||||
```
|
||||
|
||||
Define IO low-level layer interface:
|
||||
|
||||
```c
|
||||
static int write_char(char ch)
|
||||
{
|
||||
putc(ch, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
*ch = getch();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
```
|
||||
|
||||
Initialize AT command parser and run:
|
||||
|
||||
```c
|
||||
struct cat_object at; /* at command parser object */
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL); /* initialize at command parser object */
|
||||
|
||||
while (1) {
|
||||
cat_service(&at) /* periodically call at command parser service */
|
||||
|
||||
... /* other stuff, running in main loop */
|
||||
}
|
||||
|
||||
```
|
||||
70
components/api/lib/cAT/changelog.txt
Executable file
70
components/api/lib/cAT/changelog.txt
Executable file
@@ -0,0 +1,70 @@
|
||||
TODO:
|
||||
- differentation of variables for read and write commands
|
||||
- help command (printing all commands posibilities with descriptions)
|
||||
- documentation updated (buffer sized, return enum types, write variable nums, buf size hints)
|
||||
- helper setters and getters for variables
|
||||
|
||||
0.11.0
|
||||
* optional context in commands and data_getter in variables
|
||||
* optional extended read and write variable handler with parent command
|
||||
|
||||
0.10.1
|
||||
* single working buffer insteads of two separated for atcmd and unsolicited events
|
||||
|
||||
0.10.0
|
||||
* separate atcmd and unsolicited event state machines
|
||||
|
||||
0.9.0
|
||||
* variables accessors
|
||||
|
||||
0.8.1
|
||||
* fix commands shourtcuts
|
||||
|
||||
0.8.0
|
||||
* print commands list feature
|
||||
|
||||
0.7.1
|
||||
* more flexible command group initialization (pointers)
|
||||
|
||||
0.7.0
|
||||
* function for checking unsolicited buffer
|
||||
* some refactoring regarding unsolicited buffer
|
||||
* helper function cat_search_variable_by_name added
|
||||
* commands group with searching feature added
|
||||
* disable feature for commands and groups added
|
||||
|
||||
0.6.0
|
||||
* async non blocking io->write
|
||||
* async unsolicited read/test event (injected at idle and hold state)
|
||||
* hold commands parse processing feature (for delayed unsolicited read responses)
|
||||
* behavior differentation by callbacks return values
|
||||
* only-test flag in commands descriptor (for fast disable read/write/run)
|
||||
* helper function for searching command by name
|
||||
* multiple responses triggered by single request pattern support
|
||||
* generic mutex descriptor interface
|
||||
* return value states enum types
|
||||
|
||||
0.5.3
|
||||
* function for checking internal busy state added
|
||||
|
||||
0.5.2
|
||||
* small fix in auto description response
|
||||
|
||||
0.5.1
|
||||
* description field in command added (used in auto help message)
|
||||
|
||||
0.5.0
|
||||
* test command parser with auto help messages
|
||||
* output string end-line encoding same as input string
|
||||
* very basic demo example application added
|
||||
|
||||
0.4.0
|
||||
* high level parsing for command arguments
|
||||
* int, uint, hex, hexbuf, string argument types
|
||||
* validating arguments values range
|
||||
|
||||
0.3.0
|
||||
* independent buffers (parsing buffer and state buffer)
|
||||
|
||||
0.2.0
|
||||
* passing command struct instead of command name in command handlers
|
||||
161
components/api/lib/cAT/example/basic.c
Executable file
161
components/api/lib/cAT/example/basic.c
Executable file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
/* variables assigned to print command */
|
||||
static uint8_t x;
|
||||
static uint8_t y;
|
||||
static char message[16];
|
||||
|
||||
/* helper variable used to exit demo code */
|
||||
static bool quit_flag;
|
||||
|
||||
/* run command handler with application dependent login print code */
|
||||
static int print_run(const struct cat_command *cmd)
|
||||
{
|
||||
printf("some printing at (%d,%d) with text \"%s\"\n", x, y, message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* run command handler attached to HELP command for printing commands list */
|
||||
static int print_cmd_list(const struct cat_command *cmd)
|
||||
{
|
||||
return CAT_RETURN_STATE_PRINT_CMD_LIST_OK;
|
||||
}
|
||||
|
||||
/* run command handler with custom exit mechanism */
|
||||
static int quit_run(const struct cat_command *cmd)
|
||||
{
|
||||
quit_flag = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* declaring print variables array */
|
||||
static struct cat_variable print_vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &x,
|
||||
.data_size = sizeof(x),
|
||||
.name = "X",
|
||||
.access = CAT_VAR_ACCESS_READ_WRITE,
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &y,
|
||||
.data_size = sizeof(y),
|
||||
.name = "Y",
|
||||
.access = CAT_VAR_ACCESS_READ_WRITE,
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_STRING,
|
||||
.data = message,
|
||||
.data_size = sizeof(message),
|
||||
.name = "MESSAGE",
|
||||
.access = CAT_VAR_ACCESS_READ_WRITE,
|
||||
}
|
||||
};
|
||||
|
||||
/* declaring commands array */
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+PRINT",
|
||||
.description = "Printing something special at (X,Y).",
|
||||
.run = print_run,
|
||||
.var = print_vars,
|
||||
.var_num = sizeof(print_vars) / sizeof(print_vars[0]),
|
||||
.need_all_vars = true
|
||||
},
|
||||
{
|
||||
.name = "#HELP",
|
||||
.run = print_cmd_list,
|
||||
},
|
||||
{
|
||||
.name = "#QUIT",
|
||||
.run = quit_run
|
||||
},
|
||||
};
|
||||
|
||||
/* working buffer */
|
||||
static char buf[128];
|
||||
|
||||
/* declaring parser descriptor */
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
/* custom target dependent input output handlers */
|
||||
static int write_char(char ch)
|
||||
{
|
||||
putc(ch, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
*ch = getc(stdin);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* declaring input output interface descriptor for parser */
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
/* initializing */
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
/* main loop with exit code conditions */
|
||||
while ((cat_service(&at) != 0) && (quit_flag == 0)) {};
|
||||
|
||||
/* goodbye message */
|
||||
printf("Bye!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
260
components/api/lib/cAT/example/demo.c
Executable file
260
components/api/lib/cAT/example/demo.c
Executable file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static int32_t speed;
|
||||
static uint16_t adr;
|
||||
static uint8_t x;
|
||||
static uint8_t y;
|
||||
static uint8_t bytes_buf[4];
|
||||
static char msg[16];
|
||||
static bool quit_flag;
|
||||
|
||||
static int x_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
printf("x variable updated internally to: %u\n", x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int y_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
printf("y variable updated internally to: %u\n", y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msg_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
printf("msg variable updated %lu bytes internally to: <%s>\n", write_size, msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int speed_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
printf("speed variable updated internally to: %d\n", speed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adr_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
printf("adr variable updated internally to: 0x%04X\n", adr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bytesbuf_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
printf("bytes_buf variable updated %lu bytes internally to: ", write_size);
|
||||
for (i = 0; i < sizeof(bytes_buf); i++)
|
||||
printf("%02X", bytes_buf[i]);
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int go_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
printf("<%s>: x=%d y=%d msg=%s @ speed=%d\n",
|
||||
cmd->name,
|
||||
*(uint8_t*)(cmd->var[0].data),
|
||||
*(uint8_t*)(cmd->var[1].data),
|
||||
msg,
|
||||
speed
|
||||
);
|
||||
|
||||
printf("<bytes>: ");
|
||||
for (i = 0; i < sizeof(bytes_buf); i++)
|
||||
printf("%02X", bytes_buf[i]);
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
printf("<%s>: SET SPEED TO = %d\n",
|
||||
cmd->name,
|
||||
speed
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_run(const struct cat_command *cmd)
|
||||
{
|
||||
printf("TEST: <%s>", cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int quit_run(const struct cat_command *cmd)
|
||||
{
|
||||
printf("QUIT: <%s>", cmd->name);
|
||||
quit_flag = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_cmd_list(const struct cat_command *cmd)
|
||||
{
|
||||
return CAT_RETURN_STATE_PRINT_CMD_LIST_OK;
|
||||
}
|
||||
|
||||
static struct cat_variable go_vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &x,
|
||||
.data_size = sizeof(x),
|
||||
.write = x_write,
|
||||
.name = "x"
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &y,
|
||||
.data_size = sizeof(y),
|
||||
.write = y_write,
|
||||
.name = "y"
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_STRING,
|
||||
.data = msg,
|
||||
.data_size = sizeof(msg),
|
||||
.write = msg_write,
|
||||
.name = "msg"
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable set_vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &speed,
|
||||
.data_size = sizeof(speed),
|
||||
.write = speed_write,
|
||||
.name = "speed"
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &adr,
|
||||
.data_size = sizeof(adr),
|
||||
.write = adr_write,
|
||||
.name = "address"
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_HEX,
|
||||
.data = &bytes_buf,
|
||||
.data_size = sizeof(bytes_buf),
|
||||
.write = bytesbuf_write,
|
||||
.name = "buffer"
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+GO",
|
||||
.write = go_write,
|
||||
.var = go_vars,
|
||||
.var_num = sizeof(go_vars) / sizeof(go_vars[0]),
|
||||
.need_all_vars = true
|
||||
},
|
||||
{
|
||||
.name = "+SET",
|
||||
.write = set_write,
|
||||
.read = set_read,
|
||||
.var = set_vars,
|
||||
.var_num = sizeof(set_vars) / sizeof(set_vars[0]),
|
||||
},
|
||||
{
|
||||
.name = "#TEST",
|
||||
.run = test_run
|
||||
},
|
||||
{
|
||||
.name = "#HELP",
|
||||
.run = print_cmd_list,
|
||||
},
|
||||
{
|
||||
.name = "#QUIT",
|
||||
.run = quit_run
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
putc(ch, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
*ch = getc(stdin);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
while ((cat_service(&at) != 0) && (quit_flag == 0)) {};
|
||||
|
||||
printf("Bye!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
251
components/api/lib/cAT/example/unsolicited.c
Executable file
251
components/api/lib/cAT/example/unsolicited.c
Executable file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
/* variables assigned to scan command */
|
||||
static int rssi;
|
||||
static char ssid[16];
|
||||
|
||||
/* helper variable used to exit demo code */
|
||||
static bool quit_flag;
|
||||
|
||||
/* variables assigned to start command */
|
||||
static int mode;
|
||||
|
||||
/* main at command parser object */
|
||||
struct cat_object at;
|
||||
|
||||
struct scan_results {
|
||||
int rssi;
|
||||
char ssid[16];
|
||||
};
|
||||
|
||||
/* static const scan results */
|
||||
static const struct scan_results results[2][3] = {
|
||||
{
|
||||
{
|
||||
.rssi = -10,
|
||||
.ssid = "wifi1",
|
||||
},
|
||||
{
|
||||
.rssi = -50,
|
||||
.ssid = "wifi2",
|
||||
},
|
||||
{
|
||||
.rssi = -20,
|
||||
.ssid = "wifi3",
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
.rssi = -20,
|
||||
.ssid = "bluetooth1",
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* helper variable */
|
||||
static int scan_index;
|
||||
|
||||
/* run command handler with custom exit mechanism */
|
||||
static int quit_run(const struct cat_command *cmd)
|
||||
{
|
||||
quit_flag = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* helper function */
|
||||
static void load_scan_results(int index)
|
||||
{
|
||||
rssi = results[mode][index].rssi;
|
||||
strcpy(ssid, results[mode][index].ssid);
|
||||
}
|
||||
|
||||
/* declaring scan variables array */
|
||||
static struct cat_variable scan_vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &rssi,
|
||||
.data_size = sizeof(rssi),
|
||||
.name = "RSSI"
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_STRING,
|
||||
.data = ssid,
|
||||
.data_size = sizeof(ssid),
|
||||
.name = "SSID"
|
||||
}
|
||||
};
|
||||
|
||||
/* forward declaration */
|
||||
static cat_return_state scan_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size);
|
||||
|
||||
/* unsolicited command */
|
||||
static struct cat_command scan_cmd = {
|
||||
.name = "+SCAN",
|
||||
.read = scan_read,
|
||||
.var = scan_vars,
|
||||
.var_num = sizeof(scan_vars) / sizeof(scan_vars[0])
|
||||
};
|
||||
|
||||
/* unsolicited read callback handler */
|
||||
static cat_return_state scan_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
int max = (mode == 0) ? 3 : 1;
|
||||
|
||||
scan_index++;
|
||||
if (scan_index > max)
|
||||
return CAT_RETURN_STATE_HOLD_EXIT_OK;
|
||||
|
||||
load_scan_results(scan_index);
|
||||
cat_trigger_unsolicited_read(&at, &scan_cmd);
|
||||
|
||||
return CAT_RETURN_STATE_DATA_NEXT;
|
||||
}
|
||||
|
||||
/* mode variable validator */
|
||||
static int mode_write(const struct cat_variable *var, const size_t write_size)
|
||||
{
|
||||
if (*(int*)var->data >= 2)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* start write callback handler */
|
||||
static cat_return_state start_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
scan_index = 0;
|
||||
|
||||
load_scan_results(scan_index);
|
||||
cat_trigger_unsolicited_read(&at, &scan_cmd);
|
||||
|
||||
return CAT_RETURN_STATE_HOLD;
|
||||
}
|
||||
|
||||
/* run command handler attached to HELP command for printing commands list */
|
||||
static int print_cmd_list(const struct cat_command *cmd)
|
||||
{
|
||||
return CAT_RETURN_STATE_PRINT_CMD_LIST_OK;
|
||||
}
|
||||
|
||||
/* declaring start command variables array */
|
||||
static struct cat_variable start_vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &mode,
|
||||
.data_size = sizeof(mode),
|
||||
.name = "MODE",
|
||||
.write = mode_write,
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY,
|
||||
}
|
||||
};
|
||||
|
||||
/* declaring commands array */
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+START",
|
||||
.description = "Start scanning after write (0 - wifi, 1 - bluetooth).",
|
||||
.write = start_write,
|
||||
.var = start_vars,
|
||||
.var_num = sizeof(start_vars) / sizeof(start_vars[0]),
|
||||
.need_all_vars = true
|
||||
},
|
||||
{
|
||||
.name = "+SCAN",
|
||||
.description = "Scan result record.",
|
||||
.only_test = true,
|
||||
.var = scan_vars,
|
||||
.var_num = sizeof(scan_vars) / sizeof(scan_vars[0])
|
||||
},
|
||||
{
|
||||
.name = "#HELP",
|
||||
.run = print_cmd_list,
|
||||
},
|
||||
{
|
||||
.name = "#QUIT",
|
||||
.run = quit_run
|
||||
},
|
||||
};
|
||||
|
||||
/* working buffer */
|
||||
static char buf[128];
|
||||
|
||||
/* declaring parser descriptor */
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
/* custom target dependent input output handlers */
|
||||
static int write_char(char ch)
|
||||
{
|
||||
putc(ch, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
*ch = getc(stdin);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* declaring input output interface descriptor for parser */
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* initializing */
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
/* main loop with exit code conditions */
|
||||
while ((cat_service(&at) != 0) && (quit_flag == 0)) {};
|
||||
|
||||
/* goodbye message */
|
||||
printf("Bye!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
2757
components/api/lib/cAT/src/cat.c
Executable file
2757
components/api/lib/cAT/src/cat.c
Executable file
File diff suppressed because it is too large
Load Diff
557
components/api/lib/cAT/src/cat.h
Executable file
557
components/api/lib/cAT/src/cat.h
Executable file
@@ -0,0 +1,557 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef CAT_H
|
||||
#define CAT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* only forward declarations (looks for definition below) */
|
||||
struct cat_command;
|
||||
struct cat_variable;
|
||||
|
||||
#ifndef CAT_UNSOLICITED_CMD_BUFFER_SIZE
|
||||
/* unsolicited command buffer default size (can by override externally during compilation) */
|
||||
#define CAT_UNSOLICITED_CMD_BUFFER_SIZE ((size_t)(1))
|
||||
#endif
|
||||
|
||||
/* enum type with variable type definitions */
|
||||
typedef enum {
|
||||
CAT_VAR_INT_DEC = 0, /* decimal encoded signed integer variable */
|
||||
CAT_VAR_UINT_DEC, /* decimal encoded unsigned integer variable */
|
||||
CAT_VAR_NUM_HEX, /* hexadecimal encoded unsigned integer variable */
|
||||
CAT_VAR_BUF_HEX, /* asciihex encoded bytes array */
|
||||
CAT_VAR_BUF_STRING /* string variable */
|
||||
} cat_var_type;
|
||||
|
||||
/* enum type wirh variable accessors definitions */
|
||||
typedef enum {
|
||||
CAT_VAR_ACCESS_READ_WRITE = 0, /* there will be possible to read and write variable */
|
||||
CAT_VAR_ACCESS_READ_ONLY, /* there will be possible to read only variable */
|
||||
CAT_VAR_ACCESS_WRITE_ONLY, /* there will be possible to write only variable */
|
||||
} cat_var_access;
|
||||
|
||||
/* enum type with function status */
|
||||
typedef enum {
|
||||
CAT_STATUS_ERROR_BUFFER_EMPTY = -7,
|
||||
CAT_STATUS_ERROR_NOT_HOLD = -6,
|
||||
CAT_STATUS_ERROR_BUFFER_FULL = -5,
|
||||
CAT_STATUS_ERROR_UNKNOWN_STATE = -4,
|
||||
CAT_STATUS_ERROR_MUTEX_LOCK = -3,
|
||||
CAT_STATUS_ERROR_MUTEX_UNLOCK = -2,
|
||||
CAT_STATUS_ERROR = -1,
|
||||
CAT_STATUS_OK = 0,
|
||||
CAT_STATUS_BUSY = 1,
|
||||
CAT_STATUS_HOLD = 2
|
||||
} cat_status;
|
||||
|
||||
/**
|
||||
* Write variable function handler
|
||||
*
|
||||
* This callback function is called after variable update immediatly.
|
||||
* User application can validate writed value and check for amount of data size was written.
|
||||
* This handler is optional, so when is not defined, operations will be fully automatically.
|
||||
*
|
||||
* @param var - pointer to struct descriptor of parsed variable
|
||||
* @param write_size - size of data was written (useful especially with hexbuf var type)
|
||||
* @return 0 - ok, else error and stop parsing
|
||||
* */
|
||||
typedef int (*cat_var_write_handler)(const struct cat_variable *var, const size_t write_size);
|
||||
|
||||
/**
|
||||
* Read variable function handler
|
||||
*
|
||||
* This callback function is called just before variable value read.
|
||||
* User application can copy data from private fields to variable connected with parsed command.
|
||||
* This handler is optional, so when is not defined, operations will be fully automatically.
|
||||
*
|
||||
* @param var - pointer to struct descriptor of parsed variable
|
||||
* @return 0 - ok, else error and stop parsing
|
||||
* */
|
||||
typedef int (*cat_var_read_handler)(const struct cat_variable *var);
|
||||
|
||||
/**
|
||||
* Write variable extended function handler
|
||||
*
|
||||
* This callback function is called after variable update immediatly.
|
||||
* User application can validate writed value and check for amount of data size was written.
|
||||
* This handler is optional, so when is not defined, operations will be fully automatically.
|
||||
*
|
||||
* @param var - pointer to struct descriptor of parsed variable
|
||||
* @param cmd - pointer to variable parent command structure
|
||||
* @param write_size - size of data was written (useful especially with hexbuf var type)
|
||||
* @return 0 - ok, else error and stop parsing
|
||||
* */
|
||||
typedef int (*cat_var_write_ex_handler)(const struct cat_variable *var, const struct cat_command *cmd, const size_t write_size);
|
||||
|
||||
/**
|
||||
* Read variable function handler
|
||||
*
|
||||
* This callback function is called just before variable value read.
|
||||
* User application can copy data from private fields to variable connected with parsed command.
|
||||
* This handler is optional, so when is not defined, operations will be fully automatically.
|
||||
*
|
||||
* @param var - pointer to struct descriptor of parsed variable
|
||||
* @param cmd - pointer to variable parent command structure
|
||||
* @return 0 - ok, else error and stop parsing
|
||||
* */
|
||||
typedef int (*cat_var_read_ex_handler)(const struct cat_variable *var, const struct cat_command *cmd);
|
||||
|
||||
/**
|
||||
* Data getter for variable.
|
||||
* The purpose of this function is to replace statically allocated data and data_size fields
|
||||
* with function pointer with context. Then the data and data_size from this getter would be
|
||||
* changed and returned runtime.
|
||||
*
|
||||
* @param var - pointer to struct descriptor of parsed variable
|
||||
* @param context - command context
|
||||
* @param size - pointer to variable where should be placed data size
|
||||
* @return pointer to data array from context
|
||||
*/
|
||||
typedef void* (*cat_var_data_getter)(const struct cat_variable *var, void *context, size_t *data_size);
|
||||
|
||||
struct cat_variable {
|
||||
const char *name; /* variable name (optional - using only for auto format test command response) */
|
||||
cat_var_type type; /* variable type (needed for parsing and validating) */
|
||||
void *data; /* generic pointer to statically allocated memory for variable data read/write/validate operations */
|
||||
size_t data_size; /* variable data size, pointed by data pointer */
|
||||
cat_var_access access; /* variable accessor */
|
||||
|
||||
cat_var_write_handler write; /* write variable handler */
|
||||
cat_var_read_handler read; /* read variable handler */
|
||||
cat_var_write_ex_handler write_ex; /* optional write variable extended handler */
|
||||
cat_var_read_ex_handler read_ex; /* optional read variable extended handler */
|
||||
|
||||
cat_var_data_getter data_getter; /* optional data getter for dynamic linking data and data_size */
|
||||
};
|
||||
|
||||
/* enum type with command callbacks return values meaning */
|
||||
typedef enum {
|
||||
CAT_RETURN_STATE_ERROR = -1, /* immediatly error acknowledge */
|
||||
CAT_RETURN_STATE_DATA_OK, /* send current data buffer followed by ok acknowledge */
|
||||
CAT_RETURN_STATE_DATA_NEXT, /* send current data buffer and go to next callback iteration */
|
||||
CAT_RETURN_STATE_NEXT, /* go to next callback iteration without sending anything */
|
||||
CAT_RETURN_STATE_OK, /* immediatly ok acknowledge */
|
||||
CAT_RETURN_STATE_HOLD, /* enable hold parser state */
|
||||
CAT_RETURN_STATE_HOLD_EXIT_OK, /* exit from hold state with OK response */
|
||||
CAT_RETURN_STATE_HOLD_EXIT_ERROR, /* exit from hold state with ERROR response */
|
||||
CAT_RETURN_STATE_PRINT_CMD_LIST_OK, /* print commands list followed by ok acknowledge (only in TEST and RUN) */
|
||||
} cat_return_state;
|
||||
|
||||
/**
|
||||
* Write command function handler (AT+CMD=)
|
||||
*
|
||||
* This callback function is called after parsing all connected variables.
|
||||
* User application can validate all variales at once at this moment, or copy them to the other application layer buffer.
|
||||
* User can check number of variables or make custom process of parsing non standard arguments format.
|
||||
* This handler is optional, so when is not defined, operations on variables will be fully automatically.
|
||||
* If neither write handler nor variables not defined, then write command type is not available.
|
||||
*
|
||||
* @param cmd - pointer to struct descriptor of processed command
|
||||
* @param data - pointer to arguments buffer for custom parsing
|
||||
* @param data_size - length of arguments buffer
|
||||
* @param args_num - number of passed arguments connected to variables
|
||||
* @return according to cat_return_state enum definitions
|
||||
* */
|
||||
typedef cat_return_state (*cat_cmd_write_handler)(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num);
|
||||
|
||||
/**
|
||||
* Read command function handler (AT+CMD?)
|
||||
*
|
||||
* This callback function is called after format all connected variables.
|
||||
* User application can change automatic response, or add some custom data to response.
|
||||
* This handler is optional, so when is not defined, operations on variables will be fully automatically.
|
||||
* If neither read handler nor variables not defined, then read command type is not available.
|
||||
*
|
||||
* @param cmd - pointer to struct descriptor of processed command
|
||||
* @param data - pointer to arguments buffer for custom parsing
|
||||
* @param data_size - pointer to length of arguments buffer (can be modifed if needed)
|
||||
* @param max_data_size - maximum length of buffer pointed by data pointer
|
||||
* @return according to cat_return_state enum definitions
|
||||
* */
|
||||
typedef cat_return_state (*cat_cmd_read_handler)(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size);
|
||||
|
||||
/**
|
||||
* Run command function handler (AT+CMD)
|
||||
*
|
||||
* No operations on variables are done.
|
||||
* This handler is optional.
|
||||
* If run handler not defined, then run command type is not available.
|
||||
*
|
||||
* @param cmd - pointer to struct descriptor of processed command
|
||||
* @return according to cat_return_state enum definitions
|
||||
* */
|
||||
typedef cat_return_state (*cat_cmd_run_handler)(const struct cat_command *cmd);
|
||||
|
||||
/**
|
||||
* Test command function handler (AT+CMD=?)
|
||||
*
|
||||
* This callback function is called after format all connected variables.
|
||||
* User application can change automatic response, or add some custom data to response.
|
||||
* This handler is optional, so when is not defined, operations on variables will be fully automatically.
|
||||
* If neither test handler nor variables not defined, then test command type is not available.
|
||||
* Exception of this rule is write command without variables.
|
||||
* In this case, the "question mark" will be passed as a custom argument to the write handler.
|
||||
*
|
||||
* @param cmd - pointer to struct descriptor of processed command
|
||||
* @param data - pointer to arguments buffer for custom parsing
|
||||
* @param data_size - pointer to length of arguments buffer (can be modifed if needed)
|
||||
* @param max_data_size - maximum length of buffer pointed by data pointer
|
||||
* @return according to cat_return_state enum definitions
|
||||
* */
|
||||
typedef cat_return_state (*cat_cmd_test_handler)(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size);
|
||||
|
||||
/* enum type with main at parser fsm state */
|
||||
typedef enum {
|
||||
CAT_STATE_ERROR = -1,
|
||||
CAT_STATE_IDLE,
|
||||
CAT_STATE_PARSE_PREFIX,
|
||||
CAT_STATE_PARSE_COMMAND_CHAR,
|
||||
CAT_STATE_UPDATE_COMMAND_STATE,
|
||||
CAT_STATE_WAIT_READ_ACKNOWLEDGE,
|
||||
CAT_STATE_SEARCH_COMMAND,
|
||||
CAT_STATE_COMMAND_FOUND,
|
||||
CAT_STATE_COMMAND_NOT_FOUND,
|
||||
CAT_STATE_PARSE_COMMAND_ARGS,
|
||||
CAT_STATE_PARSE_WRITE_ARGS,
|
||||
CAT_STATE_FORMAT_READ_ARGS,
|
||||
CAT_STATE_WAIT_TEST_ACKNOWLEDGE,
|
||||
CAT_STATE_FORMAT_TEST_ARGS,
|
||||
CAT_STATE_WRITE_LOOP,
|
||||
CAT_STATE_READ_LOOP,
|
||||
CAT_STATE_TEST_LOOP,
|
||||
CAT_STATE_RUN_LOOP,
|
||||
CAT_STATE_HOLD,
|
||||
CAT_STATE_FLUSH_IO_WRITE_WAIT,
|
||||
CAT_STATE_FLUSH_IO_WRITE,
|
||||
CAT_STATE_AFTER_FLUSH_RESET,
|
||||
CAT_STATE_AFTER_FLUSH_OK,
|
||||
CAT_STATE_AFTER_FLUSH_FORMAT_READ_ARGS,
|
||||
CAT_STATE_AFTER_FLUSH_FORMAT_TEST_ARGS,
|
||||
CAT_STATE_PRINT_CMD,
|
||||
} cat_state;
|
||||
|
||||
/* enum type with type of command request */
|
||||
typedef enum {
|
||||
CAT_CMD_TYPE_NONE = -1,
|
||||
CAT_CMD_TYPE_RUN,
|
||||
CAT_CMD_TYPE_READ,
|
||||
CAT_CMD_TYPE_WRITE,
|
||||
CAT_CMD_TYPE_TEST,
|
||||
CAT_CMD_TYPE__TOTAL_NUM
|
||||
} cat_cmd_type;
|
||||
|
||||
/* structure with io interface functions */
|
||||
struct cat_io_interface {
|
||||
int (*write)(char ch); /* write char to output stream. return 1 if byte wrote successfully. */
|
||||
int (*read)(char *ch); /* read char from input stream. return 1 if byte read successfully. */
|
||||
};
|
||||
|
||||
/* structure with mutex interface functions */
|
||||
struct cat_mutex_interface {
|
||||
int (*lock)(void); /* lock mutex handler. return 0 if successfully locked, otherwise - cannot lock */
|
||||
int (*unlock)(void); /* unlock mutex handler. return 0 if successfully unlocked, otherwise - cannot unlock */
|
||||
};
|
||||
|
||||
/* structure with at command descriptor */
|
||||
struct cat_command {
|
||||
const char *name; /* at command name (case-insensitivity) */
|
||||
const char *description; /* at command description (optionally - can be null) */
|
||||
|
||||
cat_cmd_write_handler write; /* write command handler */
|
||||
cat_cmd_read_handler read; /* read command handler */
|
||||
cat_cmd_run_handler run; /* run command handler */
|
||||
cat_cmd_test_handler test; /* test command handler */
|
||||
|
||||
struct cat_variable const *var; /* pointer to array of variables assiocated with this command */
|
||||
size_t var_num; /* number of variables in array */
|
||||
|
||||
bool need_all_vars; /* flag to need all vars parsing */
|
||||
bool only_test; /* flag to disable read/write/run commands (only test auto description) */
|
||||
bool disable; /* flag to completely disable command */
|
||||
|
||||
void* context; /* pointer to optional context structure */
|
||||
};
|
||||
|
||||
struct cat_command_group {
|
||||
const char *name; /* command group name (optional, for identification purpose) */
|
||||
|
||||
struct cat_command const *cmd; /* pointer to array of commands descriptor */
|
||||
size_t cmd_num; /* number of commands in array */
|
||||
|
||||
bool disable; /* flag to completely disable all commands in group */
|
||||
};
|
||||
|
||||
/* structure with at command parser descriptor */
|
||||
struct cat_descriptor {
|
||||
struct cat_command_group* const *cmd_group; /* pointer to array of commands group descriptor */
|
||||
size_t cmd_group_num; /* number of commands group in array */
|
||||
|
||||
uint8_t *buf; /* pointer to working buffer (used to parse command argument) */
|
||||
size_t buf_size; /* working buffer length */
|
||||
|
||||
/* optional unsolicited buffer, if not configured (NULL) */
|
||||
/* then the buf will be divided into two smaller buffers */
|
||||
uint8_t *unsolicited_buf; /* pointer to unsolicited working buffer (used to parse command argument) */
|
||||
size_t unsolicited_buf_size; /* unsolicited working buffer length */
|
||||
};
|
||||
|
||||
/* strcuture with unsolicited command buffered infos */
|
||||
struct cat_unsolicited_cmd {
|
||||
struct cat_command const *cmd; /* pointer to commands used to unsolicited event */
|
||||
cat_cmd_type type; /* type of unsolicited event */
|
||||
};
|
||||
|
||||
/* enum type with unsolicited events fsm state */
|
||||
typedef enum {
|
||||
CAT_UNSOLICITED_STATE_IDLE,
|
||||
CAT_UNSOLICITED_STATE_FORMAT_READ_ARGS,
|
||||
CAT_UNSOLICITED_STATE_FORMAT_TEST_ARGS,
|
||||
CAT_UNSOLICITED_STATE_READ_LOOP,
|
||||
CAT_UNSOLICITED_STATE_TEST_LOOP,
|
||||
CAT_UNSOLICITED_STATE_FLUSH_IO_WRITE_WAIT,
|
||||
CAT_UNSOLICITED_STATE_FLUSH_IO_WRITE,
|
||||
CAT_UNSOLICITED_STATE_AFTER_FLUSH_RESET,
|
||||
CAT_UNSOLICITED_STATE_AFTER_FLUSH_OK,
|
||||
CAT_UNSOLICITED_STATE_AFTER_FLUSH_FORMAT_READ_ARGS,
|
||||
CAT_UNSOLICITED_STATE_AFTER_FLUSH_FORMAT_TEST_ARGS,
|
||||
} cat_unsolicited_state;
|
||||
|
||||
/* enum type with fsm type */
|
||||
typedef enum {
|
||||
CAT_FSM_TYPE_ATCMD,
|
||||
CAT_FSM_TYPE_UNSOLICITED,
|
||||
CAT_FSM_TYPE__TOTAL_NUM,
|
||||
} cat_fsm_type;
|
||||
|
||||
struct cat_unsolicited_fsm {
|
||||
cat_unsolicited_state state; /* current unsolicited fsm state */
|
||||
|
||||
size_t index; /* index used to iterate over commands and variables */
|
||||
size_t position; /* position of actually parsed char in arguments string */
|
||||
|
||||
struct cat_command const *cmd; /* pointer to current command descriptor */
|
||||
struct cat_variable const *var; /* pointer to current variable descriptor */
|
||||
cat_cmd_type cmd_type; /* type of command request */
|
||||
|
||||
char const *write_buf; /* working buffer pointer used for asynch writing to io */
|
||||
int write_state; /* before, data, after flush io write state */
|
||||
cat_unsolicited_state write_state_after; /* parser state to set after flush io write */
|
||||
|
||||
struct cat_unsolicited_cmd unsolicited_cmd_buffer[CAT_UNSOLICITED_CMD_BUFFER_SIZE]; /* buffer with unsolicited commands used to unsolicited event */
|
||||
size_t unsolicited_cmd_buffer_tail; /* tail index of unsolicited cmd buffer */
|
||||
size_t unsolicited_cmd_buffer_head; /* head index of unsolicited cmd buffer */
|
||||
size_t unsolicited_cmd_buffer_items_count; /* number of unsolicited cmd in buffer */
|
||||
};
|
||||
|
||||
/* structure with main at command parser object */
|
||||
struct cat_object {
|
||||
struct cat_descriptor const *desc; /* pointer to at command parser descriptor */
|
||||
struct cat_io_interface const *io; /* pointer to at command parser io interface */
|
||||
struct cat_mutex_interface const *mutex; /* pointer to at command parser mutex interface */
|
||||
|
||||
size_t index; /* index used to iterate over commands and variables */
|
||||
size_t partial_cntr; /* partial match commands counter */
|
||||
size_t length; /* length of input command name and command arguments */
|
||||
size_t position; /* position of actually parsed char in arguments string */
|
||||
size_t write_size; /* size of parsed buffer hex or buffer string */
|
||||
size_t commands_num; /* computed total number of registered commands */
|
||||
|
||||
struct cat_command const *cmd; /* pointer to current command descriptor */
|
||||
struct cat_variable const *var; /* pointer to current variable descriptor */
|
||||
cat_cmd_type cmd_type; /* type of command request */
|
||||
|
||||
char current_char; /* current received char from input stream */
|
||||
cat_state state; /* current fsm state */
|
||||
bool cr_flag; /* flag for detect <cr> char in input string */
|
||||
bool hold_state_flag; /* status of hold state (independent from fsm states) */
|
||||
int hold_exit_status; /* hold exit parameter with status */
|
||||
char const *write_buf; /* working buffer pointer used for asynch writing to io */
|
||||
int write_state; /* before, data, after flush io write state */
|
||||
cat_state write_state_after; /* parser state to set after flush io write */
|
||||
|
||||
struct cat_unsolicited_fsm unsolicited_fsm;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function used to initialize at command parser.
|
||||
* Initialize starting values of object fields.
|
||||
*
|
||||
* @param self pointer to at command parser object to initialize
|
||||
* @param desc pointer to at command parser descriptor
|
||||
* @param io pointer to at command parser io low-level layer interface
|
||||
* @param mutex pointer to at command partes mutex interface
|
||||
*/
|
||||
void cat_init(struct cat_object *self, const struct cat_descriptor *desc, const struct cat_io_interface *io, const struct cat_mutex_interface *mutex);
|
||||
|
||||
/**
|
||||
* Function must be called periodically to asynchronoulsy run at command parser.
|
||||
* Commands handlers will be call from this function context.
|
||||
*
|
||||
* @param self pointer to at command parser object
|
||||
* @return according to cat_return_state enum definitions
|
||||
*/
|
||||
cat_status cat_service(struct cat_object *self);
|
||||
|
||||
/**
|
||||
* Function return flag which indicating internal busy state.
|
||||
* It is used to determine whether external application modules can use shared input / output interfaces functions.
|
||||
* It is usefull especially in rtos environments.
|
||||
* If internal parser state is busy by doing some processing then function return 1.
|
||||
* If the function returns 0, then the external application modules can safely use the input / output interfaces functions shared with the library.
|
||||
* If the function returns 1, then input / output interface function are used by internal parser functions.
|
||||
*
|
||||
* @param self pointer to at command parser object
|
||||
* @return according to cat_return_state enum definitions
|
||||
*/
|
||||
cat_status cat_is_busy(struct cat_object *self);
|
||||
|
||||
/**
|
||||
* Function return flag which indicating parsing hold state.
|
||||
* If the function returns 0, then the at parsing process is normal.
|
||||
* If the function returns 1, then the at parsing process is holded.
|
||||
* To exit from hold state, user have to call cat_hold_exit or return HOLD_EXIT return value in callback.
|
||||
*
|
||||
* @param self pointer to at command parser object
|
||||
* @return according to cat_return_state enum definitions
|
||||
*/
|
||||
cat_status cat_is_hold(struct cat_object *self);
|
||||
|
||||
/**
|
||||
* Function return flag which indicating state of internal buffer of unsolicited events.
|
||||
*
|
||||
* @param self pointer to at command parser object
|
||||
* @return CAT_STATUS_OK - buffer is not full, unsolicited event can be buffered
|
||||
* CAT_STATUS_ERROR_BUFFER_FULL - buffer is full, unsolicited event cannot be buffered
|
||||
* CAT_STATUS_ERROR_MUTEX_LOCK - cannot lock mutex error
|
||||
* CAT_STATUS_ERROR_MUTEX_UNLOCK - cannot unlock mutex error
|
||||
*/
|
||||
cat_status cat_is_unsolicited_buffer_full(struct cat_object *self);
|
||||
|
||||
/**
|
||||
* Function sends unsolicited event message.
|
||||
* Command message is buffered inside parser in 1-level deep buffer and processed in cat_service context.
|
||||
* Only command pointer is buffered, so command struct should be static or global until be fully processed.
|
||||
*
|
||||
* @param self pointer to at command parser object
|
||||
* @param cmd pointer to command structure regarding which unsolicited event applies to
|
||||
* @param type type of operation (only CAT_CMD_TYPE_READ and CAT_CMD_TYPE_TEST are allowed)
|
||||
* @return according to cat_return_state enum definitions
|
||||
*/
|
||||
cat_status cat_trigger_unsolicited_event(struct cat_object *self, struct cat_command const *cmd, cat_cmd_type type);
|
||||
|
||||
/**
|
||||
* Function sends unsolicited read event message.
|
||||
* Command message is buffered inside parser in 1-level deep buffer and processed in cat_service context.
|
||||
* Only command pointer is buffered, so command struct should be static or global until be fully processed.
|
||||
*
|
||||
* @param self pointer to at command parser object
|
||||
* @param cmd pointer to command structure regarding which unsolicited read applies to
|
||||
* @return according to cat_return_state enum definitions
|
||||
*/
|
||||
cat_status cat_trigger_unsolicited_read(struct cat_object *self, struct cat_command const *cmd);
|
||||
|
||||
/**
|
||||
* Function sends unsolicited test event message.
|
||||
* Command message is buffered inside parser in 1-level deep buffer and processed in cat_service context.
|
||||
* Only command pointer is buffered, so command struct should be static or global until be fully processed.
|
||||
*
|
||||
* @param self pointer to at command parser object
|
||||
* @param cmd pointer to command structure regarding which unsolicited test applies to
|
||||
* @return according to cat_return_state enum definitions
|
||||
*/
|
||||
cat_status cat_trigger_unsolicited_test(struct cat_object *self, struct cat_command const *cmd);
|
||||
|
||||
/**
|
||||
* Function used to exit from hold state with OK/ERROR response and back to idle state.
|
||||
*
|
||||
* @param self pointer to at command parser object
|
||||
* @param status response status 0 - OK, else ERROR
|
||||
* @return according to cat_return_state enum definitions
|
||||
*/
|
||||
cat_status cat_hold_exit(struct cat_object *self, cat_status status);
|
||||
|
||||
/**
|
||||
* Function used to searching registered command by its name.
|
||||
*
|
||||
* @param self pointer to at command parser object
|
||||
* @param name command name to search
|
||||
* @return pointer to command object, NULL if command not found
|
||||
*/
|
||||
struct cat_command const* cat_search_command_by_name(struct cat_object *self, const char *name);
|
||||
|
||||
/**
|
||||
* Function used to searching registered command group by its name.
|
||||
*
|
||||
* @param self pointer to at command parser object
|
||||
* @param name command group name to search
|
||||
* @return pointer to command group object, NULL if command group not found
|
||||
*/
|
||||
struct cat_command_group const* cat_search_command_group_by_name(struct cat_object *self, const char *name);
|
||||
|
||||
/**
|
||||
* Function used to searching attached variable to command its name.
|
||||
*
|
||||
* @param self pointer to at command parser object
|
||||
* @param cmd pointer to command in which variable will be searched
|
||||
* @param name variable name to search
|
||||
* @return pointer to command group object, NULL if command group not found
|
||||
*/
|
||||
struct cat_variable const* cat_search_variable_by_name(struct cat_object *self, struct cat_command const *cmd, const char *name);
|
||||
|
||||
/**
|
||||
* Function used to check what command is currently processed.
|
||||
* Function is not protected by mutex mechanism, due to processed cmd may change after function return.
|
||||
* This only matters in multithreaded environments, it does not matter for one thread.
|
||||
*
|
||||
* @param self pointer to at command parser object
|
||||
* @param fsm type of internal state machine to check current command
|
||||
* @return pointer to command which is currently processed, NULL if no command is processed
|
||||
*/
|
||||
struct cat_command const* cat_get_processed_command(struct cat_object *self, cat_fsm_type fsm);
|
||||
|
||||
/**
|
||||
* Function return unsolicited event command status.
|
||||
* Function is not protected by mutex mechanism, due to processed cmd may change after function return.
|
||||
* This only matters in multithreaded environments, it does not matter for one thread.
|
||||
*
|
||||
* @param self pointer to at command parser object
|
||||
* @param cmd pointer to command in which variable will be searched
|
||||
* @param type type of unsolicited event
|
||||
* @return CAT_STATUS_OK - command is not buffered nor processed
|
||||
* CAT_STATUS_BUSY - command is waiting in buffer or is processed
|
||||
*/
|
||||
cat_status cat_is_unsolicited_event_buffered(struct cat_object *self, struct cat_command const *cmd, cat_cmd_type type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CAT_H */
|
||||
340
components/api/lib/cAT/tests/test_cmd_list.c
Executable file
340
components/api/lib/cAT/tests/test_cmd_list.c
Executable file
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char ack_results[512];
|
||||
|
||||
static int8_t var1;
|
||||
static int8_t var2;
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int cmd_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_test(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_run(const struct cat_command *cmd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var1_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var2_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_cmd_list(const struct cat_command *cmd)
|
||||
{
|
||||
return CAT_RETURN_STATE_PRINT_CMD_LIST_OK;
|
||||
}
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var1,
|
||||
.data_size = sizeof(var1),
|
||||
.write = var1_write
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars_ro[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var1,
|
||||
.data_size = sizeof(var1),
|
||||
.write = var1_write,
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars_wo[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var1,
|
||||
.data_size = sizeof(var1),
|
||||
.write = var1_write,
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars2[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var1,
|
||||
.data_size = sizeof(var1),
|
||||
.write = var1_write
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var2,
|
||||
.data_size = sizeof(var2),
|
||||
.write = var2_write
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars2_ro[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var1,
|
||||
.data_size = sizeof(var1),
|
||||
.write = var1_write,
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var2,
|
||||
.data_size = sizeof(var2),
|
||||
.write = var2_write
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars2_wo[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var1,
|
||||
.data_size = sizeof(var1),
|
||||
.write = var1_write,
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var2,
|
||||
.data_size = sizeof(var2),
|
||||
.write = var2_write
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+V1",
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
},
|
||||
{
|
||||
.name = "+V1RO",
|
||||
.var = vars_ro,
|
||||
.var_num = sizeof(vars_ro) / sizeof(vars_ro[0])
|
||||
},
|
||||
{
|
||||
.name = "+V1RW",
|
||||
.var = vars_wo,
|
||||
.var_num = sizeof(vars_wo) / sizeof(vars_wo[0])
|
||||
},
|
||||
{
|
||||
.name = "+V11",
|
||||
.var = vars2,
|
||||
.var_num = sizeof(vars2) / sizeof(vars2[0])
|
||||
},
|
||||
{
|
||||
.name = "+V11RO",
|
||||
.var = vars2_ro,
|
||||
.var_num = sizeof(vars2_ro) / sizeof(vars2_ro[0])
|
||||
},
|
||||
{
|
||||
.name = "+V11WO",
|
||||
.var = vars2_wo,
|
||||
.var_num = sizeof(vars2_wo) / sizeof(vars2_wo[0])
|
||||
},
|
||||
{
|
||||
.name = "+V2",
|
||||
.write = cmd_write,
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
},
|
||||
{
|
||||
.name = "+V3",
|
||||
.write = cmd_write,
|
||||
.read = cmd_read,
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
},
|
||||
{
|
||||
.name = "+V4",
|
||||
.write = cmd_write,
|
||||
.read = cmd_read,
|
||||
.test = cmd_test,
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
},
|
||||
{
|
||||
.name = "+V5",
|
||||
.write = cmd_write,
|
||||
.read = cmd_read,
|
||||
.test = cmd_test,
|
||||
.run = cmd_run,
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
},
|
||||
{
|
||||
.name = "+S1",
|
||||
},
|
||||
{
|
||||
.name = "+S2",
|
||||
.write = cmd_write,
|
||||
},
|
||||
{
|
||||
.name = "+S3",
|
||||
.write = cmd_write,
|
||||
.read = cmd_read,
|
||||
},
|
||||
{
|
||||
.name = "+S4",
|
||||
.write = cmd_write,
|
||||
.read = cmd_read,
|
||||
.test = cmd_test,
|
||||
},
|
||||
{
|
||||
.name = "+S5",
|
||||
.write = cmd_write,
|
||||
.read = cmd_read,
|
||||
.test = cmd_test,
|
||||
.run = cmd_run,
|
||||
},
|
||||
{
|
||||
.name = "+D1",
|
||||
.write = cmd_write,
|
||||
.read = cmd_read,
|
||||
.test = cmd_test,
|
||||
.run = cmd_run,
|
||||
.disable = true,
|
||||
},
|
||||
{
|
||||
.name = "+T1",
|
||||
.write = cmd_write,
|
||||
.read = cmd_read,
|
||||
.test = cmd_test,
|
||||
.run = cmd_run,
|
||||
.only_test = true,
|
||||
},
|
||||
{
|
||||
.name = "+T2",
|
||||
.only_test = true,
|
||||
},
|
||||
{
|
||||
.name = "#HELP",
|
||||
.run = print_cmd_list,
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[512];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
}
|
||||
|
||||
static void print_raw_text(char *p)
|
||||
{
|
||||
while (*p != '\0') {
|
||||
if (*p == '\n') {
|
||||
printf("\\n");
|
||||
} else {
|
||||
putchar(*p);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input("\nAT#HELP\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nAT+V1?\nAT+V1=\nAT+V1=?\n\nAT+V1RO?\nAT+V1RO=?\n\nAT+V1RW=\nAT+V1RW=?\n\nAT+V11?\nAT+V11=\nAT+V11=?\n\nAT+V11RO?\nAT+V11RO=\nAT+V11RO=?\n\nAT+V11WO?\nAT+V11WO=\nAT+V11WO=?\n\nAT+V2?\nAT+V2=\nAT+V2=?\n\nAT+V3?\nAT+V3=\nAT+V3=?\n\nAT+V4?\nAT+V4=\nAT+V4=?\n\nAT+V5\nAT+V5?\nAT+V5=\nAT+V5=?\n\nAT+S2=\n\nAT+S3?\nAT+S3=\n\nAT+S4?\nAT+S4=\nAT+S4=?\n\nAT+S5\nAT+S5?\nAT+S5=\nAT+S5=?\n\nAT+T1=?\n\nAT#HELP\n\nOK\n") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
229
components/api/lib/cAT/tests/test_hold_state.c
Executable file
229
components/api/lib/cAT/tests/test_hold_state.c
Executable file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char cmd_results[256];
|
||||
static char var_read_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int var_x, var_u1, var_u2;
|
||||
static struct cat_object at;
|
||||
|
||||
static struct cat_command u_cmds[];
|
||||
|
||||
static cat_return_state cmd_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
strcat(cmd_results, " write:");
|
||||
strcat(cmd_results, cmd->name);
|
||||
|
||||
if (var_x < 2) {
|
||||
s = cat_trigger_unsolicited_read(&at, &u_cmds[var_x]);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
|
||||
return CAT_RETURN_STATE_HOLD;
|
||||
}
|
||||
|
||||
return CAT_RETURN_STATE_ERROR;
|
||||
}
|
||||
|
||||
static cat_return_state cmd1_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
strcat(cmd_results, " read1:");
|
||||
strcat(cmd_results, cmd->name);
|
||||
|
||||
if (var_u1 > 0) {
|
||||
var_u1--;
|
||||
s = cat_trigger_unsolicited_read(&at, cmd);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
return CAT_RETURN_STATE_DATA_OK;
|
||||
}
|
||||
|
||||
return CAT_RETURN_STATE_HOLD_EXIT_OK;
|
||||
}
|
||||
|
||||
static cat_return_state cmd2_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
strcat(cmd_results, " read2:");
|
||||
strcat(cmd_results, cmd->name);
|
||||
|
||||
if (var_u2 > 0) {
|
||||
var_u2--;
|
||||
s = cat_trigger_unsolicited_read(&at, cmd);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
return CAT_RETURN_STATE_DATA_OK;
|
||||
}
|
||||
|
||||
cat_hold_exit(&at, CAT_STATUS_OK);
|
||||
return CAT_RETURN_STATE_DATA_OK;
|
||||
}
|
||||
|
||||
static int var_read(const struct cat_variable *var)
|
||||
{
|
||||
strcat(var_read_results, " var_read:");
|
||||
strcat(var_read_results, var->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_variable u_vars[] = {
|
||||
{
|
||||
.name = "U1",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_u1,
|
||||
.data_size = sizeof(var_u1),
|
||||
.read = var_read
|
||||
},
|
||||
{
|
||||
.name = "U2",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_u2,
|
||||
.data_size = sizeof(var_u2),
|
||||
.read = var_read
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.name = "X",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_x,
|
||||
.data_size = sizeof(var_x),
|
||||
.read = var_read
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+CMD",
|
||||
.write = cmd_write,
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0]),
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command u_cmds[] = {
|
||||
{
|
||||
.name = "+U1CMD",
|
||||
.read = cmd1_read,
|
||||
.var = &u_vars[0],
|
||||
.var_num = 1,
|
||||
},
|
||||
{
|
||||
.name = "+U2CMD",
|
||||
.read = cmd2_read,
|
||||
.var = &u_vars[1],
|
||||
.var_num = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
var_u1 = 2;
|
||||
var_u2 = 3;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(cmd_results, 0, sizeof(cmd_results));
|
||||
memset(var_read_results, 0, sizeof(var_read_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+CMD=0\n\nAT+CMD=1\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+U1CMD=2\n\n+U1CMD=1\n\nOK\n\n+U2CMD=3\n\n+U2CMD=2\n\n+U2CMD=1\n\n+U2CMD=0\n\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " write:+CMD read1:+U1CMD read1:+U1CMD read1:+U1CMD write:+CMD read2:+U2CMD read2:+U2CMD read2:+U2CMD read2:+U2CMD") == 0);
|
||||
assert(strcmp(var_read_results, " var_read:U1 var_read:U1 var_read:U1 var_read:U2 var_read:U2 var_read:U2 var_read:U2") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
185
components/api/lib/cAT/tests/test_mutex.c
Executable file
185
components/api/lib/cAT/tests/test_mutex.c
Executable file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char run_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int a_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " A:");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ap_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " AP:");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " +TEST:");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "A",
|
||||
.run = a_run
|
||||
},
|
||||
{
|
||||
.name = "AP",
|
||||
.run = ap_run
|
||||
},
|
||||
{
|
||||
.name = "+TEST",
|
||||
.run = test_run
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static int mutex_ret_lock;
|
||||
static int mutex_ret_unlock;
|
||||
|
||||
static int mutex_lock(void)
|
||||
{
|
||||
return mutex_ret_lock;
|
||||
}
|
||||
|
||||
static int mutex_unlock(void)
|
||||
{
|
||||
return mutex_ret_unlock;
|
||||
}
|
||||
|
||||
static struct cat_mutex_interface mutex = {
|
||||
.lock = mutex_lock,
|
||||
.unlock = mutex_unlock
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
mutex_ret_lock = 0;
|
||||
mutex_ret_unlock = 0;
|
||||
|
||||
memset(run_results, 0, sizeof(run_results));
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT\nAT+test\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, &mutex);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n\nOK\n") == 0);
|
||||
assert(strcmp(run_results, " +TEST:+TEST") == 0);
|
||||
|
||||
mutex_ret_lock = 1;
|
||||
mutex_ret_unlock = 0;
|
||||
assert(cat_service(&at) == CAT_STATUS_ERROR_MUTEX_LOCK);
|
||||
|
||||
mutex_ret_lock = 0;
|
||||
mutex_ret_unlock = 1;
|
||||
assert(cat_service(&at) == CAT_STATUS_ERROR_MUTEX_UNLOCK);
|
||||
|
||||
mutex_ret_lock = 1;
|
||||
mutex_ret_unlock = 0;
|
||||
assert(cat_is_busy(&at) == CAT_STATUS_ERROR_MUTEX_LOCK);
|
||||
|
||||
mutex_ret_lock = 0;
|
||||
mutex_ret_unlock = 1;
|
||||
assert(cat_is_busy(&at) == CAT_STATUS_ERROR_MUTEX_UNLOCK);
|
||||
|
||||
mutex_ret_lock = 0;
|
||||
mutex_ret_unlock = 0;
|
||||
assert(cat_service(&at) == CAT_STATUS_OK);
|
||||
assert(cat_is_busy(&at) == CAT_STATUS_OK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
223
components/api/lib/cAT/tests/test_order.c
Executable file
223
components/api/lib/cAT/tests/test_order.c
Executable file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char run_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int e_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " E:");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int e0_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " E0:");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int e1_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " E1:");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_command cmds1[] = {
|
||||
{
|
||||
.name = "E",
|
||||
.run = e_run,
|
||||
},
|
||||
{
|
||||
.name = "E0",
|
||||
.run = e0_run,
|
||||
},
|
||||
{
|
||||
.name = "E1",
|
||||
.run = e1_run,
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds2[] = {
|
||||
{
|
||||
.name = "E0",
|
||||
.run = e0_run,
|
||||
},
|
||||
{
|
||||
.name = "E1",
|
||||
.run = e1_run,
|
||||
},
|
||||
{
|
||||
.name = "E",
|
||||
.run = e_run,
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds3[] = {
|
||||
{
|
||||
.name = "E0",
|
||||
.run = e0_run,
|
||||
},
|
||||
{
|
||||
.name = "E",
|
||||
.run = e_run,
|
||||
},
|
||||
{
|
||||
.name = "E1",
|
||||
.run = e1_run,
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_1_group = {
|
||||
.cmd = cmds1,
|
||||
.cmd_num = sizeof(cmds1) / sizeof(cmds1[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_1_desc[] = {
|
||||
&cmd_1_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc_1 = {
|
||||
.cmd_group = cmd_1_desc,
|
||||
.cmd_group_num = sizeof(cmd_1_desc) / sizeof(cmd_1_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static struct cat_command_group cmd_2_group = {
|
||||
.cmd = cmds2,
|
||||
.cmd_num = sizeof(cmds2) / sizeof(cmds2[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_2_desc[] = {
|
||||
&cmd_2_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc_2 = {
|
||||
.cmd_group = cmd_2_desc,
|
||||
.cmd_group_num = sizeof(cmd_2_desc) / sizeof(cmd_2_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static struct cat_command_group cmd_3_group = {
|
||||
.cmd = cmds3,
|
||||
.cmd_num = sizeof(cmds3) / sizeof(cmds3[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_3_desc[] = {
|
||||
&cmd_3_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc_3 = {
|
||||
.cmd_group = cmd_3_desc,
|
||||
.cmd_group_num = sizeof(cmd_3_desc) / sizeof(cmd_3_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
memset(run_results, 0, sizeof(run_results));
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nATE\n\nATE0\n\nATE1\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc_1, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n\nOK\n\nOK\n") == 0);
|
||||
assert(strcmp(run_results, " E:E E0:E0 E1:E1") == 0);
|
||||
|
||||
cat_init(&at, &desc_2, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n\nOK\n\nOK\n") == 0);
|
||||
assert(strcmp(run_results, " E:E E0:E0 E1:E1") == 0);
|
||||
|
||||
cat_init(&at, &desc_3, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n\nOK\n\nOK\n") == 0);
|
||||
assert(strcmp(run_results, " E:E E0:E0 E1:E1") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
195
components/api/lib/cAT/tests/test_parse.c
Executable file
195
components/api/lib/cAT/tests/test_parse.c
Executable file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char run_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int a_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " A:");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ap_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " AP:");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " +TEST:");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "A",
|
||||
.run = a_run,
|
||||
.disable = false,
|
||||
},
|
||||
{
|
||||
.name = "AP",
|
||||
.run = ap_run,
|
||||
.disable = false,
|
||||
},
|
||||
{
|
||||
.name = "+TEST",
|
||||
.run = test_run,
|
||||
.disable = false,
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
memset(run_results, 0, sizeof(run_results));
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nsa\rAT\n\r\nAT\nAT+\n\nATA\r\natap\naaaattttap\na\n\r+test\r\n+testATA\nATAPATAP\n\rAT\rATA\nAT+test\r\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\r\nERROR\r\n\nOK\n\nOK\n\r\nOK\r\n\nOK\n\nERROR\n\nERROR\n\r\nERROR\r\n\nERROR\n\nERROR\n\r\nERROR\r\n\r\nOK\r\n") == 0);
|
||||
assert(strcmp(run_results, " +TEST:+TEST A:A AP:AP +TEST:+TEST") == 0);
|
||||
|
||||
prepare_input("\nAT\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(cat_is_busy(&at) == 0);
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(strcmp(run_results, "") == 0);
|
||||
|
||||
prepare_input("\nAT+te");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(cat_is_busy(&at) != 0);
|
||||
assert(strcmp(ack_results, "") == 0);
|
||||
assert(strcmp(run_results, "") == 0);
|
||||
|
||||
prepare_input("st\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(cat_is_busy(&at) == 0);
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(strcmp(run_results, " +TEST:+TEST") == 0);
|
||||
|
||||
struct cat_command *cmd;
|
||||
|
||||
cmd = (struct cat_command*)cat_search_command_by_name(&at, "A");
|
||||
cmd->disable = true;
|
||||
cmd = (struct cat_command*)cat_search_command_by_name(&at, "+TEST");
|
||||
cmd->disable = true;
|
||||
|
||||
prepare_input("\nATA\n\nATAP\n\nAT+TEST\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n\nOK\n\nERROR\n") == 0);
|
||||
assert(strcmp(run_results, " AP:AP AP:AP") == 0);
|
||||
|
||||
struct cat_command_group *cmd_group;
|
||||
cmd_group = (struct cat_command_group*)cat_search_command_group_by_name(&at, "standard");
|
||||
assert(cmd_group == NULL);
|
||||
|
||||
cmd_desc[0]->name = "standard";
|
||||
cmd_group = (struct cat_command_group*)cat_search_command_group_by_name(&at, "standard");
|
||||
assert(cmd_group == cmd_desc[0]);
|
||||
cmd_group->disable = true;
|
||||
|
||||
prepare_input("\nATA\n\nATAP\n\nAT+TEST\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n\nERROR\n\nERROR\n") == 0);
|
||||
assert(strcmp(run_results, "") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
165
components/api/lib/cAT/tests/test_read.c
Executable file
165
components/api/lib/cAT/tests/test_read.c
Executable file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char run_results[256];
|
||||
static char read_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int a_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " A_");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int a_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(read_results, " A:");
|
||||
strcat(read_results, cmd->name);
|
||||
|
||||
snprintf(data, max_data_size, "%s=A-val", cmd->name);
|
||||
*data_size = strlen(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ap_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(read_results, " AP:");
|
||||
strcat(read_results, cmd->name);
|
||||
|
||||
*data_size = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(read_results, " +TEST:");
|
||||
strcat(read_results, cmd->name);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "A",
|
||||
.read = a_read,
|
||||
.run = a_run
|
||||
},
|
||||
{
|
||||
.name = "AP",
|
||||
.read = ap_read
|
||||
},
|
||||
{
|
||||
.name = "+TEST",
|
||||
.read = test_read
|
||||
},
|
||||
{
|
||||
.name = "+EMPTY"
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
memset(run_results, 0, sizeof(run_results));
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(read_results, 0, sizeof(read_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT\r\nAT+\nAT+?\nATA?\r\nATAP\nATAP?\nATAPA?\nAT+TEST?\nAT+te?\nAT+e?\nAT+empTY?\r\nATA\r\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\r\nOK\r\n\nERROR\n\nERROR\n\r\nA=A-val\r\n\r\nOK\r\n\nERROR\n\nAP=\n\nOK\n\nERROR\n\nERROR\n\nERROR\n\nERROR\n\r\nERROR\r\n\r\nOK\r\n") == 0);
|
||||
assert(strcmp(run_results, " A_A") == 0);
|
||||
assert(strcmp(read_results, " A:A AP:AP +TEST:+TEST +TEST:+TEST") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
225
components/api/lib/cAT/tests/test_read_args.c
Executable file
225
components/api/lib/cAT/tests/test_read_args.c
Executable file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char ack_results[256];
|
||||
|
||||
static int8_t var_int;
|
||||
static uint8_t var_uint;
|
||||
static uint8_t var_hex8;
|
||||
static uint16_t var_hex16;
|
||||
static uint32_t var_hex32;
|
||||
static uint8_t var_buf[4];
|
||||
static char var_string[16];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
static int common_cntr;
|
||||
static uint8_t ctx;
|
||||
|
||||
static int cmd_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd2_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
sprintf(data, "%s=test", cmd->name);
|
||||
*data_size = strlen(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int common_var_read_handler(const struct cat_variable *var)
|
||||
{
|
||||
common_cntr++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void* var_int_data_getter(const struct cat_variable *var, void *context, size_t *data_size)
|
||||
{
|
||||
*data_size = sizeof(var_int);
|
||||
assert(context == &ctx);
|
||||
return &var_int;
|
||||
}
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.read = common_var_read_handler,
|
||||
.data_getter = var_int_data_getter,
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint,
|
||||
.data_size = sizeof(var_uint),
|
||||
.read = common_var_read_handler
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex8,
|
||||
.data_size = sizeof(var_hex8),
|
||||
.read = common_var_read_handler
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex16,
|
||||
.data_size = sizeof(var_hex16),
|
||||
.read = common_var_read_handler
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex32,
|
||||
.data_size = sizeof(var_hex32),
|
||||
.read = common_var_read_handler
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_HEX,
|
||||
.data = &var_buf,
|
||||
.data_size = sizeof(var_buf),
|
||||
.read = common_var_read_handler
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_STRING,
|
||||
.data = &var_string,
|
||||
.data_size = sizeof(var_string),
|
||||
.read = common_var_read_handler
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+SET",
|
||||
.read = cmd_read,
|
||||
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0]),
|
||||
.context = &ctx,
|
||||
},
|
||||
{
|
||||
.name = "+TEST",
|
||||
.read = cmd2_read,
|
||||
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0]),
|
||||
.context = &ctx,
|
||||
},
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
var_int = -1;
|
||||
var_uint = 255;
|
||||
var_hex8 = 0xAA;
|
||||
var_hex16 = 0x0123;
|
||||
var_hex32 = 0xFF001234;
|
||||
|
||||
var_buf[0] = 0x12;
|
||||
var_buf[1] = 0x34;
|
||||
var_buf[2] = 0x56;
|
||||
var_buf[3] = 0x78;
|
||||
|
||||
common_cntr = 0;
|
||||
|
||||
sprintf(var_string, "\\\"test\n");
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+SET?\r\n";
|
||||
static const char test_case_2[] = "\nAT+TEST?\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\r\n+SET=-1,255,0xAA,0x0123,0xFF001234,12345678,\"\\\\\\\"test\\n\"\r\n\r\nOK\r\n") == 0);
|
||||
assert(common_cntr == 7);
|
||||
|
||||
prepare_input(test_case_2);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+TEST=test\n\nOK\n") == 0);
|
||||
assert(common_cntr == 7);
|
||||
|
||||
return 0;
|
||||
}
|
||||
206
components/api/lib/cAT/tests/test_return_read.c
Executable file
206
components/api/lib/cAT/tests/test_return_read.c
Executable file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char cmd_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int var_x;
|
||||
static struct cat_object at;
|
||||
|
||||
static cat_return_state ret;
|
||||
static bool ret_error;
|
||||
|
||||
static cat_return_state cmd_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(cmd_results, " read:");
|
||||
strcat(cmd_results, cmd->name);
|
||||
|
||||
if (cat_is_hold(&at) == CAT_STATUS_HOLD) {
|
||||
var_x++;
|
||||
if (var_x > 4) {
|
||||
ret = (ret_error == false) ? CAT_RETURN_STATE_HOLD_EXIT_OK : CAT_RETURN_STATE_HOLD_EXIT_ERROR;
|
||||
} else {
|
||||
if (var_x == 4) {
|
||||
strcpy(data, "test");
|
||||
*data_size = strlen(data);
|
||||
}
|
||||
ret = CAT_RETURN_STATE_DATA_NEXT;
|
||||
}
|
||||
} else {
|
||||
if ((ret == CAT_RETURN_STATE_DATA_NEXT) || (ret == CAT_RETURN_STATE_NEXT)) {
|
||||
var_x++;
|
||||
if (var_x > 2)
|
||||
ret = CAT_RETURN_STATE_DATA_OK;
|
||||
} else if (ret == CAT_RETURN_STATE_HOLD) {
|
||||
cat_trigger_unsolicited_read(&at, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.name = "X",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_x,
|
||||
.data_size = sizeof(var_x)
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+CMD",
|
||||
.read = cmd_read,
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0]),
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
var_x = 1;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(cmd_results, 0, sizeof(cmd_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+CMD?\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
ret = CAT_RETURN_STATE_ERROR;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n") == 0);
|
||||
assert(strcmp(cmd_results, " read:+CMD") == 0);
|
||||
|
||||
ret = CAT_RETURN_STATE_DATA_OK;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=1\n\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " read:+CMD") == 0);
|
||||
|
||||
ret = CAT_RETURN_STATE_DATA_NEXT;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=1\n\n+CMD=2\n\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " read:+CMD read:+CMD") == 0);
|
||||
|
||||
ret = CAT_RETURN_STATE_NEXT;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=2\n\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " read:+CMD read:+CMD") == 0);
|
||||
|
||||
ret = CAT_RETURN_STATE_OK;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " read:+CMD") == 0);
|
||||
|
||||
ret_error = false;
|
||||
ret = CAT_RETURN_STATE_HOLD;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=1\n\n+CMD=2\n\ntest\n\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " read:+CMD read:+CMD read:+CMD read:+CMD read:+CMD") == 0);
|
||||
|
||||
ret_error = true;
|
||||
ret = CAT_RETURN_STATE_HOLD;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=1\n\n+CMD=2\n\ntest\n\nERROR\n") == 0);
|
||||
assert(strcmp(cmd_results, " read:+CMD read:+CMD read:+CMD read:+CMD read:+CMD") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
236
components/api/lib/cAT/tests/test_return_run.c
Executable file
236
components/api/lib/cAT/tests/test_return_run.c
Executable file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char cmd_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int var_x;
|
||||
static struct cat_object at;
|
||||
|
||||
static cat_return_state ret;
|
||||
static bool ret_error;
|
||||
|
||||
static cat_return_state cmd_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(cmd_results, " read:");
|
||||
strcat(cmd_results, cmd->name);
|
||||
|
||||
var_x++;
|
||||
if (var_x > 5) {
|
||||
ret = (ret_error == false) ? CAT_RETURN_STATE_HOLD_EXIT_OK : CAT_RETURN_STATE_HOLD_EXIT_ERROR;
|
||||
} else {
|
||||
if (var_x == 5) {
|
||||
strcpy(data, "test");
|
||||
*data_size = strlen(data);
|
||||
}
|
||||
ret = CAT_RETURN_STATE_DATA_NEXT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static cat_return_state cmd_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(cmd_results, " run:");
|
||||
strcat(cmd_results, cmd->name);
|
||||
|
||||
if ((ret == CAT_RETURN_STATE_DATA_NEXT) || (ret == CAT_RETURN_STATE_NEXT)) {
|
||||
var_x++;
|
||||
if (var_x > 3)
|
||||
ret = CAT_RETURN_STATE_DATA_OK;
|
||||
} else if (ret == CAT_RETURN_STATE_HOLD) {
|
||||
cat_trigger_unsolicited_read(&at, cmd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.name = "X",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_x,
|
||||
.data_size = sizeof(var_x)
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+CMD",
|
||||
.run = cmd_run,
|
||||
.read = cmd_read,
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0]),
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
var_x = 2;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(cmd_results, 0, sizeof(cmd_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+CMD\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
ret = CAT_RETURN_STATE_ERROR;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n") == 0);
|
||||
assert(strcmp(cmd_results, " run:+CMD") == 0);
|
||||
assert(var_x == 2);
|
||||
|
||||
ret = CAT_RETURN_STATE_DATA_OK;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " run:+CMD") == 0);
|
||||
assert(var_x == 2);
|
||||
|
||||
ret = CAT_RETURN_STATE_DATA_NEXT;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " run:+CMD run:+CMD") == 0);
|
||||
assert(var_x == 4);
|
||||
|
||||
ret = CAT_RETURN_STATE_NEXT;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " run:+CMD run:+CMD") == 0);
|
||||
assert(var_x == 4);
|
||||
|
||||
ret = CAT_RETURN_STATE_OK;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " run:+CMD") == 0);
|
||||
assert(var_x == 2);
|
||||
|
||||
ret_error = false;
|
||||
ret = CAT_RETURN_STATE_HOLD;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=2\n\n+CMD=3\n\ntest\n\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " run:+CMD read:+CMD read:+CMD read:+CMD read:+CMD") == 0);
|
||||
assert(var_x == 6);
|
||||
|
||||
ret_error = true;
|
||||
ret = CAT_RETURN_STATE_HOLD;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=2\n\n+CMD=3\n\ntest\n\nERROR\n") == 0);
|
||||
assert(strcmp(cmd_results, " run:+CMD read:+CMD read:+CMD read:+CMD read:+CMD") == 0);
|
||||
assert(var_x == 6);
|
||||
|
||||
ret = CAT_RETURN_STATE_HOLD_EXIT_ERROR;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n") == 0);
|
||||
assert(strcmp(cmd_results, " run:+CMD") == 0);
|
||||
assert(var_x == 2);
|
||||
|
||||
ret = CAT_RETURN_STATE_HOLD_EXIT_OK;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n") == 0);
|
||||
assert(strcmp(cmd_results, " run:+CMD") == 0);
|
||||
assert(var_x == 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
206
components/api/lib/cAT/tests/test_return_test.c
Executable file
206
components/api/lib/cAT/tests/test_return_test.c
Executable file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char cmd_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int var_x;
|
||||
static struct cat_object at;
|
||||
|
||||
static cat_return_state ret;
|
||||
static bool ret_error;
|
||||
|
||||
static cat_return_state cmd_test(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(cmd_results, " test:");
|
||||
strcat(cmd_results, cmd->name);
|
||||
|
||||
if (cat_is_hold(&at) == CAT_STATUS_HOLD) {
|
||||
var_x++;
|
||||
if (var_x > 4) {
|
||||
ret = (ret_error == false) ? CAT_RETURN_STATE_HOLD_EXIT_OK : CAT_RETURN_STATE_HOLD_EXIT_ERROR;
|
||||
} else {
|
||||
if (var_x == 4) {
|
||||
strcpy(data, "test");
|
||||
*data_size = strlen(data);
|
||||
}
|
||||
ret = CAT_RETURN_STATE_DATA_NEXT;
|
||||
}
|
||||
} else {
|
||||
if ((ret == CAT_RETURN_STATE_DATA_NEXT) || (ret == CAT_RETURN_STATE_NEXT)) {
|
||||
var_x++;
|
||||
if (var_x > 2)
|
||||
ret = CAT_RETURN_STATE_DATA_OK;
|
||||
} else if (ret == CAT_RETURN_STATE_HOLD) {
|
||||
cat_trigger_unsolicited_test(&at, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.name = "X",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_x,
|
||||
.data_size = sizeof(var_x)
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+CMD",
|
||||
.test = cmd_test,
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0]),
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
var_x = 1;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(cmd_results, 0, sizeof(cmd_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+CMD=?\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
ret = CAT_RETURN_STATE_ERROR;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n") == 0);
|
||||
assert(strcmp(cmd_results, " test:+CMD") == 0);
|
||||
|
||||
ret = CAT_RETURN_STATE_DATA_OK;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=<X:INT32[RW]>\n\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " test:+CMD") == 0);
|
||||
|
||||
ret = CAT_RETURN_STATE_DATA_NEXT;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=<X:INT32[RW]>\n\n+CMD=<X:INT32[RW]>\n\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " test:+CMD test:+CMD") == 0);
|
||||
|
||||
ret = CAT_RETURN_STATE_NEXT;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=<X:INT32[RW]>\n\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " test:+CMD test:+CMD") == 0);
|
||||
|
||||
ret = CAT_RETURN_STATE_OK;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " test:+CMD") == 0);
|
||||
|
||||
ret_error = false;
|
||||
ret = CAT_RETURN_STATE_HOLD;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=<X:INT32[RW]>\n\n+CMD=<X:INT32[RW]>\n\ntest\n\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " test:+CMD test:+CMD test:+CMD test:+CMD test:+CMD") == 0);
|
||||
|
||||
ret_error = true;
|
||||
ret = CAT_RETURN_STATE_HOLD;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=<X:INT32[RW]>\n\n+CMD=<X:INT32[RW]>\n\ntest\n\nERROR\n") == 0);
|
||||
assert(strcmp(cmd_results, " test:+CMD test:+CMD test:+CMD test:+CMD test:+CMD") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
236
components/api/lib/cAT/tests/test_return_write.c
Executable file
236
components/api/lib/cAT/tests/test_return_write.c
Executable file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char cmd_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int var_x;
|
||||
static struct cat_object at;
|
||||
|
||||
static cat_return_state ret;
|
||||
static bool ret_error;
|
||||
|
||||
static cat_return_state cmd_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(cmd_results, " read:");
|
||||
strcat(cmd_results, cmd->name);
|
||||
|
||||
var_x++;
|
||||
if (var_x > 5) {
|
||||
ret = (ret_error == false) ? CAT_RETURN_STATE_HOLD_EXIT_OK : CAT_RETURN_STATE_HOLD_EXIT_ERROR;
|
||||
} else {
|
||||
if (var_x == 5) {
|
||||
strcpy(data, "test");
|
||||
*data_size = strlen(data);
|
||||
}
|
||||
ret = CAT_RETURN_STATE_DATA_NEXT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static cat_return_state cmd_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
strcat(cmd_results, " write:");
|
||||
strcat(cmd_results, cmd->name);
|
||||
|
||||
if ((ret == CAT_RETURN_STATE_DATA_NEXT) || (ret == CAT_RETURN_STATE_NEXT)) {
|
||||
var_x++;
|
||||
if (var_x > 3)
|
||||
ret = CAT_RETURN_STATE_DATA_OK;
|
||||
} else if (ret == CAT_RETURN_STATE_HOLD) {
|
||||
cat_trigger_unsolicited_read(&at, cmd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.name = "X",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_x,
|
||||
.data_size = sizeof(var_x)
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+CMD",
|
||||
.write = cmd_write,
|
||||
.read = cmd_read,
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0]),
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
var_x = 1;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(cmd_results, 0, sizeof(cmd_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+CMD=2\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
ret = CAT_RETURN_STATE_ERROR;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n") == 0);
|
||||
assert(strcmp(cmd_results, " write:+CMD") == 0);
|
||||
assert(var_x == 2);
|
||||
|
||||
ret = CAT_RETURN_STATE_DATA_OK;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " write:+CMD") == 0);
|
||||
assert(var_x == 2);
|
||||
|
||||
ret = CAT_RETURN_STATE_DATA_NEXT;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " write:+CMD write:+CMD") == 0);
|
||||
assert(var_x == 4);
|
||||
|
||||
ret = CAT_RETURN_STATE_NEXT;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " write:+CMD write:+CMD") == 0);
|
||||
assert(var_x == 4);
|
||||
|
||||
ret = CAT_RETURN_STATE_OK;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " write:+CMD") == 0);
|
||||
assert(var_x == 2);
|
||||
|
||||
ret_error = false;
|
||||
ret = CAT_RETURN_STATE_HOLD;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=2\n\n+CMD=3\n\ntest\n\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " write:+CMD read:+CMD read:+CMD read:+CMD read:+CMD") == 0);
|
||||
assert(var_x == 6);
|
||||
|
||||
ret_error = true;
|
||||
ret = CAT_RETURN_STATE_HOLD;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+CMD=2\n\n+CMD=3\n\ntest\n\nERROR\n") == 0);
|
||||
assert(strcmp(cmd_results, " write:+CMD read:+CMD read:+CMD read:+CMD read:+CMD") == 0);
|
||||
assert(var_x == 6);
|
||||
|
||||
ret = CAT_RETURN_STATE_HOLD_EXIT_ERROR;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n") == 0);
|
||||
assert(strcmp(cmd_results, " write:+CMD") == 0);
|
||||
assert(var_x == 2);
|
||||
|
||||
ret = CAT_RETURN_STATE_HOLD_EXIT_OK;
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n") == 0);
|
||||
assert(strcmp(cmd_results, " write:+CMD") == 0);
|
||||
assert(var_x == 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
157
components/api/lib/cAT/tests/test_run.c
Executable file
157
components/api/lib/cAT/tests/test_run.c
Executable file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char run_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int a_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " A:");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ap_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " AP:");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " +TEST:");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int force_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " FORCE:");
|
||||
strcat(run_results, cmd->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "A",
|
||||
.run = a_run
|
||||
},
|
||||
{
|
||||
.name = "AP",
|
||||
.run = ap_run
|
||||
},
|
||||
{
|
||||
.name = "+TEST",
|
||||
.run = test_run
|
||||
},
|
||||
{
|
||||
.name = "+EMPTY"
|
||||
},
|
||||
{
|
||||
.name = "FORCE",
|
||||
.run = force_run,
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
memset(run_results, 0, sizeof(run_results));
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT\nAT+\nATA\r\nATAP\nATAPA\nAT+TEST\nAT+te\nAT+e\nAT+empTY\naTf\nAtFoRcE\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n\nERROR\n\r\nOK\r\n\nOK\n\nERROR\n\nOK\n\nOK\n\nERROR\n\nERROR\n\nERROR\n\nERROR\n") == 0);
|
||||
assert(strcmp(run_results, " A:A AP:AP +TEST:+TEST +TEST:+TEST FORCE:FORCE FORCE:FORCE") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
224
components/api/lib/cAT/tests/test_search_cmd.c
Executable file
224
components/api/lib/cAT/tests/test_search_cmd.c
Executable file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static int ap_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ap_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_variable vars_ap1[] = {
|
||||
{
|
||||
.name = "var_ap1_1"
|
||||
},
|
||||
{
|
||||
.name = "var_ap1_2"
|
||||
},
|
||||
{
|
||||
.name = "var_ap1_3"
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars_apx2[] = {
|
||||
{
|
||||
.name = "var_apx2_1"
|
||||
},
|
||||
{
|
||||
.name = "var_apx2_2"
|
||||
},
|
||||
{
|
||||
.name = "var_apx2_3"
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "AP1",
|
||||
.write = ap_write,
|
||||
.only_test = true,
|
||||
.var = vars_ap1,
|
||||
.var_num = sizeof(vars_ap1) / sizeof(vars_ap1[0])
|
||||
},
|
||||
{
|
||||
.name = "AP2",
|
||||
.read = ap_read,
|
||||
.only_test = false
|
||||
},
|
||||
};
|
||||
|
||||
static struct cat_command cmds2[] = {
|
||||
{
|
||||
.name = "APX1",
|
||||
.write = ap_write,
|
||||
.only_test = true
|
||||
},
|
||||
{
|
||||
.name = "APX2",
|
||||
.read = ap_read,
|
||||
.only_test = false,
|
||||
.var = vars_apx2,
|
||||
.var_num = sizeof(vars_apx2) / sizeof(vars_apx2[0])
|
||||
},
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group1 = {
|
||||
.name = "std",
|
||||
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group cmd_group2 = {
|
||||
.name = "ext",
|
||||
|
||||
.cmd = cmds2,
|
||||
.cmd_num = sizeof(cmds2) / sizeof(cmds2[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group1,
|
||||
&cmd_group2
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
struct cat_command const *cmd;
|
||||
struct cat_command_group const *cmd_group;
|
||||
struct cat_variable const *var;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
cmd = cat_search_command_by_name(&at, "A");
|
||||
assert(cmd == NULL);
|
||||
|
||||
cmd = cat_search_command_by_name(&at, "AP");
|
||||
assert(cmd == NULL);
|
||||
|
||||
cmd = cat_search_command_by_name(&at, "AP1");
|
||||
assert(cmd == &cmds[0]);
|
||||
|
||||
cmd = cat_search_command_by_name(&at, "AP2");
|
||||
assert(cmd == &cmds[1]);
|
||||
|
||||
cmd = cat_search_command_by_name(&at, "AP3");
|
||||
assert(cmd == NULL);
|
||||
|
||||
cmd = cat_search_command_by_name(&at, "APX1");
|
||||
assert(cmd == &cmds2[0]);
|
||||
|
||||
cmd = cat_search_command_by_name(&at, "APX2");
|
||||
assert(cmd == &cmds2[1]);
|
||||
|
||||
cmd = cat_search_command_by_name(&at, "APX3");
|
||||
assert(cmd == NULL);
|
||||
|
||||
cmd_group = cat_search_command_group_by_name(&at, "std");
|
||||
assert(cmd_group == cmd_desc[0]);
|
||||
|
||||
cmd_group = cat_search_command_group_by_name(&at, "ext");
|
||||
assert(cmd_group == cmd_desc[1]);
|
||||
|
||||
cmd_group = cat_search_command_group_by_name(&at, "not");
|
||||
assert(cmd_group == NULL);
|
||||
|
||||
var = cat_search_variable_by_name(&at, &cmds[0], "v");
|
||||
assert(var == NULL);
|
||||
|
||||
var = cat_search_variable_by_name(&at, &cmds[0], "var_ap");
|
||||
assert(var == NULL);
|
||||
|
||||
var = cat_search_variable_by_name(&at, &cmds[0], "var_apx2");
|
||||
assert(var == NULL);
|
||||
|
||||
var = cat_search_variable_by_name(&at, &cmds[0], "var_ap1_1");
|
||||
assert(var == &vars_ap1[0]);
|
||||
|
||||
var = cat_search_variable_by_name(&at, &cmds[0], "var_ap1_2");
|
||||
assert(var == &vars_ap1[1]);
|
||||
|
||||
var = cat_search_variable_by_name(&at, &cmds[0], "var_ap1_3");
|
||||
assert(var == &vars_ap1[2]);
|
||||
|
||||
var = cat_search_variable_by_name(&at, &cmds[0], "var_ap1_4");
|
||||
assert(var == NULL);
|
||||
|
||||
var = cat_search_variable_by_name(&at, &cmds[1], "var_ap1_1");
|
||||
assert(var == NULL);
|
||||
|
||||
var = cat_search_variable_by_name(&at, &cmds2[1], "var_apx2_1");
|
||||
assert(var == &vars_apx2[0]);
|
||||
|
||||
var = cat_search_variable_by_name(&at, &cmds2[1], "var_apx2_2");
|
||||
assert(var == &vars_apx2[1]);
|
||||
|
||||
var = cat_search_variable_by_name(&at, &cmds2[1], "var_apx2_3");
|
||||
assert(var == &vars_apx2[2]);
|
||||
|
||||
var = cat_search_variable_by_name(&at, &cmds2[1], "var_apx2_4");
|
||||
assert(var == NULL);
|
||||
|
||||
var = cat_search_variable_by_name(&at, &cmds2[0], "var_apx2_1");
|
||||
assert(var == NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
149
components/api/lib/cAT/tests/test_shortcuts.c
Executable file
149
components/api/lib/cAT/tests/test_shortcuts.c
Executable file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char run_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int print_name(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, cmd->name);
|
||||
strcat(run_results, " ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+TEST",
|
||||
.run = print_name
|
||||
},
|
||||
{
|
||||
.name = "+TEST_A",
|
||||
.run = print_name
|
||||
},
|
||||
{
|
||||
.name = "+TEST_B",
|
||||
.run = print_name
|
||||
},
|
||||
{
|
||||
.name = "+ONE",
|
||||
.run = print_name
|
||||
},
|
||||
{
|
||||
.name = "+TWO",
|
||||
.run = print_name
|
||||
},
|
||||
};
|
||||
|
||||
static char buf[256];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
memset(run_results, 0, sizeof(run_results));
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT\nAT+\nAT+T\nAT+TE\nAT+TES\nAT+TEST\nAT+TEST_\nAT+TEST_A\nAT+TEST_B\nAT+O\nAT+ON\nAT+ONE\nAT+TW\nAT+TWO\n";
|
||||
|
||||
static void print_raw_text(char *p)
|
||||
{
|
||||
while (*p != '\0') {
|
||||
if (*p == '\n') {
|
||||
printf("\\n");
|
||||
} else {
|
||||
putchar(*p);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n\nERROR\n\nERROR\n\nERROR\n\nERROR\n\nOK\n\nERROR\n\nOK\n\nOK\n\nOK\n\nOK\n\nOK\n\nOK\n\nOK\n") == 0);
|
||||
assert(strcmp(run_results, "+TEST +TEST_A +TEST_B +ONE +ONE +ONE +TWO +TWO ") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
183
components/api/lib/cAT/tests/test_test.c
Executable file
183
components/api/lib/cAT/tests/test_test.c
Executable file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char test_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int a_test(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(test_results, " A:");
|
||||
strcat(test_results, cmd->name);
|
||||
|
||||
snprintf(data, max_data_size, "%s=A-val", cmd->name);
|
||||
*data_size = strlen(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ap_test(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(test_results, " AP:");
|
||||
strcat(test_results, cmd->name);
|
||||
|
||||
*data_size = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ap_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
strcat(test_results, " AP_W:");
|
||||
strcat(test_results, cmd->name);
|
||||
|
||||
assert(args_num == 0);
|
||||
assert(data[0] == 'a');
|
||||
assert(data_size == 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apw_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
strcat(test_results, " APW:");
|
||||
strcat(test_results, cmd->name);
|
||||
|
||||
assert(args_num == 0);
|
||||
assert(data[0] == '?');
|
||||
assert(data_size == 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_test(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(test_results, " +TEST:");
|
||||
strcat(test_results, cmd->name);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "A",
|
||||
.test = a_test
|
||||
},
|
||||
{
|
||||
.name = "AP",
|
||||
.test = ap_test,
|
||||
.write = ap_write
|
||||
},
|
||||
{
|
||||
.name = "APW",
|
||||
.write = apw_write
|
||||
},
|
||||
{
|
||||
.name = "+TEST",
|
||||
.test = test_test
|
||||
},
|
||||
{
|
||||
.name = "+EMPTY"
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(test_results, 0, sizeof(test_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT\r\nAT\nATAP=?\nATAP=?a\nATAP=a\nATAPW=?\nAT+TEST=?\nATA=?\nAT+EMPTY=?\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\r\nOK\r\n\nOK\n\nAP=\n\nOK\n\nERROR\n\nOK\n\nOK\n\nERROR\n\nA=A-val\n\nOK\n\nERROR\n") == 0);
|
||||
assert(strcmp(test_results, " AP:AP AP_W:AP APW:APW +TEST:+TEST A:A") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
459
components/api/lib/cAT/tests/test_test_args.c
Executable file
459
components/api/lib/cAT/tests/test_test_args.c
Executable file
@@ -0,0 +1,459 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char ack_results[256];
|
||||
|
||||
static int8_t var_int8;
|
||||
static int16_t var_int16;
|
||||
static int32_t var_int32;
|
||||
static uint8_t var_uint8;
|
||||
static uint16_t var_uint16;
|
||||
static uint32_t var_uint32;
|
||||
static uint8_t var_hex8;
|
||||
static uint16_t var_hex16;
|
||||
static uint32_t var_hex32;
|
||||
static uint8_t var_buf[4];
|
||||
static char var_string[16];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int cmd_override_test(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(data, "\ntest");
|
||||
*data_size = strlen(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_error_test(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int cmd_ok_test(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcpy(data, "test1");
|
||||
*data_size = strlen(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_ok2_test(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(data, "test2");
|
||||
*data_size = strlen(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int8,
|
||||
.data_size = sizeof(var_int8),
|
||||
.name = "x"
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int16,
|
||||
.data_size = sizeof(var_int16),
|
||||
.name = "y"
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int32,
|
||||
.data_size = sizeof(var_int32)
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint8,
|
||||
.data_size = sizeof(var_uint8)
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint16,
|
||||
.data_size = sizeof(var_uint16)
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint32,
|
||||
.data_size = sizeof(var_uint32)
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex8,
|
||||
.data_size = sizeof(var_hex8)
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex16,
|
||||
.data_size = sizeof(var_hex16)
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex32,
|
||||
.data_size = sizeof(var_hex32)
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_HEX,
|
||||
.data = &var_buf,
|
||||
.data_size = sizeof(var_buf)
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_STRING,
|
||||
.data = &var_string,
|
||||
.data_size = sizeof(var_string),
|
||||
.name = "msg"
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars_ro[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int8,
|
||||
.data_size = sizeof(var_int8),
|
||||
.name = "x",
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int16,
|
||||
.data_size = sizeof(var_int16),
|
||||
.name = "y",
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int32,
|
||||
.data_size = sizeof(var_int32),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint8,
|
||||
.data_size = sizeof(var_uint8),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint16,
|
||||
.data_size = sizeof(var_uint16),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint32,
|
||||
.data_size = sizeof(var_uint32),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex8,
|
||||
.data_size = sizeof(var_hex8),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex16,
|
||||
.data_size = sizeof(var_hex16),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex32,
|
||||
.data_size = sizeof(var_hex32),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_HEX,
|
||||
.data = &var_buf,
|
||||
.data_size = sizeof(var_buf),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_STRING,
|
||||
.data = &var_string,
|
||||
.data_size = sizeof(var_string),
|
||||
.name = "msg",
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars_wo[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int8,
|
||||
.data_size = sizeof(var_int8),
|
||||
.name = "x",
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int16,
|
||||
.data_size = sizeof(var_int16),
|
||||
.name = "y",
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int32,
|
||||
.data_size = sizeof(var_int32),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint8,
|
||||
.data_size = sizeof(var_uint8),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint16,
|
||||
.data_size = sizeof(var_uint16),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint32,
|
||||
.data_size = sizeof(var_uint32),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex8,
|
||||
.data_size = sizeof(var_hex8),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex16,
|
||||
.data_size = sizeof(var_hex16),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex32,
|
||||
.data_size = sizeof(var_hex32),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_HEX,
|
||||
.data = &var_buf,
|
||||
.data_size = sizeof(var_buf),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_STRING,
|
||||
.data = &var_string,
|
||||
.data_size = sizeof(var_string),
|
||||
.name = "msg",
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars2[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int8,
|
||||
.data_size = sizeof(var_int8),
|
||||
.name = "var"
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+SET",
|
||||
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
},
|
||||
{
|
||||
.name = "+SETRO",
|
||||
|
||||
.var = vars_ro,
|
||||
.var_num = sizeof(vars_ro) / sizeof(vars_ro[0])
|
||||
},
|
||||
{
|
||||
.name = "+SETWO",
|
||||
|
||||
.var = vars_wo,
|
||||
.var_num = sizeof(vars_wo) / sizeof(vars_wo[0])
|
||||
},
|
||||
{
|
||||
.name = "+TEST",
|
||||
.description = "test_desc",
|
||||
.test = cmd_override_test,
|
||||
|
||||
.var = vars2,
|
||||
.var_num = sizeof(vars2) / sizeof(vars2[0])
|
||||
},
|
||||
{
|
||||
.name = "+TEST2",
|
||||
.description = "test2_desc",
|
||||
|
||||
.var = vars2,
|
||||
.var_num = sizeof(vars2) / sizeof(vars2[0])
|
||||
},
|
||||
{
|
||||
.name = "+AP",
|
||||
.test = cmd_error_test,
|
||||
|
||||
.var = vars2,
|
||||
.var_num = sizeof(vars2) / sizeof(vars2[0])
|
||||
},
|
||||
{
|
||||
.name = "+ZZ",
|
||||
.test = cmd_ok_test,
|
||||
},
|
||||
{
|
||||
.name = "+ZZ2",
|
||||
.description = "zz2_desc",
|
||||
.test = cmd_ok_test,
|
||||
},
|
||||
{
|
||||
.name = "+ZZ3",
|
||||
.description = "zz3_desc",
|
||||
.test = cmd_ok2_test,
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[256];
|
||||
static char unsolicited_buf[256];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
.unsolicited_buf = unsolicited_buf,
|
||||
.unsolicited_buf_size = sizeof(unsolicited_buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
var_int8 = -8;
|
||||
var_int16 = -16;
|
||||
var_int32 = -32;
|
||||
var_uint8 = 8;
|
||||
var_uint8 = 16;
|
||||
var_uint8 = 32;
|
||||
var_hex8 = 0x08;
|
||||
var_hex16 = 0x16;
|
||||
var_hex32 = 0x32;
|
||||
var_hex16 = 0x0123;
|
||||
var_hex32 = 0xFF001234;
|
||||
|
||||
var_buf[0] = 0x12;
|
||||
var_buf[1] = 0x34;
|
||||
var_buf[2] = 0x56;
|
||||
var_buf[3] = 0x78;
|
||||
|
||||
sprintf(var_string, "TST");
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+SET=?\n";
|
||||
static const char test_case_1_ro[] = "\nAT+SETRO=?\n";
|
||||
static const char test_case_1_wo[] = "\nAT+SETWO=?\n";
|
||||
static const char test_case_2[] = "\nAT+TEST=?\nAT+TEST2=?\r\nAT+AP=?\n";
|
||||
static const char test_case_3[] = "\nAT+ZZ=?\nAT+ZZ2=?\nAT+ZZ3=?\r\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+SET=<x:INT8[RW]>,<y:INT16[RW]>,<INT32[RW]>,<UINT8[RW]>,<UINT16[RW]>,<UINT32[RW]>,<HEX8[RW]>,<HEX16[RW]>,<HEX32[RW]>,<HEXBUF[RW]>,<msg:STRING[RW]>\n\nOK\n") == 0);
|
||||
|
||||
prepare_input(test_case_1_ro);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+SETRO=<x:INT8[RO]>,<y:INT16[RO]>,<INT32[RO]>,<UINT8[RO]>,<UINT16[RO]>,<UINT32[RO]>,<HEX8[RO]>,<HEX16[RO]>,<HEX32[RO]>,<HEXBUF[RO]>,<msg:STRING[RO]>\n\nOK\n") == 0);
|
||||
|
||||
prepare_input(test_case_1_wo);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+SETWO=<x:INT8[WO]>,<y:INT16[WO]>,<INT32[WO]>,<UINT8[WO]>,<UINT16[WO]>,<UINT32[WO]>,<HEX8[WO]>,<HEX16[WO]>,<HEX32[WO]>,<HEXBUF[WO]>,<msg:STRING[WO]>\n\nOK\n") == 0);
|
||||
|
||||
prepare_input(test_case_2);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+TEST=<var:INT8[RW]>\ntest_desc\ntest\n\nOK\n\r\n+TEST2=<var:INT8[RW]>\r\ntest2_desc\r\n\r\nOK\r\n\nERROR\n") == 0);
|
||||
|
||||
prepare_input(test_case_3);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\ntest1\n\nOK\n\ntest1\n\nOK\n\r\n+ZZ3=\r\nzz3_desctest2\r\n\r\nOK\r\n") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
173
components/api/lib/cAT/tests/test_test_only.c
Executable file
173
components/api/lib/cAT/tests/test_test_only.c
Executable file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char cmd_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int ap_test(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(cmd_results, " test:");
|
||||
strcat(cmd_results, cmd->name);
|
||||
|
||||
strcpy(data, "ap_test");
|
||||
*data_size = strlen(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ap_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(cmd_results, " run:");
|
||||
strcat(cmd_results, cmd->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ap_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
strcat(cmd_results, " read:");
|
||||
strcat(cmd_results, cmd->name);
|
||||
|
||||
strcpy(data, "ap_read");
|
||||
*data_size = strlen(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ap_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
strcat(cmd_results, " write:");
|
||||
strcat(cmd_results, cmd->name);
|
||||
|
||||
assert(strcmp(data, "1") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "AP1",
|
||||
.test = ap_test,
|
||||
.write = ap_write,
|
||||
.read = ap_read,
|
||||
.run = ap_run,
|
||||
.only_test = true
|
||||
},
|
||||
{
|
||||
.name = "AP2",
|
||||
.test = ap_test,
|
||||
.write = ap_write,
|
||||
.read = ap_read,
|
||||
.run = ap_run,
|
||||
.only_test = false
|
||||
},
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(cmd_results, 0, sizeof(cmd_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nATAP1=?\n\nATAP1?\n\nATAP1=1\n\nATAP1\n";
|
||||
static const char test_case_2[] = "\nATAP2=?\n\nATAP2?\n\nATAP2=1\n\nATAP2\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nap_test\n\nOK\n\nERROR\n\nERROR\n\nERROR\n") == 0);
|
||||
assert(strcmp(cmd_results, " test:AP1") == 0);
|
||||
|
||||
prepare_input(test_case_2);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nap_test\n\nOK\n\nap_read\n\nOK\n\nOK\n\nOK\n") == 0);
|
||||
assert(strcmp(cmd_results, " test:AP2 read:AP2 write:AP2 run:AP2") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
203
components/api/lib/cAT/tests/test_unsolicited_read.c
Executable file
203
components/api/lib/cAT/tests/test_unsolicited_read.c
Executable file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char read_results[256];
|
||||
static char var_read_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int var_x, var_u1, var_u2;
|
||||
static struct cat_object at;
|
||||
|
||||
static struct cat_command u_cmds[];
|
||||
|
||||
static cat_return_state cmd_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
strcat(read_results, " read:");
|
||||
strcat(read_results, cmd->name);
|
||||
|
||||
if (strcmp(cmd->name, "+CMD") == 0) {
|
||||
s = cat_trigger_unsolicited_read(&at, &u_cmds[1]);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
}
|
||||
|
||||
return CAT_RETURN_STATE_DATA_OK;
|
||||
}
|
||||
|
||||
static int var_read(const struct cat_variable *var)
|
||||
{
|
||||
strcat(var_read_results, " var_read:");
|
||||
strcat(var_read_results, var->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_variable u_vars[] = {
|
||||
{
|
||||
.name = "U1",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_u1,
|
||||
.data_size = sizeof(var_u1),
|
||||
.read = var_read
|
||||
},
|
||||
{
|
||||
.name = "U2",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_u2,
|
||||
.data_size = sizeof(var_u2),
|
||||
.read = var_read
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.name = "X",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_x,
|
||||
.data_size = sizeof(var_x),
|
||||
.read = var_read
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+CMD",
|
||||
.read = cmd_read,
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0]),
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command u_cmds[] = {
|
||||
{
|
||||
.name = "+U1CMD",
|
||||
.read = cmd_read,
|
||||
.var = &u_vars[0],
|
||||
.var_num = 1,
|
||||
},
|
||||
{
|
||||
.name = "+U2CMD",
|
||||
.read = cmd_read,
|
||||
.var = &u_vars[1],
|
||||
.var_num = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
var_x = 1;
|
||||
var_u1 = 2;
|
||||
var_u2 = 3;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(read_results, 0, sizeof(read_results));
|
||||
memset(var_read_results, 0, sizeof(var_read_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+CMD?\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
|
||||
s = cat_is_unsolicited_buffer_full(&at);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_trigger_unsolicited_event(&at, &u_cmds[0], CAT_CMD_TYPE_READ);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_is_unsolicited_buffer_full(&at);
|
||||
assert(s == CAT_STATUS_ERROR_BUFFER_FULL);
|
||||
s = cat_trigger_unsolicited_read(&at, &u_cmds[1]);
|
||||
assert(s == CAT_STATUS_ERROR_BUFFER_FULL);
|
||||
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+U1CMD=2\n\n+CMD=1\n\n+U2CMD=3\n\nOK\n") == 0);
|
||||
assert(strcmp(read_results, " read:+U1CMD read:+CMD read:+U2CMD") == 0);
|
||||
assert(strcmp(var_read_results, " var_read:U1 var_read:X var_read:U2") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
238
components/api/lib/cAT/tests/test_unsolicited_read_buffer.c
Executable file
238
components/api/lib/cAT/tests/test_unsolicited_read_buffer.c
Executable file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char read_results[256];
|
||||
static char var_read_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int var_x, var_u1, var_u2;
|
||||
static struct cat_object at;
|
||||
|
||||
static struct cat_command u_cmds[];
|
||||
|
||||
static cat_return_state cmd_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
strcat(read_results, " read:");
|
||||
strcat(read_results, cmd->name);
|
||||
|
||||
if (strcmp(cmd->name, "+CMD") == 0) {
|
||||
s = cat_trigger_unsolicited_read(&at, &u_cmds[1]);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
}
|
||||
|
||||
return CAT_RETURN_STATE_DATA_OK;
|
||||
}
|
||||
|
||||
static int var_read(const struct cat_variable *var)
|
||||
{
|
||||
strcat(var_read_results, " var_read:");
|
||||
strcat(var_read_results, var->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_variable u_vars[] = {
|
||||
{
|
||||
.name = "U1",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_u1,
|
||||
.data_size = sizeof(var_u1),
|
||||
.read = var_read
|
||||
},
|
||||
{
|
||||
.name = "U2",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_u2,
|
||||
.data_size = sizeof(var_u2),
|
||||
.read = var_read
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.name = "X",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_x,
|
||||
.data_size = sizeof(var_x),
|
||||
.read = var_read
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+CMD",
|
||||
.read = cmd_read,
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0]),
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command u_cmds[] = {
|
||||
{
|
||||
.name = "+U1CMD",
|
||||
.read = cmd_read,
|
||||
.var = &u_vars[0],
|
||||
.var_num = 1,
|
||||
},
|
||||
{
|
||||
.name = "+U2CMD",
|
||||
.read = cmd_read,
|
||||
.var = &u_vars[1],
|
||||
.var_num = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
var_x = 1;
|
||||
var_u1 = 2;
|
||||
var_u2 = 3;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(read_results, 0, sizeof(read_results));
|
||||
memset(var_read_results, 0, sizeof(var_read_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+CMD?\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
|
||||
s = cat_is_unsolicited_buffer_full(&at);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_READ);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_NONE);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_trigger_unsolicited_event(&at, &u_cmds[0], CAT_CMD_TYPE_READ);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_READ);
|
||||
assert(s == CAT_STATUS_BUSY);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_TEST);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_NONE);
|
||||
assert(s == CAT_STATUS_BUSY);
|
||||
s = cat_is_unsolicited_buffer_full(&at);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_trigger_unsolicited_event(&at, &u_cmds[1], CAT_CMD_TYPE_READ);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_READ);
|
||||
assert(s == CAT_STATUS_BUSY);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_TEST);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_NONE);
|
||||
assert(s == CAT_STATUS_BUSY);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[1], CAT_CMD_TYPE_READ);
|
||||
assert(s == CAT_STATUS_BUSY);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[1], CAT_CMD_TYPE_TEST);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[1], CAT_CMD_TYPE_NONE);
|
||||
assert(s == CAT_STATUS_BUSY);
|
||||
s = cat_is_unsolicited_buffer_full(&at);
|
||||
assert(s == CAT_STATUS_ERROR_BUFFER_FULL);
|
||||
s = cat_trigger_unsolicited_read(&at, &u_cmds[1]);
|
||||
assert(s == CAT_STATUS_ERROR_BUFFER_FULL);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_READ);
|
||||
assert(s == CAT_STATUS_BUSY);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_TEST);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[1], CAT_CMD_TYPE_NONE);
|
||||
assert(s == CAT_STATUS_BUSY);
|
||||
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+U1CMD=2\n\n+CMD=1\n\n+U2CMD=3\n\nOK\n\n+U2CMD=3\n") == 0);
|
||||
assert(strcmp(read_results, " read:+U1CMD read:+CMD read:+U2CMD read:+U2CMD") == 0);
|
||||
assert(strcmp(var_read_results, " var_read:U1 var_read:X var_read:U2 var_read:U2") == 0);
|
||||
|
||||
s = cat_is_unsolicited_buffer_full(&at);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
211
components/api/lib/cAT/tests/test_unsolicited_read_stress.c
Executable file
211
components/api/lib/cAT/tests/test_unsolicited_read_stress.c
Executable file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char read_results[256];
|
||||
static char var_read_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int var_x, var_u1;
|
||||
static struct cat_object at;
|
||||
|
||||
static struct cat_command u_cmds[];
|
||||
|
||||
static cat_return_state cmd_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
strcat(read_results, " read:");
|
||||
strcat(read_results, cmd->name);
|
||||
|
||||
return CAT_RETURN_STATE_DATA_OK;
|
||||
}
|
||||
|
||||
static int var_read(const struct cat_variable *var)
|
||||
{
|
||||
strcat(var_read_results, " var_read:");
|
||||
strcat(var_read_results, var->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_variable u_vars[] = {
|
||||
{
|
||||
.name = "U1",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_u1,
|
||||
.data_size = sizeof(var_u1),
|
||||
.read = var_read
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.name = "X",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_x,
|
||||
.data_size = sizeof(var_x),
|
||||
.read = var_read
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+CMD",
|
||||
.read = cmd_read,
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0]),
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command u_cmds[] = {
|
||||
{
|
||||
.name = "+UCMD",
|
||||
.read = cmd_read,
|
||||
.var = u_vars,
|
||||
.var_num = sizeof(u_vars) / sizeof(u_vars[0]),
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
var_x = 1;
|
||||
var_u1 = 2;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(read_results, 0, sizeof(read_results));
|
||||
memset(var_read_results, 0, sizeof(var_read_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+CMD?\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
cat_status s;
|
||||
int events = 4;
|
||||
struct cat_command const *cmd;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
|
||||
cmd = cat_get_processed_command(&at, CAT_FSM_TYPE_ATCMD);
|
||||
assert(cmd == NULL);
|
||||
cmd = cat_get_processed_command(&at, CAT_FSM_TYPE_UNSOLICITED);
|
||||
assert(cmd == NULL);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_READ);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_NONE);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
|
||||
while (events > 0) {
|
||||
s = cat_is_unsolicited_buffer_full(&at);
|
||||
cmd = cat_get_processed_command(&at, CAT_FSM_TYPE_UNSOLICITED);
|
||||
if ((s == CAT_STATUS_OK) && (cmd == NULL)) {
|
||||
var_u1 = events;
|
||||
s = cat_trigger_unsolicited_event(&at, &u_cmds[0], CAT_CMD_TYPE_READ);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
events--;
|
||||
} else {
|
||||
assert(cmd == &u_cmds[0]);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_READ);
|
||||
assert(s == CAT_STATUS_BUSY);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_TEST);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_is_unsolicited_event_buffered(&at, &u_cmds[0], CAT_CMD_TYPE_NONE);
|
||||
assert(s == CAT_STATUS_BUSY);
|
||||
}
|
||||
s = cat_service(&at);
|
||||
assert(s == CAT_STATUS_BUSY);
|
||||
}
|
||||
|
||||
while (cat_service(&at) != 0) {};
|
||||
cmd = cat_get_processed_command(&at, CAT_FSM_TYPE_ATCMD);
|
||||
assert(cmd == NULL);
|
||||
cmd = cat_get_processed_command(&at, CAT_FSM_TYPE_UNSOLICITED);
|
||||
assert(cmd == NULL);
|
||||
|
||||
assert(strcmp(ack_results, "\n+UCMD=4\n\n+CMD=1\n\n+UCMD=3\n\nOK\n\n+UCMD=2\n\n+UCMD=1\n") == 0);
|
||||
assert(strcmp(read_results, " read:+UCMD read:+CMD read:+UCMD read:+UCMD read:+UCMD") == 0);
|
||||
assert(strcmp(var_read_results, " var_read:U1 var_read:X var_read:U1 var_read:U1 var_read:U1") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
189
components/api/lib/cAT/tests/test_unsolicited_test.c
Executable file
189
components/api/lib/cAT/tests/test_unsolicited_test.c
Executable file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char read_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int var_x, var_u1, var_u2;
|
||||
static struct cat_object at;
|
||||
|
||||
static struct cat_command u_cmds[];
|
||||
|
||||
static cat_return_state cmd_test(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
strcat(read_results, " test:");
|
||||
strcat(read_results, cmd->name);
|
||||
|
||||
if (strcmp(cmd->name, "+CMD") == 0) {
|
||||
s = cat_trigger_unsolicited_test(&at, &u_cmds[1]);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
}
|
||||
|
||||
return CAT_RETURN_STATE_DATA_OK;
|
||||
}
|
||||
|
||||
static struct cat_variable u_vars[] = {
|
||||
{
|
||||
.name = "U1",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_u1,
|
||||
.data_size = sizeof(var_u1)
|
||||
},
|
||||
{
|
||||
.name = "U2",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_u2,
|
||||
.data_size = sizeof(var_u2)
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.name = "X",
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_x,
|
||||
.data_size = sizeof(var_x)
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+CMD",
|
||||
.test = cmd_test,
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0]),
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command u_cmds[] = {
|
||||
{
|
||||
.name = "+U1CMD",
|
||||
.test = cmd_test,
|
||||
.var = &u_vars[0],
|
||||
.var_num = 1,
|
||||
},
|
||||
{
|
||||
.name = "+U2CMD",
|
||||
.test = cmd_test,
|
||||
.var = &u_vars[1],
|
||||
.var_num = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
var_x = 1;
|
||||
var_u1 = 2;
|
||||
var_u2 = 3;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(read_results, 0, sizeof(read_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+CMD=?\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
cat_status s;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
|
||||
s = cat_is_unsolicited_buffer_full(&at);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_trigger_unsolicited_event(&at, &u_cmds[0], CAT_CMD_TYPE_TEST);
|
||||
assert(s == CAT_STATUS_OK);
|
||||
s = cat_is_unsolicited_buffer_full(&at);
|
||||
assert(s == CAT_STATUS_ERROR_BUFFER_FULL);
|
||||
s = cat_trigger_unsolicited_test(&at, &u_cmds[1]);
|
||||
assert(s == CAT_STATUS_ERROR_BUFFER_FULL);
|
||||
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+U1CMD=<U1:INT32[RW]>\n\n+CMD=<X:INT32[RW]>\n\n+U2CMD=<U2:INT32[RW]>\n\nOK\n") == 0);
|
||||
assert(strcmp(read_results, " test:+U1CMD test:+CMD test:+U2CMD") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
545
components/api/lib/cAT/tests/test_var_access.c
Executable file
545
components/api/lib/cAT/tests/test_var_access.c
Executable file
@@ -0,0 +1,545 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char ack_results[256];
|
||||
|
||||
static int8_t var1;
|
||||
static int8_t var2;
|
||||
static int8_t var3;
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int var2_write_cntr;
|
||||
static int var3_read_cntr;
|
||||
|
||||
static int8_t var_int8;
|
||||
static int16_t var_int16;
|
||||
static int32_t var_int32;
|
||||
static uint8_t var_uint8;
|
||||
static uint16_t var_uint16;
|
||||
static uint32_t var_uint32;
|
||||
static uint8_t var_hex8;
|
||||
static uint16_t var_hex16;
|
||||
static uint32_t var_hex32;
|
||||
static uint8_t var_buf[4];
|
||||
static char var_string[16];
|
||||
|
||||
static int cmd_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_read(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_test(const struct cat_command *cmd, uint8_t *data, size_t *data_size, const size_t max_data_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_run(const struct cat_command *cmd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var1_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var1_read(const struct cat_variable *var)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var2_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
var2_write_cntr++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var2_read(const struct cat_variable *var)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var3_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var3_read(const struct cat_variable *var)
|
||||
{
|
||||
var3_read_cntr++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_cmd_list(const struct cat_command *cmd)
|
||||
{
|
||||
return CAT_RETURN_STATE_PRINT_CMD_LIST_OK;
|
||||
}
|
||||
|
||||
static struct cat_variable vars_ro[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var2,
|
||||
.data_size = sizeof(var2),
|
||||
.write = var2_write,
|
||||
.read = var2_read,
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars_wo[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var3,
|
||||
.data_size = sizeof(var3),
|
||||
.write = var3_write,
|
||||
.read = var3_read,
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var1,
|
||||
.data_size = sizeof(var1),
|
||||
.write = var1_write,
|
||||
.read = var1_read,
|
||||
.access = CAT_VAR_ACCESS_READ_WRITE
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var2,
|
||||
.data_size = sizeof(var2),
|
||||
.write = var2_write,
|
||||
.read = var2_read,
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var3,
|
||||
.data_size = sizeof(var3),
|
||||
.write = var3_write,
|
||||
.read = var3_read,
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars_misc_ro[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var1,
|
||||
.data_size = sizeof(var1),
|
||||
.access = CAT_VAR_ACCESS_READ_WRITE
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int8,
|
||||
.data_size = sizeof(var_int8),
|
||||
.name = "x",
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int16,
|
||||
.data_size = sizeof(var_int16),
|
||||
.name = "y",
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int32,
|
||||
.data_size = sizeof(var_int32),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint8,
|
||||
.data_size = sizeof(var_uint8),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint16,
|
||||
.data_size = sizeof(var_uint16),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint32,
|
||||
.data_size = sizeof(var_uint32),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex8,
|
||||
.data_size = sizeof(var_hex8),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex16,
|
||||
.data_size = sizeof(var_hex16),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex32,
|
||||
.data_size = sizeof(var_hex32),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_HEX,
|
||||
.data = &var_buf,
|
||||
.data_size = sizeof(var_buf),
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_STRING,
|
||||
.data = &var_string,
|
||||
.data_size = sizeof(var_string),
|
||||
.name = "msg",
|
||||
.access = CAT_VAR_ACCESS_READ_ONLY
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_variable vars_misc_wo[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var1,
|
||||
.data_size = sizeof(var1),
|
||||
.access = CAT_VAR_ACCESS_READ_WRITE
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int8,
|
||||
.data_size = sizeof(var_int8),
|
||||
.name = "x",
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int16,
|
||||
.data_size = sizeof(var_int16),
|
||||
.name = "y",
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var_int32,
|
||||
.data_size = sizeof(var_int32),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint8,
|
||||
.data_size = sizeof(var_uint8),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint16,
|
||||
.data_size = sizeof(var_uint16),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var_uint32,
|
||||
.data_size = sizeof(var_uint32),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex8,
|
||||
.data_size = sizeof(var_hex8),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex16,
|
||||
.data_size = sizeof(var_hex16),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var_hex32,
|
||||
.data_size = sizeof(var_hex32),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_HEX,
|
||||
.data = &var_buf,
|
||||
.data_size = sizeof(var_buf),
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_BUF_STRING,
|
||||
.data = &var_string,
|
||||
.data_size = sizeof(var_string),
|
||||
.name = "msg",
|
||||
.access = CAT_VAR_ACCESS_WRITE_ONLY
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+VRW",
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
},
|
||||
{
|
||||
.name = "+VRO",
|
||||
.var = vars_ro,
|
||||
.var_num = sizeof(vars_ro) / sizeof(vars_ro[0])
|
||||
},
|
||||
{
|
||||
.name = "+VWO",
|
||||
.var = vars_wo,
|
||||
.var_num = sizeof(vars_wo) / sizeof(vars_wo[0])
|
||||
},
|
||||
{
|
||||
.name = "+MRO",
|
||||
.var = vars_misc_ro,
|
||||
.var_num = sizeof(vars_misc_ro) / sizeof(vars_misc_ro[0])
|
||||
},
|
||||
{
|
||||
.name = "+MWO",
|
||||
.var = vars_misc_wo,
|
||||
.var_num = sizeof(vars_misc_wo) / sizeof(vars_misc_wo[0])
|
||||
},
|
||||
{
|
||||
.name = "#HELP",
|
||||
.run = print_cmd_list,
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[256];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
}
|
||||
|
||||
static void print_raw_text(char *p)
|
||||
{
|
||||
while (*p != '\0') {
|
||||
if (*p == '\n') {
|
||||
printf("\\n");
|
||||
} else {
|
||||
putchar(*p);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input("\nAT#HELP\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nAT+VRW?\nAT+VRW=\nAT+VRW=?\n\nAT+VRO?\nAT+VRO=?\n\nAT+VWO=\nAT+VWO=?\n\nAT+MRO?\nAT+MRO=\nAT+MRO=?\n\nAT+MWO?\nAT+MWO=\nAT+MWO=?\n\nAT#HELP\n\nOK\n") == 0);
|
||||
|
||||
prepare_input("\nAT+VRW=?\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+VRW=<INT8[RW]>,<INT8[RO]>,<INT8[WO]>\n\nOK\n") == 0);
|
||||
|
||||
prepare_input("\nAT+VRO=?\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+VRO=<INT8[RO]>\n\nOK\n") == 0);
|
||||
|
||||
prepare_input("\nAT+VWO=?\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+VWO=<INT8[WO]>\n\nOK\n") == 0);
|
||||
|
||||
var2 = 1;
|
||||
prepare_input("\nAT+VRO=1\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n") == 0);
|
||||
assert(var2 == 1);
|
||||
|
||||
var3 = 3;
|
||||
prepare_input("\nAT+VWO?\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n") == 0);
|
||||
assert(var3 == 3);
|
||||
|
||||
var1 = -1;
|
||||
var2 = -2;
|
||||
var3 = -3;
|
||||
var2_write_cntr = 0;
|
||||
var3_read_cntr = 0;
|
||||
|
||||
prepare_input("\nAT+VRW?\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+VRW=-1,-2,0\n\nOK\n") == 0);
|
||||
assert(var2_write_cntr == 0);
|
||||
assert(var3_read_cntr == 1);
|
||||
|
||||
prepare_input("\nAT+VRW=1,2,3\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(var2_write_cntr == 1);
|
||||
assert(var3_read_cntr == 1);
|
||||
assert(var1 == 1);
|
||||
assert(var2 == -2);
|
||||
assert(var3 == 3);
|
||||
|
||||
var1 = 100;
|
||||
var_int8 = 1;
|
||||
var_int16 = 2;
|
||||
var_int32 = 3;
|
||||
var_uint8 = 4;
|
||||
var_uint16 = 5;
|
||||
var_uint32 = 6;
|
||||
var_hex8 = 7;
|
||||
var_hex16 = 8;
|
||||
var_hex32 = 9;
|
||||
var_buf[0] = 0x10;
|
||||
var_buf[1] = 0x11;
|
||||
var_buf[2] = 0x12;
|
||||
var_buf[3] = 0x13;
|
||||
strcpy(var_string, "test_string");
|
||||
|
||||
prepare_input("\nAT+MWO?\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+MWO=100,0,0,0,0,0,0,0x00,0x0000,0x00000000,00000000,\"\"\n\nOK\n") == 0);
|
||||
|
||||
prepare_input("\nAT+MWO=1,2,3,4,5,6,7,0x08,0x0009,0x0000000A,01020304,\"abc\"\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(var1 == 1);
|
||||
assert(var_int8 == 2);
|
||||
assert(var_int16 == 3);
|
||||
assert(var_int32 == 4);
|
||||
assert(var_uint8 == 5);
|
||||
assert(var_uint16 == 6);
|
||||
assert(var_uint32 == 7);
|
||||
assert(var_hex8 == 8);
|
||||
assert(var_hex16 == 9);
|
||||
assert(var_hex32 == 10);
|
||||
assert(var_buf[0] == 0x01);
|
||||
assert(var_buf[1] == 0x02);
|
||||
assert(var_buf[2] == 0x03);
|
||||
assert(var_buf[3] == 0x04);
|
||||
assert(strcmp(var_string, "abc") == 0);
|
||||
|
||||
prepare_input("\nAT+MRO?\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\n+MRO=1,2,3,4,5,6,7,0x08,0x0009,0x0000000A,01020304,\"abc\"\n\nOK\n") == 0);
|
||||
|
||||
prepare_input("\nAT+MRO=2,0,0,0,0,0,0,0x00,0x0000,0x00000000,00000000,\"cba\"\n");
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n") == 0);
|
||||
assert(var1 == 2);
|
||||
assert(var_int8 == 2);
|
||||
assert(var_int16 == 3);
|
||||
assert(var_int32 == 4);
|
||||
assert(var_uint8 == 5);
|
||||
assert(var_uint16 == 6);
|
||||
assert(var_uint32 == 7);
|
||||
assert(var_hex8 == 8);
|
||||
assert(var_hex16 == 9);
|
||||
assert(var_hex32 == 10);
|
||||
assert(var_buf[0] == 0x01);
|
||||
assert(var_buf[1] == 0x02);
|
||||
assert(var_buf[2] == 0x03);
|
||||
assert(var_buf[3] == 0x04);
|
||||
assert(strcmp(var_string, "abc") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
166
components/api/lib/cAT/tests/test_write.c
Executable file
166
components/api/lib/cAT/tests/test_write.c
Executable file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char run_results[256];
|
||||
static char write_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int a_run(const struct cat_command *cmd)
|
||||
{
|
||||
strcat(run_results, " A_");
|
||||
strcat(run_results, cmd->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int a_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
strcat(write_results, " A:");
|
||||
strncat(write_results, data, data_size);
|
||||
|
||||
assert(args_num == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ap_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
strcat(write_results, " AP:");
|
||||
strncat(write_results, data, data_size);
|
||||
|
||||
assert(args_num == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
strcat(write_results, " +TEST:");
|
||||
strncat(write_results, data, data_size);
|
||||
|
||||
assert(args_num == 0);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "A",
|
||||
.write = a_write,
|
||||
.run = a_run
|
||||
},
|
||||
{
|
||||
.name = "AP",
|
||||
.write = ap_write
|
||||
},
|
||||
{
|
||||
.name = "+TEST",
|
||||
.write = test_write
|
||||
},
|
||||
{
|
||||
.name = "+EMPTY"
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
memset(run_results, 0, sizeof(run_results));
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(write_results, 0, sizeof(write_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT\nAT+\nAT+?\nATA=123\r\nATA=\nATAP?\nATAP=11\r22\r\nAT+TEST=456\nAT+te=789\nAT+e=1\nAT+empTY=2\r\nATA\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n\nERROR\n\nERROR\n\r\nOK\r\n\nOK\n\nERROR\n\r\nOK\r\n\nERROR\n\nERROR\n\nERROR\n\r\nERROR\r\n\nOK\n") == 0);
|
||||
assert(strcmp(run_results, " A_A") == 0);
|
||||
assert(strcmp(write_results, " A:123 A: AP:1122 +TEST:456 +TEST:789") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
174
components/api/lib/cAT/tests/test_write_hex_buffer.c
Executable file
174
components/api/lib/cAT/tests/test_write_hex_buffer.c
Executable file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char write_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static uint8_t var[4];
|
||||
static size_t var_write_size[4];
|
||||
static int var_write_size_index;
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int cmd_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
strcat(write_results, " CMD:");
|
||||
strncat(write_results, data, data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
var_write_size[var_write_size_index++] = write_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_BUF_HEX,
|
||||
.data = var,
|
||||
.data_size = sizeof(var),
|
||||
.write = var_write
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+SET",
|
||||
.write = cmd_write,
|
||||
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
memset(var, 0, sizeof(var));
|
||||
memset(var_write_size, 0, sizeof(var_write_size));
|
||||
var_write_size_index = 0;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(write_results, 0, sizeof(write_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+SET=0\nAT+SET=aa\nAT+SET=001\nAT+SET=12345678\nAT+SET=ffAA\n";
|
||||
static const char test_case_2[] = "\nAT+SET=0x11\nAT+SET=11\nAT+SET=-1\nAT+SET=87654321\nAT+SET=0001\nAT+SET=1122334455\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n\nOK\n\nERROR\n\nOK\n\nOK\n") == 0);
|
||||
assert(strcmp(write_results, " CMD:aa CMD:12345678 CMD:ffAA") == 0);
|
||||
|
||||
assert(var[0] == 0xFF);
|
||||
assert(var[1] == 0xAA);
|
||||
assert(var[2] == 0x56);
|
||||
assert(var[3] == 0x78);
|
||||
|
||||
assert(var_write_size[0] == 1);
|
||||
assert(var_write_size[1] == 4);
|
||||
assert(var_write_size[2] == 2);
|
||||
assert(var_write_size[3] == 0);
|
||||
|
||||
prepare_input(test_case_2);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n\nOK\n\nERROR\n\nOK\n\nOK\n\nERROR\n") == 0);
|
||||
assert(strcmp(write_results, " CMD:11 CMD:87654321 CMD:0001") == 0);
|
||||
|
||||
assert(var[0] == 0x11);
|
||||
assert(var[1] == 0x22);
|
||||
assert(var[2] == 0x33);
|
||||
assert(var[3] == 0x44);
|
||||
|
||||
assert(var_write_size[0] == 1);
|
||||
assert(var_write_size[1] == 4);
|
||||
assert(var_write_size[2] == 2);
|
||||
assert(var_write_size[3] == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
212
components/api/lib/cAT/tests/test_write_hex_range.c
Executable file
212
components/api/lib/cAT/tests/test_write_hex_range.c
Executable file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char write_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static uint8_t var1, var1b;
|
||||
static uint16_t var2, var2b;
|
||||
static uint32_t var3, var3b;
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int cmd_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
strcat(write_results, " CMD:");
|
||||
strncat(write_results, data, data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var1_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
assert(write_size == 1);
|
||||
var1b = *(uint8_t*)(var->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var2_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
assert(write_size == 2);
|
||||
var2b = *(uint16_t*)(var->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var3_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
assert(write_size == 4);
|
||||
var3b = *(uint32_t*)(var->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var1,
|
||||
.data_size = sizeof(var1),
|
||||
.write = var1_write
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var2,
|
||||
.data_size = sizeof(var2),
|
||||
.write = var2_write
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_NUM_HEX,
|
||||
.data = &var3,
|
||||
.data_size = sizeof(var3),
|
||||
.write = var3_write
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+SET",
|
||||
.write = cmd_write,
|
||||
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
var1 = 1;
|
||||
var2 = 2;
|
||||
var3 = 3;
|
||||
var1b = 10;
|
||||
var2b = 20;
|
||||
var3b = 30;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(write_results, 0, sizeof(write_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+SET=0\nAT+SET=0x0\nAT+SET=0x01\nAT+SET=0x0ff\nAT+SET=0x100\n";
|
||||
static const char test_case_2[] = "\nAT+SET=0x,0x00\nAT+SET=0x1,0x00\nAT+SET=0x2,0xFFf\nAT+SET=0x3,0xFFFF\nAT+SET=0x4,0xFFFFF\n";
|
||||
static const char test_case_3[] = "\nAT+SET=0x0,0x0,0\nAT+SET=0x0,0x0,0x0000000000000\nAT+SET=0x0,0x0,0x1\nAT+SET=0x0,0x0,0xffffFFFF\nAT+SET=0x10,0x20,0x100000000\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n\nOK\n\nOK\n\nOK\n\nERROR\n") == 0);
|
||||
assert(strcmp(write_results, " CMD:0x0 CMD:0x01 CMD:0x0ff") == 0);
|
||||
|
||||
assert(var1 == 255);
|
||||
assert(var1b == var1);
|
||||
assert(var2 == 2);
|
||||
assert(var2b == 20);
|
||||
assert(var3 == 3);
|
||||
assert(var3b == 30);
|
||||
|
||||
prepare_input(test_case_2);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n\nOK\n\nOK\n\nOK\n\nERROR\n") == 0);
|
||||
assert(strcmp(write_results, " CMD:0x1,0x00 CMD:0x2,0xFFf CMD:0x3,0xFFFF") == 0);
|
||||
|
||||
assert(var1 == 4);
|
||||
assert(var1b == var1);
|
||||
assert(var2 == 0xFFFF);
|
||||
assert(var2b == var2);
|
||||
assert(var3 == 3);
|
||||
assert(var3b == 30);
|
||||
|
||||
prepare_input(test_case_3);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n\nOK\n\nOK\n\nOK\n\nERROR\n") == 0);
|
||||
assert(strcmp(write_results, " CMD:0x0,0x0,0x0000000000000 CMD:0x0,0x0,0x1 CMD:0x0,0x0,0xffffFFFF") == 0);
|
||||
|
||||
assert(var1 == 0x10);
|
||||
assert(var1b == var1);
|
||||
assert(var2 == 0x20);
|
||||
assert(var2b == var2);
|
||||
assert(var3 == 0xFFFFFFFF);
|
||||
assert(var3b == var3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
212
components/api/lib/cAT/tests/test_write_int_range.c
Executable file
212
components/api/lib/cAT/tests/test_write_int_range.c
Executable file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char write_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static int8_t var1, var1b;
|
||||
static int16_t var2, var2b;
|
||||
static int32_t var3, var3b;
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int cmd_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
strcat(write_results, " CMD:");
|
||||
strncat(write_results, data, data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var1_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
assert(write_size == 1);
|
||||
var1b = *(int8_t*)(var->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var2_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
assert(write_size == 2);
|
||||
var2b = *(int16_t*)(var->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var3_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
assert(write_size == 4);
|
||||
var3b = *(int32_t*)(var->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var1,
|
||||
.data_size = sizeof(var1),
|
||||
.write = var1_write
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var2,
|
||||
.data_size = sizeof(var2),
|
||||
.write = var2_write
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var3,
|
||||
.data_size = sizeof(var3),
|
||||
.write = var3_write
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+SET",
|
||||
.write = cmd_write,
|
||||
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf),
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
var1 = 1;
|
||||
var2 = 2;
|
||||
var3 = 3;
|
||||
var1b = -1;
|
||||
var2b = -2;
|
||||
var3b = -3;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(write_results, 0, sizeof(write_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+SET=-128\nAT+SET=-129\nAT+SET=127\nAT+SET=128\n";
|
||||
static const char test_case_2[] = "\nAT+SET=-128,-32768\nAT+SET=-128,-40000\nAT+SET=-128,32767\nAT+SET=-100,40000\n";
|
||||
static const char test_case_3[] = "\nAT+SET=0,0,-2147483648\nAT+SET=0,0,-2147483649\nAT+SET=1,1,2147483647\nAT+SET=2,2,2147483648\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n\nERROR\n\nOK\n\nERROR\n") == 0);
|
||||
assert(strcmp(write_results, " CMD:-128 CMD:127") == 0);
|
||||
|
||||
assert(var1 == 127);
|
||||
assert(var1b == var1);
|
||||
assert(var2 == 2);
|
||||
assert(var2b == -2);
|
||||
assert(var3 == 3);
|
||||
assert(var3b == -3);
|
||||
|
||||
prepare_input(test_case_2);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n\nERROR\n\nOK\n\nERROR\n") == 0);
|
||||
assert(strcmp(write_results, " CMD:-128,-32768 CMD:-128,32767") == 0);
|
||||
|
||||
assert(var1 == -100);
|
||||
assert(var1b == var1);
|
||||
assert(var2 == 32767);
|
||||
assert(var2b == var2);
|
||||
assert(var3 == 3);
|
||||
assert(var3b == -3);
|
||||
|
||||
prepare_input(test_case_3);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n\nERROR\n\nOK\n\nERROR\n") == 0);
|
||||
assert(strcmp(write_results, " CMD:0,0,-2147483648 CMD:1,1,2147483647") == 0);
|
||||
|
||||
assert(var1 == 2);
|
||||
assert(var1b == var1);
|
||||
assert(var2 == 2);
|
||||
assert(var2b == var2);
|
||||
assert(var3 == 2147483647);
|
||||
assert(var3b == var3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
234
components/api/lib/cAT/tests/test_write_parse.c
Executable file
234
components/api/lib/cAT/tests/test_write_parse.c
Executable file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char write_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static int8_t var1, var2, var3;
|
||||
static int8_t var1b, var2b, var3b;
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int cmd_write1(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
char tmp[32];
|
||||
sprintf(tmp, " CMD1_%ld:", args_num);
|
||||
strcat(write_results, tmp);
|
||||
strncat(write_results, data, data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_write3(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
char tmp[32];
|
||||
sprintf(tmp, " CMD3_%ld:", args_num);
|
||||
strcat(write_results, tmp);
|
||||
strncat(write_results, data, data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var1_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
assert(write_size == 1);
|
||||
var1b = *(int8_t*)(var->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var2_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
assert(write_size == 1);
|
||||
var2b = *(int8_t*)(var->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var3_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
assert(write_size == 1);
|
||||
var3b = *(int8_t*)(var->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var1,
|
||||
.data_size = sizeof(var1),
|
||||
.write = var1_write
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var2,
|
||||
.data_size = sizeof(var2),
|
||||
.write = var2_write
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_INT_DEC,
|
||||
.data = &var3,
|
||||
.data_size = sizeof(var3),
|
||||
.write = var3_write
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+SET1",
|
||||
.write = cmd_write1,
|
||||
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
},
|
||||
{
|
||||
.name = "+SET3",
|
||||
.write = cmd_write3,
|
||||
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
},
|
||||
{
|
||||
.name = "+SETALL",
|
||||
.write = cmd_write3,
|
||||
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0]),
|
||||
.need_all_vars = true
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
var1 = 1;
|
||||
var2 = 2;
|
||||
var3 = 3;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(write_results, 0, sizeof(write_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+SET=-10,-20,-30\r\nAT+SET1=-10,-20,-30\r\nAT+SET1=-1\r\n";
|
||||
static const char test_case_2[] = "\nAT+SET3=-1,-2,-3,0\nAT+SET3=-1,-2,-3\nAT+SET3=-100\n";
|
||||
static const char test_case_3[] = "\nAT+SETALL=-11,-22,-33\nAT+SETALL=-1,-2,-3\nAT+SETALL=100\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\r\nERROR\r\n\r\nOK\r\n\r\nOK\r\n") == 0);
|
||||
assert(strcmp(write_results, " CMD1_3:-10,-20,-30 CMD1_1:-1") == 0);
|
||||
|
||||
assert(var1 == -1);
|
||||
assert(var2 == -20);
|
||||
assert(var3 == -30);
|
||||
assert(var1b == -1);
|
||||
assert(var2b == -20);
|
||||
assert(var3b == -30);
|
||||
|
||||
prepare_input(test_case_2);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n\nOK\n\nOK\n") == 0);
|
||||
assert(strcmp(write_results, " CMD3_3:-1,-2,-3 CMD3_1:-100") == 0);
|
||||
|
||||
assert(var1 == -100);
|
||||
assert(var2 == -2);
|
||||
assert(var3 == -3);
|
||||
assert(var1b == -100);
|
||||
assert(var2b == -2);
|
||||
assert(var3b == -3);
|
||||
|
||||
prepare_input(test_case_3);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nOK\n\nOK\n\nERROR\n") == 0);
|
||||
assert(strcmp(write_results, " CMD3_3:-11,-22,-33 CMD3_3:-1,-2,-3") == 0);
|
||||
|
||||
assert(var1 == 100);
|
||||
assert(var2 == -2);
|
||||
assert(var3 == -3);
|
||||
assert(var1b == 100);
|
||||
assert(var2b == -2);
|
||||
assert(var3b == -3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
168
components/api/lib/cAT/tests/test_write_string_buffer.c
Executable file
168
components/api/lib/cAT/tests/test_write_string_buffer.c
Executable file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char write_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static uint8_t var[8];
|
||||
static size_t var_write_size[4];
|
||||
static int var_write_size_index;
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int cmd_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
strcat(write_results, " CMD:");
|
||||
strncat(write_results, data, data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
var_write_size[var_write_size_index++] = write_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_BUF_STRING,
|
||||
.data = var,
|
||||
.data_size = sizeof(var),
|
||||
.write = var_write
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+SET",
|
||||
.write = cmd_write,
|
||||
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
memset(var, 0, sizeof(var));
|
||||
memset(var_write_size, 0, sizeof(var_write_size));
|
||||
var_write_size_index = 0;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(write_results, 0, sizeof(write_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+SET=0\nAT+SET=\"\\\"abcd\\\"\"\nAT+SET=\"\"a\nAT+SET=\"1122334\"\nAT+SET=\"t\"\r\n";
|
||||
static const char test_case_2[] = "\nAT+SET=\"12345678\"\nAT+SET=\"\"\nAT+SET=\"\\\\\\\\\"\nAT+SET=\"r1\\nr2\\n\"\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n\nOK\n\nERROR\n\nOK\n\r\nOK\r\n") == 0);
|
||||
assert(strcmp(write_results, " CMD:\"\\\"abcd\\\"\" CMD:\"1122334\" CMD:\"t\"") == 0);
|
||||
|
||||
assert(strcmp(var, "t") == 0);
|
||||
|
||||
assert(var_write_size[0] == 6);
|
||||
assert(var_write_size[1] == 7);
|
||||
assert(var_write_size[2] == 1);
|
||||
assert(var_write_size[3] == 0);
|
||||
|
||||
prepare_input(test_case_2);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n\nOK\n\nOK\n\nOK\n") == 0);
|
||||
assert(strcmp(write_results, " CMD:\"\" CMD:\"\\\\\\\\\" CMD:\"r1\\nr2\\n\"") == 0);
|
||||
|
||||
assert(strcmp(var, "r1\nr2\n") == 0);
|
||||
|
||||
assert(var_write_size[0] == 0);
|
||||
assert(var_write_size[1] == 2);
|
||||
assert(var_write_size[2] == 6);
|
||||
assert(var_write_size[3] == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
212
components/api/lib/cAT/tests/test_write_uint_range.c
Executable file
212
components/api/lib/cAT/tests/test_write_uint_range.c
Executable file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Marcin Borowicz
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../src/cat.h"
|
||||
|
||||
static char write_results[256];
|
||||
static char ack_results[256];
|
||||
|
||||
static uint8_t var1, var1b;
|
||||
static uint16_t var2, var2b;
|
||||
static uint32_t var3, var3b;
|
||||
|
||||
static char const *input_text;
|
||||
static size_t input_index;
|
||||
|
||||
static int cmd_write(const struct cat_command *cmd, const uint8_t *data, const size_t data_size, const size_t args_num)
|
||||
{
|
||||
strcat(write_results, " CMD:");
|
||||
strncat(write_results, data, data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var1_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
assert(write_size == 1);
|
||||
var1b = *(uint8_t*)(var->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var2_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
assert(write_size == 2);
|
||||
var2b = *(uint16_t*)(var->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int var3_write(const struct cat_variable *var, size_t write_size)
|
||||
{
|
||||
assert(write_size == 4);
|
||||
var3b = *(uint32_t*)(var->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cat_variable vars[] = {
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var1,
|
||||
.data_size = sizeof(var1),
|
||||
.write = var1_write
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var2,
|
||||
.data_size = sizeof(var2),
|
||||
.write = var2_write
|
||||
},
|
||||
{
|
||||
.type = CAT_VAR_UINT_DEC,
|
||||
.data = &var3,
|
||||
.data_size = sizeof(var3),
|
||||
.write = var3_write
|
||||
}
|
||||
};
|
||||
|
||||
static struct cat_command cmds[] = {
|
||||
{
|
||||
.name = "+SET",
|
||||
.write = cmd_write,
|
||||
|
||||
.var = vars,
|
||||
.var_num = sizeof(vars) / sizeof(vars[0])
|
||||
}
|
||||
};
|
||||
|
||||
static char buf[128];
|
||||
|
||||
static struct cat_command_group cmd_group = {
|
||||
.cmd = cmds,
|
||||
.cmd_num = sizeof(cmds) / sizeof(cmds[0]),
|
||||
};
|
||||
|
||||
static struct cat_command_group *cmd_desc[] = {
|
||||
&cmd_group
|
||||
};
|
||||
|
||||
static struct cat_descriptor desc = {
|
||||
.cmd_group = cmd_desc,
|
||||
.cmd_group_num = sizeof(cmd_desc) / sizeof(cmd_desc[0]),
|
||||
|
||||
.buf = buf,
|
||||
.buf_size = sizeof(buf)
|
||||
};
|
||||
|
||||
static int write_char(char ch)
|
||||
{
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
strcat(ack_results, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_char(char *ch)
|
||||
{
|
||||
if (input_index >= strlen(input_text))
|
||||
return 0;
|
||||
|
||||
*ch = input_text[input_index];
|
||||
input_index++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cat_io_interface iface = {
|
||||
.read = read_char,
|
||||
.write = write_char
|
||||
};
|
||||
|
||||
static void prepare_input(const char *text)
|
||||
{
|
||||
input_text = text;
|
||||
input_index = 0;
|
||||
|
||||
var1 = 1;
|
||||
var2 = 2;
|
||||
var3 = 3;
|
||||
var1b = 10;
|
||||
var2b = 20;
|
||||
var3b = 30;
|
||||
|
||||
memset(ack_results, 0, sizeof(ack_results));
|
||||
memset(write_results, 0, sizeof(write_results));
|
||||
}
|
||||
|
||||
static const char test_case_1[] = "\nAT+SET=-128\nAT+SET=0\nAT+SET=255\nAT+SET=256\n";
|
||||
static const char test_case_2[] = "\nAT+SET=0,-1\nAT+SET=0,0\nAT+SET=0,65535\nAT+SET=1,65536\n";
|
||||
static const char test_case_3[] = "\nAT+SET=0,0,-1\nAT+SET=0,0,0\nAT+SET=1,1,4294967295\nAT+SET=2,2,4294967296\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct cat_object at;
|
||||
|
||||
cat_init(&at, &desc, &iface, NULL);
|
||||
|
||||
prepare_input(test_case_1);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n\nOK\n\nOK\n\nERROR\n") == 0);
|
||||
assert(strcmp(write_results, " CMD:0 CMD:255") == 0);
|
||||
|
||||
assert(var1 == 255);
|
||||
assert(var1b == var1);
|
||||
assert(var2 == 2);
|
||||
assert(var2b == 20);
|
||||
assert(var3 == 3);
|
||||
assert(var3b == 30);
|
||||
|
||||
prepare_input(test_case_2);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n\nOK\n\nOK\n\nERROR\n") == 0);
|
||||
assert(strcmp(write_results, " CMD:0,0 CMD:0,65535") == 0);
|
||||
|
||||
assert(var1 == 1);
|
||||
assert(var1b == var1);
|
||||
assert(var2 == 65535);
|
||||
assert(var2b == var2);
|
||||
assert(var3 == 3);
|
||||
assert(var3b == 30);
|
||||
|
||||
prepare_input(test_case_3);
|
||||
while (cat_service(&at) != 0) {};
|
||||
|
||||
assert(strcmp(ack_results, "\nERROR\n\nOK\n\nOK\n\nERROR\n") == 0);
|
||||
assert(strcmp(write_results, " CMD:0,0,0 CMD:1,1,4294967295") == 0);
|
||||
|
||||
assert(var1 == 2);
|
||||
assert(var1b == var1);
|
||||
assert(var2 == 2);
|
||||
assert(var2b == var2);
|
||||
assert(var3 == 4294967295);
|
||||
assert(var3b == var3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user