Release of version 2.1.0

This commit is contained in:
chaurah
2016-06-23 19:13:52 +00:00
parent e1d998390d
commit 40b80840df
97 changed files with 9255 additions and 1129 deletions

View File

@@ -1,4 +1,23 @@
#Change Log
## [2.1.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.1.0) (Jun 15, 2016)
New features:
- Added unit tests, further details can be found in the testing readme [here](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/README.md)
- Added sample to demonstrate building the SDK as library
- Added sample to demonstrate building the SDK in C++
Bugfixes/Improvements:
- Increased default value of Maximum Reconnect Wait interval to 128 secs
- Increased default value of MQTT Command Timeout in Shadow Connect to 20 secs
- Shadow null/length checks
- Client Id Length not passed correctly in shadow connect
- Add extern C to headers and source files, added sample to demonstrate usage with C++
- Delete/Accepted not being reported, callback added for delete/accepted
- Append IOT_ to all Debug macros (eg. DEBUG is now IOT_DEBUG)
- Fixed exit on error for subscribe_publish_sample
## [2.0.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.0.0) (April 28, 2016)
New features:

575
CppUTestMakefileWorker.mk Normal file
View File

@@ -0,0 +1,575 @@
#---------
#
# MakefileWorker.mk
#
# Include this helper file in your makefile
# It makes
# A static library
# A test executable
#
# See this example for parameter settings
# examples/Makefile
#
#----------
# Inputs - these variables describe what to build
#
# INCLUDE_DIRS - Directories used to search for include files.
# This generates a -I for each directory
# SRC_DIRS - Directories containing source file to built into the library
# SRC_FILES - Specific source files to build into library. Helpful when not all code
# in a directory can be built for test (hopefully a temporary situation)
# TEST_SRC_DIRS - Directories containing unit test code build into the unit test runner
# These do not go in a library. They are explicitly included in the test runner
# TEST_SRC_FILES - Specific source files to build into the unit test runner
# These do not go in a library. They are explicitly included in the test runner
# MOCKS_SRC_DIRS - Directories containing mock source files to build into the test runner
# These do not go in a library. They are explicitly included in the test runner
#----------
# You can adjust these variables to influence how to build the test target
# and where to put and name outputs
# See below to determine defaults
# COMPONENT_NAME - the name of the thing being built
# TEST_TARGET - name the test executable. By default it is
# $(COMPONENT_NAME)_tests
# Helpful if you want 1 > make files in the same directory with different
# executables as output.
# CPPUTEST_HOME - where CppUTest home dir found
# TARGET_PLATFORM - Influences how the outputs are generated by modifying the
# CPPUTEST_OBJS_DIR and CPPUTEST_LIB_DIR to use a sub-directory under the
# normal objs and lib directories. Also modifies where to search for the
# CPPUTEST_LIB to link against.
# CPPUTEST_OBJS_DIR - a directory where o and d files go
# CPPUTEST_LIB_DIR - a directory where libs go
# CPPUTEST_ENABLE_DEBUG - build for debug
# CPPUTEST_USE_MEM_LEAK_DETECTION - Links with overridden new and delete
# CPPUTEST_USE_STD_CPP_LIB - Set to N to keep the standard C++ library out
# of the test harness
# CPPUTEST_USE_GCOV - Turn on coverage analysis
# Clean then build with this flag set to Y, then 'make gcov'
# CPPUTEST_MAPFILE - generate a map file
# CPPUTEST_WARNINGFLAGS - overly picky by default
# OTHER_MAKEFILE_TO_INCLUDE - a hook to use this makefile to make
# other targets. Like CSlim, which is part of fitnesse
# CPPUTEST_USE_VPATH - Use Make's VPATH functionality to support user
# specification of source files and directories that aren't below
# the user's Makefile in the directory tree, like:
# SRC_DIRS += ../../lib/foo
# It defaults to N, and shouldn't be necessary except in the above case.
#----------
#
# Other flags users can initialize to sneak in their settings
# CPPUTEST_CXXFLAGS - flags for the C++ compiler
# CPPUTEST_CPPFLAGS - flags for the C++ AND C preprocessor
# CPPUTEST_CFLAGS - flags for the C complier
# CPPUTEST_LDFLAGS - Linker flags
#----------
# Some behavior is weird on some platforms. Need to discover the platform.
# Platforms
UNAME_OUTPUT = "$(shell uname -a)"
MACOSX_STR = Darwin
MINGW_STR = MINGW
CYGWIN_STR = CYGWIN
LINUX_STR = Linux
SUNOS_STR = SunOS
UNKNWOWN_OS_STR = Unknown
# Compilers
CC_VERSION_OUTPUT ="$(shell $(CXX) -v 2>&1)"
CLANG_STR = clang
SUNSTUDIO_CXX_STR = SunStudio
UNAME_OS = $(UNKNWOWN_OS_STR)
ifeq ($(findstring $(MINGW_STR),$(UNAME_OUTPUT)),$(MINGW_STR))
UNAME_OS = $(MINGW_STR)
endif
ifeq ($(findstring $(CYGWIN_STR),$(UNAME_OUTPUT)),$(CYGWIN_STR))
UNAME_OS = $(CYGWIN_STR)
endif
ifeq ($(findstring $(LINUX_STR),$(UNAME_OUTPUT)),$(LINUX_STR))
UNAME_OS = $(LINUX_STR)
endif
ifeq ($(findstring $(MACOSX_STR),$(UNAME_OUTPUT)),$(MACOSX_STR))
UNAME_OS = $(MACOSX_STR)
#lion has a problem with the 'v' part of -a
UNAME_OUTPUT = "$(shell uname -pmnrs)"
endif
ifeq ($(findstring $(SUNOS_STR),$(UNAME_OUTPUT)),$(SUNOS_STR))
UNAME_OS = $(SUNOS_STR)
SUNSTUDIO_CXX_ERR_STR = CC -flags
ifeq ($(findstring $(SUNSTUDIO_CXX_ERR_STR),$(CC_VERSION_OUTPUT)),$(SUNSTUDIO_CXX_ERR_STR))
CC_VERSION_OUTPUT ="$(shell $(CXX) -V 2>&1)"
COMPILER_NAME = $(SUNSTUDIO_CXX_STR)
endif
endif
ifeq ($(findstring $(CLANG_STR),$(CC_VERSION_OUTPUT)),$(CLANG_STR))
COMPILER_NAME = $(CLANG_STR)
endif
#Kludge for mingw, it does not have cc.exe, but gcc.exe will do
ifeq ($(UNAME_OS),$(MINGW_STR))
CC := gcc
endif
# RHEL5 is always going to use GCC, CC is going for the old verison
CC := gcc
#And another kludge. Exception handling in gcc 4.6.2 is broken when linking the
# Standard C++ library as a shared library. Unbelievable.
ifeq ($(UNAME_OS),$(MINGW_STR))
CPPUTEST_LDFLAGS += -static
endif
ifeq ($(UNAME_OS),$(CYGWIN_STR))
CPPUTEST_LDFLAGS += -static
endif
#Kludge for MacOsX gcc compiler on Darwin9 who can't handle pendantic
ifeq ($(UNAME_OS),$(MACOSX_STR))
ifeq ($(findstring Version 9,$(UNAME_OUTPUT)),Version 9)
CPPUTEST_PEDANTIC_ERRORS = N
endif
endif
ifndef COMPONENT_NAME
COMPONENT_NAME = name_this_in_the_makefile
endif
# Debug on by default
ifndef CPPUTEST_ENABLE_DEBUG
CPPUTEST_ENABLE_DEBUG = Y
endif
# new and delete for memory leak detection on by default
ifndef CPPUTEST_USE_MEM_LEAK_DETECTION
CPPUTEST_USE_MEM_LEAK_DETECTION = Y
endif
# Use the standard C library
ifndef CPPUTEST_USE_STD_C_LIB
CPPUTEST_USE_STD_C_LIB = Y
endif
# Use the standard C++ library
ifndef CPPUTEST_USE_STD_CPP_LIB
CPPUTEST_USE_STD_CPP_LIB = Y
endif
# Use gcov, off by default
ifndef CPPUTEST_USE_GCOV
CPPUTEST_USE_GCOV = N
endif
ifndef CPPUTEST_PEDANTIC_ERRORS
CPPUTEST_PEDANTIC_ERRORS = Y
endif
# Default warnings
ifndef CPPUTEST_WARNINGFLAGS
CPPUTEST_WARNINGFLAGS = -Wall -Wextra -Wswitch-default -Wswitch-enum -Wconversion
ifeq ($(CPPUTEST_PEDANTIC_ERRORS), Y)
CPPUTEST_WARNINGFLAGS += -pedantic-errors
endif
ifeq ($(UNAME_OS),$(LINUX_STR))
# CPPUTEST_WARNINGFLAGS += -Wsign-conversion
endif
CPPUTEST_CXX_WARNINGFLAGS = -Woverloaded-virtual
CPPUTEST_C_WARNINGFLAGS = -Wstrict-prototypes
endif
#Wonderful extra compiler warnings with clang
ifeq ($(COMPILER_NAME),$(CLANG_STR))
# -Wno-disabled-macro-expansion -> Have to disable the macro expansion warning as the operator new overload warns on that.
# -Wno-padded -> I sort-of like this warning but if there is a bool at the end of the class, it seems impossible to remove it! (except by making padding explicit)
# -Wno-global-constructors Wno-exit-time-destructors -> Great warnings, but in CppUTest it is impossible to avoid as the automatic test registration depends on the global ctor and dtor
# -Wno-weak-vtables -> The TEST_GROUP macro declares a class and will automatically inline its methods. Thats ok as they are only in one translation unit. Unfortunately, the warning can't detect that, so it must be disabled.
CPPUTEST_CXX_WARNINGFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-global-constructors -Wno-exit-time-destructors -Wno-weak-vtables
CPPUTEST_C_WARNINGFLAGS += -Weverything -Wno-padded
endif
# Uhm. Maybe put some warning flags for SunStudio here?
ifeq ($(COMPILER_NAME),$(SUNSTUDIO_CXX_STR))
CPPUTEST_CXX_WARNINGFLAGS =
CPPUTEST_C_WARNINGFLAGS =
endif
# Default dir for temporary files (d, o)
ifndef CPPUTEST_OBJS_DIR
ifndef TARGET_PLATFORM
CPPUTEST_OBJS_DIR = objs
else
CPPUTEST_OBJS_DIR = objs/$(TARGET_PLATFORM)
endif
endif
# Default dir for the output library
ifndef CPPUTEST_LIB_DIR
ifndef TARGET_PLATFORM
CPPUTEST_LIB_DIR = testLibs
else
CPPUTEST_LIB_DIR = testLibs/$(TARGET_PLATFORM)
endif
endif
# No map by default
ifndef CPPUTEST_MAP_FILE
CPPUTEST_MAP_FILE = N
endif
# No extentions is default
ifndef CPPUTEST_USE_EXTENSIONS
CPPUTEST_USE_EXTENSIONS = N
endif
# No VPATH is default
ifndef CPPUTEST_USE_VPATH
CPPUTEST_USE_VPATH := N
endif
# Make empty, instead of 'N', for usage in $(if ) conditionals
ifneq ($(CPPUTEST_USE_VPATH), Y)
CPPUTEST_USE_VPATH :=
endif
ifndef TARGET_PLATFORM
CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_BUILD_LIB)
else
CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_BUILD_LIB)/$(TARGET_PLATFORM)
endif
# --------------------------------------
# derived flags in the following area
# --------------------------------------
# Without the C library, we'll need to disable the C++ library and ...
ifeq ($(CPPUTEST_USE_STD_C_LIB), N)
CPPUTEST_USE_STD_CPP_LIB = N
CPPUTEST_USE_MEM_LEAK_DETECTION = N
CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_C_LIB_DISABLED
CPPUTEST_CPPFLAGS += -nostdinc
endif
CPPUTEST_CPPFLAGS += -DCPPUTEST_COMPILATION
ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N)
CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED
else
ifndef CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE
CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include $(CPPUTEST_INCLUDE)/CppUTest/MemoryLeakDetectorNewMacros.h
endif
ifndef CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE
CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(CPPUTEST_INCLUDE)/CppUTest/MemoryLeakDetectorMallocMacros.h
endif
endif
ifeq ($(CPPUTEST_ENABLE_DEBUG), Y)
CPPUTEST_CXXFLAGS += -g
CPPUTEST_CFLAGS += -g
CPPUTEST_LDFLAGS += -g
endif
ifeq ($(CPPUTEST_USE_STD_CPP_LIB), N)
CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED
ifeq ($(CPPUTEST_USE_STD_C_LIB), Y)
CPPUTEST_CXXFLAGS += -nostdinc++
endif
endif
ifdef $(GMOCK_HOME)
GTEST_HOME = $(GMOCK_HOME)/gtest
CPPUTEST_CPPFLAGS += -I$(GMOCK_HOME)/include
GMOCK_LIBRARY = $(GMOCK_HOME)/lib/.libs/libgmock.a
LD_LIBRARIES += $(GMOCK_LIBRARY)
CPPUTEST_CPPFLAGS += -DINCLUDE_GTEST_TESTS
CPPUTEST_WARNINGFLAGS =
CPPUTEST_CPPFLAGS += -I$(GTEST_HOME)/include -I$(GTEST_HOME)
GTEST_LIBRARY = $(GTEST_HOME)/lib/.libs/libgtest.a
LD_LIBRARIES += $(GTEST_LIBRARY)
endif
ifeq ($(CPPUTEST_USE_GCOV), Y)
CPPUTEST_CXXFLAGS += -fprofile-arcs -ftest-coverage
CPPUTEST_CFLAGS += -fprofile-arcs -ftest-coverage
endif
CPPUTEST_CXXFLAGS += $(CPPUTEST_WARNINGFLAGS) $(CPPUTEST_CXX_WARNINGFLAGS)
CPPUTEST_CPPFLAGS += $(CPPUTEST_WARNINGFLAGS)
CPPUTEST_CXXFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE)
CPPUTEST_CPPFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE)
CPPUTEST_CFLAGS += $(CPPUTEST_C_WARNINGFLAGS)
TARGET_MAP = $(COMPONENT_NAME).map.txt
ifeq ($(CPPUTEST_MAP_FILE), Y)
CPPUTEST_LDFLAGS += -Wl,-map,$(TARGET_MAP)
endif
# Link with CppUTest lib
CPPUTEST_LIB = $(CPPUTEST_LIB_LINK_DIR)/libCppUTest.a
ifeq ($(CPPUTEST_USE_EXTENSIONS), Y)
CPPUTEST_LIB += $(CPPUTEST_LIB_LINK_DIR)/libCppUTestExt.a
endif
ifdef CPPUTEST_STATIC_REALTIME
LD_LIBRARIES += -lrt
endif
TARGET_LIB = \
$(CPPUTEST_LIB_DIR)/lib$(COMPONENT_NAME).a
ifndef TEST_TARGET
ifndef TARGET_PLATFORM
TEST_TARGET = $(COMPONENT_NAME)_tests
else
TEST_TARGET = $(COMPONENT_NAME)_$(TARGET_PLATFORM)_tests
endif
endif
#Helper Functions
get_src_from_dir = $(wildcard $1/*.cpp) $(wildcard $1/*.cc) $(wildcard $1/*.c)
get_dirs_from_dirspec = $(wildcard $1)
get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir)))
__src_to = $(subst .c,$1, $(subst .cc,$1, $(subst .cpp,$1,$(if $(CPPUTEST_USE_VPATH),$(notdir $2),$2))))
src_to = $(addprefix $(CPPUTEST_OBJS_DIR)/,$(call __src_to,$1,$2))
src_to_o = $(call src_to,.o,$1)
src_to_d = $(call src_to,.d,$1)
src_to_gcda = $(call src_to,.gcda,$1)
src_to_gcno = $(call src_to,.gcno,$1)
time = $(shell date +%s)
delta_t = $(eval minus, $1, $2)
debug_print_list = $(foreach word,$1,echo " $(word)";) echo;
#Derived
STUFF_TO_CLEAN += $(TEST_TARGET) $(TEST_TARGET).exe $(TARGET_LIB) $(TARGET_MAP)
SRC += $(call get_src_from_dir_list, $(SRC_DIRS)) $(SRC_FILES)
OBJ = $(call src_to_o,$(SRC))
STUFF_TO_CLEAN += $(OBJ)
TEST_SRC += $(call get_src_from_dir_list, $(TEST_SRC_DIRS)) $(TEST_SRC_FILES)
TEST_OBJS = $(call src_to_o,$(TEST_SRC))
STUFF_TO_CLEAN += $(TEST_OBJS)
MOCKS_SRC += $(call get_src_from_dir_list, $(MOCKS_SRC_DIRS))
MOCKS_OBJS = $(call src_to_o,$(MOCKS_SRC))
STUFF_TO_CLEAN += $(MOCKS_OBJS)
ALL_SRC = $(SRC) $(TEST_SRC) $(MOCKS_SRC)
# If we're using VPATH
ifeq ($(CPPUTEST_USE_VPATH), Y)
# gather all the source directories and add them
VPATH += $(sort $(dir $(ALL_SRC)))
# Add the component name to the objs dir path, to differentiate between same-name objects
CPPUTEST_OBJS_DIR := $(addsuffix /$(COMPONENT_NAME),$(CPPUTEST_OBJS_DIR))
endif
#LCOV html generation
BUILD_OUTPUT_DIR=build_output
COVERAGE_DIR=$(BUILD_OUTPUT_DIR)/generated-coverage
LCOV_INFO_FILE=$(TEST_TARGET).info
LCOV_SUMMARY_FILE=$(TEST_TARGET)_summary.info
#Test coverage with gcov
GCOV_OUTPUT = gcov_output.txt
GCOV_REPORT = gcov_report.txt
GCOV_ERROR = gcov_error.txt
GCOV_GCDA_FILES = $(call src_to_gcda, $(ALL_SRC))
GCOV_GCNO_FILES = $(call src_to_gcno, $(ALL_SRC))
TEST_OUTPUT = $(TEST_TARGET).txt
STUFF_TO_CLEAN += \
$(GCOV_OUTPUT)\
$(GCOV_REPORT)\
$(GCOV_REPORT).html\
$(GCOV_ERROR)\
$(GCOV_GCDA_FILES)\
$(GCOV_GCNO_FILES)\
$(TEST_OUTPUT)
#The gcda files for gcov need to be deleted before each run
#To avoid annoying messages.
GCOV_CLEAN = $(SILENCE)$(RM) -f $(GCOV_GCDA_FILES) $(GCOV_OUTPUT) $(GCOV_REPORT) $(GCOV_ERROR)
RUN_TEST_TARGET = $(SILENCE) $(GCOV_CLEAN) ; echo "Running $(TEST_TARGET)"; ./$(TEST_TARGET) $(CPPUTEST_EXE_FLAGS)
ifeq ($(CPPUTEST_USE_GCOV), Y)
ifeq ($(COMPILER_NAME),$(CLANG_STR))
LD_LIBRARIES += --coverage
else
LD_LIBRARIES += -lgcov
endif
endif
INCLUDES_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(INCLUDE_DIRS))
INCLUDES += $(foreach dir, $(INCLUDES_DIRS_EXPANDED), -I$(dir))
MOCK_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(MOCKS_SRC_DIRS))
INCLUDES += $(foreach dir, $(MOCK_DIRS_EXPANDED), -I$(dir))
CPPUTEST_CPPFLAGS += $(INCLUDES)
DEP_FILES = $(call src_to_d, $(ALL_SRC))
STUFF_TO_CLEAN += $(DEP_FILES) $(PRODUCTION_CODE_START) $(PRODUCTION_CODE_END)
STUFF_TO_CLEAN += $(STDLIB_CODE_START) $(MAP_FILE) cpputest_*.xml junit_run_output
# We'll use the CPPUTEST_CFLAGS etc so that you can override AND add to the CppUTest flags
CFLAGS = $(CPPUTEST_CFLAGS) $(CPPUTEST_ADDITIONAL_CFLAGS)
CPPFLAGS = $(CPPUTEST_CPPFLAGS) $(CPPUTEST_ADDITIONAL_CPPFLAGS)
CXXFLAGS = $(CPPUTEST_CXXFLAGS) $(CPPUTEST_ADDITIONAL_CXXFLAGS)
LDFLAGS = $(CPPUTEST_LDFLAGS) $(CPPUTEST_ADDITIONAL_LDFLAGS)
# Don't consider creating the archive a warning condition that does STDERR output
ARFLAGS := $(ARFLAGS)c
DEP_FLAGS=-MMD -MP
# Some macros for programs to be overridden. For some reason, these are not in Make defaults
RANLIB = ranlib
# Targets
ALL_TARGETS += cpputest_all
ALL_TARGETS_CLEAN += cpputest_clean
.PHONY: cpputest_all
cpputest_all: start $(TEST_TARGET) gcov
$(RUN_TEST_TARGET)
.PHONY: start
start: $(TEST_TARGET)
$(SILENCE)START_TIME=$(call time)
.PHONY: all_no_tests
all_no_tests: $(TEST_TARGET)
.PHONY: flags
flags:
@echo
@echo "OS ${UNAME_OS}"
@echo "Compile C and C++ source with CPPFLAGS:"
@$(call debug_print_list,$(CPPFLAGS))
@echo "Compile C++ source with CXXFLAGS:"
@$(call debug_print_list,$(CXXFLAGS))
@echo "Compile C source with CFLAGS:"
@$(call debug_print_list,$(CFLAGS))
@echo "Link with LDFLAGS:"
@$(call debug_print_list,$(LDFLAGS))
@echo "Link with LD_LIBRARIES:"
@$(call debug_print_list,$(LD_LIBRARIES))
@echo "Create libraries with ARFLAGS:"
@$(call debug_print_list,$(ARFLAGS))
TEST_DEPS = $(TEST_OBJS) $(MOCKS_OBJS) $(PRODUCTION_CODE_START) $(TARGET_LIB) $(USER_LIBS) $(PRODUCTION_CODE_END) $(CPPUTEST_LIB) $(STDLIB_CODE_START)
test-deps: $(TEST_DEPS)
$(TEST_TARGET): $(TEST_DEPS)
@echo Linking $@
$(SILENCE)$(CXX) -o $@ $^ $(LD_LIBRARIES) $(LDFLAGS)
$(TARGET_LIB): $(OBJ)
@echo Building archive $@
$(SILENCE)mkdir -p $(dir $@)
$(SILENCE)$(AR) $(ARFLAGS) $@ $^
$(SILENCE)$(RANLIB) $@
test: $(TEST_TARGET)
$(RUN_TEST_TARGET) $(COMMAND_LINE_ARGUMENTS) | tee $(TEST_OUTPUT)
vtest: $(TEST_TARGET)
$(RUN_TEST_TARGET) -v | tee $(TEST_OUTPUT)
$(CPPUTEST_OBJS_DIR)/%.o: %.cc
@echo compiling $(notdir $<)
$(SILENCE)mkdir -p $(dir $@)
$(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $<
$(CPPUTEST_OBJS_DIR)/%.o: %.cpp
@echo compiling $(notdir $<)
$(SILENCE)mkdir -p $(dir $@)
$(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $<
$(CPPUTEST_OBJS_DIR)/%.o: %.c
@echo compiling $(notdir $<)
$(SILENCE)mkdir -p $(dir $@)
$(SILENCE)$(COMPILE.c) $(DEP_FLAGS) $(OUTPUT_OPTION) $<
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP_FILES)
endif
.PHONY: cpputest_clean
cpputest_clean:
@echo Making clean
$(SILENCE)$(RM) $(STUFF_TO_CLEAN)
$(SILENCE)$(RM) -rf gcov $(CPPUTEST_OBJS_DIR)
$(SILENCE)find . -name "*.gcno" | xargs $(RM) -f
$(SILENCE)find . -name "*.gcda" | xargs $(RM) -f
#realclean gets rid of all gcov, o and d files in the directory tree
#not just the ones made by this makefile
.PHONY: realclean
realclean: clean
$(SILENCE)$(RM) -rf gcov
$(SILENCE)$(RM) -rf $(BUILD_OUTPUT_DIR)
$(SILENCE)find . -name "*.gdcno" | xargs $(RM) -f
$(SILENCE)find . -name "*.[do]" | xargs $(RM) -f
gcov: test
$(SILENCE)mkdir -p $(BUILD_OUTPUT_DIR)
ifeq ($(CPPUTEST_USE_VPATH), Y)
$(SILENCE)gcov --object-directory $(CPPUTEST_OBJS_DIR) $(SRC) >> $(GCOV_OUTPUT) 2>> $(GCOV_ERROR)
else
$(SILENCE)for d in $(SRC_DIRS) ; do \
FILES=`ls $$d/*.c $$d/*.cc $$d/*.cpp 2> /dev/null` ; \
gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$d $$FILES >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \
done
$(SILENCE)for f in $(SRC_FILES) ; do \
gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$f $$f >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \
done
endif
$(SILENCE)./filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT)
$(SILENCE)mkdir -p gcov
$(SILENCE)mv *.gcov gcov
$(SILENCE)mv gcov_* gcov
$(SILENCE)mkdir -p $(COVERAGE_DIR)
$(SILENCE)lcov -d $(CPPUTEST_OBJS_DIR) -c -o $(COVERAGE_DIR)/$(LCOV_INFO_FILE) -q --rc lcov_branch_coverage=1
$(SILENCE)lcov --remove $(COVERAGE_DIR)/$(LCOV_INFO_FILE) $(LCOV_EXCLUDE_PATTERN) -o $(COVERAGE_DIR)/$(LCOV_INFO_FILE)
$(SILENCE)lcov --remove $(COVERAGE_DIR)/$(LCOV_INFO_FILE) "*CppUTest*" -o $(COVERAGE_DIR)/$(LCOV_INFO_FILE)
$(SILENCE)lcov --summary ./$(COVERAGE_DIR)/$(LCOV_INFO_FILE) &> $(COVERAGE_DIR)/$(LCOV_SUMMARY_FILE)
$(SILENCE)echo ansic:line:`grep -E -o "([0-9]*\.[0-9]+|[0-9]+)" $(COVERAGE_DIR)/$(LCOV_SUMMARY_FILE) | head -1` >> $(COVERAGE_DIR)/coverage-data.txt
$(SILENCE)genhtml -o $(COVERAGE_DIR) $(COVERAGE_DIR)/$(LCOV_INFO_FILE) -q --rc lcov_branch_coverage=1
@echo "See gcov directory for details"
.PHONEY: format
format:
$(CPPUTEST_HOME)/scripts/reformat.sh $(PROJECT_HOME_DIR)
.PHONEY: debug
debug:
@echo
@echo "Target Source files:"
@$(call debug_print_list,$(SRC))
@echo "Target Object files:"
@$(call debug_print_list,$(OBJ))
@echo "Test Source files:"
@$(call debug_print_list,$(TEST_SRC))
@echo "Test Object files:"
@$(call debug_print_list,$(TEST_OBJS))
@echo "Mock Source files:"
@$(call debug_print_list,$(MOCKS_SRC))
@echo "Mock Object files:"
@$(call debug_print_list,$(MOCKS_OBJS))
@echo "All Input Dependency files:"
@$(call debug_print_list,$(DEP_FILES))
@echo Stuff to clean:
@$(call debug_print_list,$(STUFF_TO_CLEAN))
@echo Includes:
@$(call debug_print_list,$(INCLUDES))
-include $(OTHER_MAKEFILE_TO_INCLUDE)

View File

@@ -128,7 +128,7 @@ The threading layer provides the implementation of mutexes used for thread-safe
###Sample Porting:
Marvell has ported an older version of the SDK to its IoT Starter kit. [These](https://github.com/marvell-iot/aws_starter_sdk/tree/master/wmsdk/external/aws_iot/aws_iot_src/protocol/mqtt/aws_iot_embedded_client_wrapper/platform_wmsdk) files are example implementations of the above mentioned functions.
Marvell has ported an older version of the SDK to its IoT Starter kit. [These](https://github.com/marvell-iot/aws_starter_sdk/tree/master/sdk/external/aws_iot/aws_iot_src/protocol/mqtt/aws_iot_embedded_client_wrapper/platform_wmsdk) files are example implementations of the above mentioned functions.
This provides a port of the timer and network layer. The threading layer is not a part of this port.
##Time source for certificate validation
@@ -147,4 +147,4 @@ There is a validation test for the multi-threaded implementation that can be fou
##Sample applications
The sample apps in this SDK provide a working implementation for mbedTLS. They use a reference implementation for linux provided with the SDK. Threading layer is enabled in the subscribe publish sample.
The sample apps in this SDK provide a working implementation for mbedTLS. They use a reference implementation for linux provided with the SDK. Threading layer is enabled in the subscribe publish sample.

View File

@@ -27,7 +27,7 @@ Ensure you understand the AWS IoT platform and create the necessary certificates
In order to quickly get started with the AWS IoT platform, we have ported the SDK for POSIX type Operating Systems like Ubuntu, OS X and RHEL. The SDK is configured for the mbedTLS library and can be built out of the box with *GCC* using *make utility*. The tarball can be downloaded from the below link:
* [mbedTLS from ARM](https://s3.amazonaws.com/aws-iot-device-sdk-embedded-c/linux_mqtt_mbedtls-2.0.0.tar)
* [mbedTLS from ARM](https://s3.amazonaws.com/aws-iot-device-sdk-embedded-c/linux_mqtt_mbedtls-2.1.0.tar)
##Installation
This section explains the individual steps to retrieve the necessary files and be able to build your first application using the AWS IoT device SDK for embedded C.
@@ -39,7 +39,7 @@ Steps:
* Download the SDK to device and place in the newly created directory
* Expand the tarball (tar -xf <tarball.tar>). This will create the below directories:
* `certs` - TLS certificates directory
* `docs` - SDK API and file documentation
* `docs` - SDK API and file documentation. This folder is not present on GitHub. You can access the documentation [here](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html)
* `external_libs` - The mbedTLS and jsmn source files
* `include` - The AWS IoT SDK header files
* `platform` - Platform specific files for timer, TLS and threading layers

4
certs/README.txt Normal file
View File

@@ -0,0 +1,4 @@
# Copy certificates for running the samples and tests provided with the SDK into this directory
# Certificates can be created and downloaded from the AWS IoT Console
# The IoT Client takes the full path of the certificates as an input parameter while initializing
# This is the default folder for the certificates only for samples and tests. A different path can be specified if required.

View File

@@ -0,0 +1,2 @@
# Copy source code for CppUTest into this directory
# The SDK was tested internally with CppUTest v3.6 which can be found here - https://github.com/cpputest/cpputest/releases/tag/v3.6

View File

@@ -1 +1,2 @@
# Copy source code for mbedTLS into this directory
# Copy source code for mbedTLS into this directory
# The SDK was tested internally with mbedTLS v2.1.1 which can be found here - https://github.com/ARMmbed/mbedtls/releases/tag/mbedtls-2.1.1

63
filterGcov.sh Executable file
View File

@@ -0,0 +1,63 @@
#!/bin/bash
INPUT_FILE=$1
TEMP_FILE1=${INPUT_FILE}1.tmp
TEMP_FILE2=${INPUT_FILE}2.tmp
TEMP_FILE3=${INPUT_FILE}3.tmp
ERROR_FILE=$2
OUTPUT_FILE=$3
HTML_OUTPUT_FILE=$3.html
TEST_RESULTS=$4
flattenGcovOutput() {
while read line1
do
read line2
echo $line2 " " $line1
read junk
read junk
done < ${INPUT_FILE}
}
getRidOfCruft() {
sed '-e s/^Lines.*://g' \
'-e s/^[0-9]\./ &/g' \
'-e s/^[0-9][0-9]\./ &/g' \
'-e s/of.*File/ /g' \
"-e s/'//g" \
'-e s/^.*\/usr\/.*$//g' \
'-e s/^.*\.$//g'
}
flattenPaths() {
sed \
-e 's/\/[^/][^/]*\/[^/][^/]*\/\.\.\/\.\.\//\//g' \
-e 's/\/[^/][^/]*\/[^/][^/]*\/\.\.\/\.\.\//\//g' \
-e 's/\/[^/][^/]*\/[^/][^/]*\/\.\.\/\.\.\//\//g' \
-e 's/\/[^/][^/]*\/\.\.\//\//g'
}
getFileNameRootFromErrorFile() {
sed '-e s/gc..:cannot open .* file//g' ${ERROR_FILE}
}
writeEachNoTestCoverageFile() {
while read line
do
echo " 0.00% " ${line}
done
}
createHtmlOutput() {
echo "<table border="2" cellspacing="5" cellpadding="5">"
echo "<tr><th>Coverage</th><th>File</th></tr>"
sed "-e s/.*% /<tr><td>&<\/td><td>/" \
"-e s/[a-zA-Z0-9_]*\.[ch][a-z]*/<a href='file:\.\/&.gcov'>&<\/a><\/td><\/tr>/"
echo "</table>"
sed "-e s/.*/&<br>/g" < ${TEST_RESULTS}
}
flattenGcovOutput | getRidOfCruft | flattenPaths > ${TEMP_FILE1}
getFileNameRootFromErrorFile | writeEachNoTestCoverageFile | flattenPaths > ${TEMP_FILE2}
cat ${TEMP_FILE1} ${TEMP_FILE2} | sort | uniq > ${OUTPUT_FILE}
createHtmlOutput < ${OUTPUT_FILE} > ${HTML_OUTPUT_FILE}
rm -f ${TEMP_FILE1} ${TEMP_FILE2}

View File

@@ -21,6 +21,10 @@
#ifndef AWS_IOT_SDK_SRC_IOT_ERROR_H_
#define AWS_IOT_SDK_SRC_IOT_ERROR_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Used to avoid warnings in case of unused parameters in function pointers */
#define IOT_UNUSED(x) (void)(x)
@@ -57,7 +61,7 @@ typedef enum {
/** The TLS handshake failed */
SSL_CONNECTION_ERROR = -4,
/** Error associated with setting up the parameters of a Socket */
TCP_SETUP_ERROR =-5,
TCP_SETUP_ERROR = -5,
/** A timeout occurred while waiting for the TLS handshake to complete. */
NETWORK_SSL_CONNECT_TIMEOUT_ERROR = -6,
/** A Generic write error based on the platform used */
@@ -65,7 +69,7 @@ typedef enum {
/** SSL initialization error at the TLS layer */
NETWORK_SSL_INIT_ERROR = -8,
/** An error occurred when loading the certificates. The certificates could not be located or are incorrectly formatted. */
NETWORK_SSL_CERT_ERROR= -9,
NETWORK_SSL_CERT_ERROR = -9,
/** SSL Write times out */
NETWORK_SSL_WRITE_TIMEOUT_ERROR = -10,
/** SSL Read times out */
@@ -122,7 +126,7 @@ typedef enum {
/** Connect request failed with the server returning an unknown error */
MQTT_CONNACK_UNKNOWN_ERROR = -36,
/** Connect request failed with the server returning an unacceptable protocol version error */
MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = -37,
MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = -37,
/** Connect request failed with the server returning an identifier rejected error */
MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR = -38,
/** Connect request failed with the server returning an unavailable error */
@@ -147,6 +151,10 @@ typedef enum {
MUTEX_UNLOCK_ERROR = -48,
/** Mutex destroy failed */
MUTEX_DESTROY_ERROR = -49,
}IoT_Error_t;
} IoT_Error_t;
#ifdef __cplusplus
}
#endif
#endif /* AWS_IOT_SDK_SRC_IOT_ERROR_H_ */

View File

@@ -25,6 +25,10 @@
#ifndef AWS_IOT_SDK_SRC_JSON_UTILS_H_
#define AWS_IOT_SDK_SRC_JSON_UTILS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
@@ -186,4 +190,8 @@ IoT_Error_t parseBooleanValue(bool *b, const char *jsonString, jsmntok_t *token)
*/
IoT_Error_t parseStringValue(char *buf, const char *jsonString, jsmntok_t *token);
#ifdef __cplusplus
}
#endif
#endif /* AWS_IOT_SDK_SRC_JSON_UTILS_H_ */

View File

@@ -28,6 +28,10 @@
#ifndef _IOT_LOG_H
#define _IOT_LOG_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
@@ -36,15 +40,15 @@
*
* Macro to expose function, line number as well as desired log message.
*/
#ifdef IOT_DEBUG
#define DEBUG(...) \
{\
printf("DEBUG: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \
printf(__VA_ARGS__); \
printf("\n"); \
}
#ifdef ENABLE_IOT_DEBUG
#define IOT_DEBUG(...) \
{\
printf("DEBUG: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \
printf(__VA_ARGS__); \
printf("\n"); \
}
#else
#define DEBUG(...)
#define IOT_DEBUG(...)
#endif
/**
@@ -52,22 +56,23 @@
*
* Macro to print message function entry and exit
*/
#ifdef IOT_TRACE
#ifdef ENABLE_IOT_TRACE
#define FUNC_ENTRY \
{\
printf("FUNC_ENTRY: %s L#%d \n", __PRETTY_FUNCTION__, __LINE__); \
}
{\
printf("FUNC_ENTRY: %s L#%d \n", __PRETTY_FUNCTION__, __LINE__); \
}
#define FUNC_EXIT \
{\
printf("FUNC_EXIT: %s L#%d \n", __PRETTY_FUNCTION__, __LINE__); \
}
{\
printf("FUNC_EXIT: %s L#%d \n", __PRETTY_FUNCTION__, __LINE__); \
}
#define FUNC_EXIT_RC(x) \
{\
printf("FUNC_EXIT: %s L#%d Return Code : %d \n", __PRETTY_FUNCTION__, __LINE__, x); \
return x; \
}
{\
printf("FUNC_EXIT: %s L#%d Return Code : %d \n", __PRETTY_FUNCTION__, __LINE__, x); \
return x; \
}
#else
#define FUNC_ENTRY
#define FUNC_EXIT
#define FUNC_EXIT_RC(x) { return x; }
#endif
@@ -77,14 +82,14 @@
*
* Macro to expose desired log message. Info messages do not include automatic function names and line numbers.
*/
#ifdef IOT_INFO
#define INFO(...) \
{\
printf(__VA_ARGS__); \
printf("\n"); \
}
#ifdef ENABLE_IOT_INFO
#define IOT_INFO(...) \
{\
printf(__VA_ARGS__); \
printf("\n"); \
}
#else
#define INFO(...)
#define IOT_INFO(...)
#endif
/**
@@ -92,15 +97,15 @@
*
* Macro to expose function, line number as well as desired log message.
*/
#ifdef IOT_WARN
#define WARN(...) \
{ \
printf("WARN: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \
printf(__VA_ARGS__); \
printf("\n"); \
}
#ifdef ENABLE_IOT_WARN
#define IOT_WARN(...) \
{ \
printf("WARN: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \
printf(__VA_ARGS__); \
printf("\n"); \
}
#else
#define WARN(...)
#define IOT_WARN(...)
#endif
/**
@@ -108,17 +113,19 @@
*
* Macro to expose function, line number as well as desired log message.
*/
#ifdef IOT_ERROR
#define ERROR(...) \
{ \
printf("ERROR: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \
printf(__VA_ARGS__); \
printf("\n"); \
}
#ifdef ENABLE_IOT_ERROR
#define IOT_ERROR(...) \
{ \
printf("ERROR: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \
printf(__VA_ARGS__); \
printf("\n"); \
}
#else
#define ERROR(...)
#define IOT_ERROR(...)
#endif
#ifdef __cplusplus
}
#endif
#endif // _IOT_LOG_H

View File

@@ -39,6 +39,10 @@
#ifndef AWS_IOT_SDK_SRC_IOT_MQTT_CLIENT_H
#define AWS_IOT_SDK_SRC_IOT_MQTT_CLIENT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Library Header files */
#include "stdio.h"
#include "stdbool.h"
@@ -166,16 +170,22 @@ typedef struct {
char *pDeviceCertLocation; ///< Pointer to a string defining the device identity certificate file (full file, not path)
char *pDevicePrivateKeyLocation; ///< Pointer to a string defining the device private key file (full file, not path)
uint32_t mqttCommandTimeout_ms; ///< Timeout for MQTT blocking calls. In milliseconds
#ifdef _ENABLE_THREAD_SUPPORT_
bool isBlockOnThreadLockEnabled; ///< Timeout for Thread blocking calls. Set to 0 to block until lock is obtained. In milliseconds
#endif
uint32_t tlsHandshakeTimeout_ms; ///< TLS handshake timeout. In milliseconds
bool isSSLHostnameVerify; ///< Client should perform server certificate hostname validation
iot_disconnect_handler disconnectHandler; ///< Callback to be invoked upon connection loss
void *disconnectHandlerData; ///< Data to pass as argument when disconnect handler is called
#ifdef _ENABLE_THREAD_SUPPORT_
bool isBlockOnThreadLockEnabled; ///< Timeout for Thread blocking calls. Set to 0 to block until lock is obtained. In milliseconds
#endif
} IoT_Client_Init_Params;
extern const IoT_Client_Init_Params iotClientInitParamsDefault;
#ifdef _ENABLE_THREAD_SUPPORT_
#define IoT_Client_Init_Params_initializer { true, NULL, 0, NULL, NULL, NULL, 20000, 5000, true, NULL, NULL, false }
#else
#define IoT_Client_Init_Params_initializer { true, NULL, 0, NULL, NULL, NULL, 20000, 5000, true, NULL, NULL }
#endif
/**
* @brief MQTT Client State Type
*
@@ -399,4 +409,8 @@ uint32_t aws_iot_mqtt_get_network_disconnected_count(AWS_IoT_Client *pClient);
*/
void aws_iot_mqtt_reset_network_disconnected_count(AWS_IoT_Client *pClient);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -39,6 +39,10 @@
#ifndef AWS_IOT_SDK_SRC_IOT_COMMON_INTERNAL_H
#define AWS_IOT_SDK_SRC_IOT_COMMON_INTERNAL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#include <string.h>
@@ -63,26 +67,26 @@ typedef enum msgTypes {
PINGREQ = 12,
PINGRESP = 13,
DISCONNECT = 14
}MessageTypes;
} MessageTypes;
/**
* Bitfields for the MQTT header byte.
*/
typedef union {
unsigned char byte; /**< the whole byte */
unsigned char byte; /**< the whole byte */
#if defined(REVERSED)
struct {
unsigned int type : 4; /**< message type nibble */
unsigned int dup : 1; /**< DUP flag bit */
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
unsigned int retain : 1; /**< retained flag bit */
unsigned int type : 4; /**< message type nibble */
unsigned int dup : 1; /**< DUP flag bit */
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
unsigned int retain : 1; /**< retained flag bit */
} bits;
#else
struct {
unsigned int retain : 1; /**< retained flag bit */
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
unsigned int dup : 1; /**< DUP flag bit */
unsigned int type : 4; /**< message type nibble */
unsigned int retain : 1; /**< retained flag bit */
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
unsigned int dup : 1; /**< DUP flag bit */
unsigned int type : 4; /**< message type nibble */
} bits;
#endif
} MQTTHeader;
@@ -131,4 +135,8 @@ IoT_Error_t aws_iot_mqtt_client_unlock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_
#endif
#ifdef __cplusplus
}
#endif
#endif /* AWS_IOT_SDK_SRC_IOT_COMMON_INTERNAL_H */

View File

@@ -39,6 +39,10 @@
#ifndef AWS_IOT_SDK_SRC_IOT_MQTT_INTERFACE_H
#define AWS_IOT_SDK_SRC_IOT_MQTT_INTERFACE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Library Header files */
#include "stdio.h"
#include "stdbool.h"
@@ -188,4 +192,8 @@ IoT_Error_t aws_iot_mqtt_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms);
*/
IoT_Error_t aws_iot_mqtt_attempt_reconnect(AWS_IoT_Client *pClient);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -16,10 +16,18 @@
#ifndef SRC_SHADOW_AWS_IOT_SHADOW_ACTIONS_H_
#define SRC_SHADOW_AWS_IOT_SHADOW_ACTIONS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "aws_iot_shadow_interface.h"
IoT_Error_t iot_shadow_action(const char *pThingName, ShadowActions_t action,
const char *pJsonDocumentToBeSent, fpActionCallback_t callback, void *pCallbackContext,
uint32_t timeout_seconds, bool isSticky);
IoT_Error_t aws_iot_shadow_internal_action(const char *pThingName, ShadowActions_t action,
const char *pJsonDocumentToBeSent, fpActionCallback_t callback,
void *pCallbackContext, uint32_t timeout_seconds, bool isSticky);
#ifdef __cplusplus
}
#endif
#endif /* SRC_SHADOW_AWS_IOT_SHADOW_ACTIONS_H_ */

View File

@@ -15,6 +15,10 @@
#ifndef AWS_IOT_SDK_SRC_IOT_SHADOW_H_
#define AWS_IOT_SDK_SRC_IOT_SHADOW_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file aws_iot_shadow_interface.h
@@ -51,8 +55,8 @@ typedef struct {
char *pRootCA; ///< Location with the Filename of the Root CA
char *pClientCRT; ///< Location of Device certs signed by AWS IoT service
char *pClientKey; ///< Location of Device private key
bool enableAutoReconnect; ///< Set to true to enable auto reconnect
iot_disconnect_handler disconnectHandler; ///< Callback to be invoked upon connection loss.
bool enableAutoReconnect; ///< Set to true to enable auto reconnect
iot_disconnect_handler disconnectHandler; ///< Callback to be invoked upon connection loss.
} ShadowInitParameters_t;
/*!
@@ -67,6 +71,8 @@ typedef struct {
typedef struct {
char *pMyThingName; ///< Every device has a Thing Shadow and this is the placeholder for name
char *pMqttClientId; ///< Currently the Shadow uses MQTT to connect and it is important to ensure we have unique client id
uint16_t mqttClientIdLen; ///< Currently the Shadow uses MQTT to connect and it is important to ensure we have unique client id
pApplicationHandler_t deleteActionHandler; ///< Callback to be invoked when Thing shadow for this device is deleted
} ShadowConnectParameters_t;
/*!
@@ -79,6 +85,9 @@ extern const ShadowInitParameters_t ShadowInitParametersDefault;
/*!
* @brief This is set to defaults from the configuration file
* The length of the client id is initialized as 0. This is due to C language limitations of using constant literals
* only for creating const variables. The client id will be assigned using the value from aws_iot_config.h but the
* length needs to be assigned in code. shadow_sample.c file demonstrates this.
*
* \relates ShadowConnectParameters_t
*/
@@ -88,12 +97,13 @@ extern const ShadowConnectParameters_t ShadowConnectParametersDefault;
/**
* @brief Initialize the Thing Shadow before use
*
* This function takes care of initializing the internal book-keeping data structures
* This function takes care of initializing the internal book-keeping data structures and initializing the IoT client.
*
* @param pClient MQTT Client used as the protocol layer
* @param pClient A new MQTT Client to be used as the protocol layer. Will be initialized with pParams.
* @return An IoT Error Type defining successful/failed Initialization
*/
IoT_Error_t aws_iot_shadow_init(AWS_IoT_Client *pClient, ShadowInitParameters_t *pParams);
/**
* @brief Connect to the AWS IoT Thing Shadow service over MQTT
*
@@ -104,6 +114,7 @@ IoT_Error_t aws_iot_shadow_init(AWS_IoT_Client *pClient, ShadowInitParameters_t
* @return An IoT Error Type defining successful/failed Connection
*/
IoT_Error_t aws_iot_shadow_connect(AWS_IoT_Client *pClient, ShadowConnectParameters_t *pParams);
/**
* @brief Yield function to let the background tasks of MQTT and Shadow
*
@@ -116,6 +127,7 @@ IoT_Error_t aws_iot_shadow_connect(AWS_IoT_Client *pClient, ShadowConnectParamet
* @return An IoT Error Type defining successful/failed Yield
*/
IoT_Error_t aws_iot_shadow_yield(AWS_IoT_Client *pClient, uint32_t timeout);
/**
* @brief Disconnect from the AWS IoT Thing Shadow service over MQTT
*
@@ -160,7 +172,7 @@ typedef enum {
*
*/
typedef void (*fpActionCallback_t)(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status,
const char *pReceivedJsonDocument, void *pContextData);
const char *pReceivedJsonDocument, void *pContextData);
/**
* @brief This function is the one used to perform an Update action to a Thing Name's Shadow.
@@ -186,7 +198,8 @@ typedef void (*fpActionCallback_t)(const char *pThingName, ShadowActions_t actio
* @return An IoT Error Type defining successful/failed update action
*/
IoT_Error_t aws_iot_shadow_update(AWS_IoT_Client *pClient, const char *pThingName, char *pJsonString,
fpActionCallback_t callback, void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe);
fpActionCallback_t callback, void *pContextData, uint8_t timeout_seconds,
bool isPersistentSubscribe);
/**
* @brief This function is the one used to perform an Get action to a Thing Name's Shadow.
@@ -203,7 +216,8 @@ IoT_Error_t aws_iot_shadow_update(AWS_IoT_Client *pClient, const char *pThingNam
* @return An IoT Error Type defining successful/failed get action
*/
IoT_Error_t aws_iot_shadow_get(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback,
void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe);
void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe);
/**
* @brief This function is the one used to perform an Delete action to a Thing Name's Shadow.
*
@@ -219,7 +233,7 @@ IoT_Error_t aws_iot_shadow_get(AWS_IoT_Client *pClient, const char *pThingName,
* @return An IoT Error Type defining successful/failed delete action
*/
IoT_Error_t aws_iot_shadow_delete(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback,
void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscriptions);
void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscriptions);
/**
* @brief This function is used to listen on the delta topic of #AWS_IOT_MY_THING_NAME mentioned in the aws_iot_config.h file.
@@ -275,4 +289,8 @@ void aws_iot_shadow_disable_discard_old_delta_msgs(void);
*/
IoT_Error_t aws_iot_shadow_set_autoreconnect_status(AWS_IoT_Client *pClient, bool newStatus);
#ifdef __cplusplus
}
#endif
#endif //AWS_IOT_SDK_SRC_IOT_SHADOW_H_

View File

@@ -15,6 +15,10 @@
#ifndef AWS_IOT_SDK_SRC_IOT_SHADOW_JSON_H_
#define AWS_IOT_SDK_SRC_IOT_SHADOW_JSON_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
@@ -23,16 +27,27 @@
#include "aws_iot_shadow_json_data.h"
bool isJsonValidAndParse(const char *pJsonDocument, void *pJsonHandler, int32_t *pTokenCount);
bool isJsonKeyMatchingAndUpdateValue(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount,
jsonStruct_t *pDataStruct, uint32_t *pDataLength, int32_t *pDataPosition);
void iot_shadow_get_request_json(char *pJsonDocument);
void iot_shadow_delete_request_json(char *pJsonDocument);
bool isJsonKeyMatchingAndUpdateValue(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount,
jsonStruct_t *pDataStruct, uint32_t *pDataLength, int32_t *pDataPosition);
void aws_iot_shadow_internal_get_request_json(char *pJsonDocument);
void aws_iot_shadow_internal_delete_request_json(char *pJsonDocument);
void resetClientTokenSequenceNum(void);
bool isReceivedJsonValid(const char *pJsonDocument);
void FillWithClientToken(char *pStringToUpdateClientToken);
bool extractClientToken(const char *pJsonDocumentToBeSent, char *pExtractedClientToken);
bool extractVersionNumber(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, uint32_t *pVersionNumber);
#ifdef __cplusplus
}
#endif
#endif // AWS_IOT_SDK_SRC_IOT_SHADOW_JSON_H_

View File

@@ -16,6 +16,10 @@
#ifndef SRC_SHADOW_AWS_IOT_SHADOW_JSON_DATA_H_
#define SRC_SHADOW_AWS_IOT_SHADOW_JSON_DATA_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file aws_iot_shadow_json_data.h
* @brief This file is the interface for all the Shadow related JSON functions.
@@ -28,6 +32,7 @@
*
*/
typedef struct jsonStruct jsonStruct_t;
/**
* @brief Every JSON name value can have a callback. The callback should follow this signature
*/
@@ -137,4 +142,8 @@ IoT_Error_t aws_iot_finalize_json_document(char *pJsonDocument, size_t maxSizeOf
IoT_Error_t aws_iot_fill_with_client_token(char *pBufferToBeUpdatedWithClientToken, size_t maxSizeOfJsonDocument);
#ifdef __cplusplus
}
#endif
#endif /* SRC_SHADOW_AWS_IOT_SHADOW_JSON_DATA_H_ */

View File

@@ -16,6 +16,10 @@
#ifndef SRC_SHADOW_AWS_IOT_SHADOW_RECORDS_H_
#define SRC_SHADOW_AWS_IOT_SHADOW_RECORDS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include "aws_iot_shadow_interface.h"
@@ -26,20 +30,26 @@ extern uint32_t shadowJsonVersionNum;
extern bool shadowDiscardOldDeltaFlag;
extern char myThingName[MAX_SIZE_OF_THING_NAME];
extern uint16_t myThingNameLen;
extern char mqttClientID[MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES];
extern uint16_t mqttClientIDLen;
void initializeRecords(AWS_IoT_Client *pClient);
bool isSubscriptionPresent(const char *pThingName, ShadowActions_t action);
IoT_Error_t subscribeToShadowActionAcks(const char *pThingName, ShadowActions_t action, bool isSticky);
void incrementSubscriptionCnt(const char *pThingName, ShadowActions_t action, bool isSticky);
IoT_Error_t publishToShadowAction(const char * pThingName, ShadowActions_t action, const char *pJsonDocumentToBeSent);
IoT_Error_t publishToShadowAction(const char *pThingName, ShadowActions_t action, const char *pJsonDocumentToBeSent);
void addToAckWaitList(uint8_t indexAckWaitList, const char *pThingName, ShadowActions_t action,
const char *pExtractedClientToken, fpActionCallback_t callback, void *pCallbackContext,
uint32_t timeout_seconds);
const char *pExtractedClientToken, fpActionCallback_t callback, void *pCallbackContext,
uint32_t timeout_seconds);
bool getNextFreeIndexOfAckWaitList(uint8_t *pIndex);
void HandleExpiredResponseCallbacks(void);
void initDeltaTokens(void);
IoT_Error_t registerJsonTokenOnDelta(jsonStruct_t *pStruct);
#ifdef __cplusplus
}
#endif
#endif /* SRC_SHADOW_AWS_IOT_SHADOW_RECORDS_H_ */

View File

@@ -35,7 +35,7 @@
/**
* @brief MINOR version when functionality is added in a backwards-compatible manner.
*/
#define VERSION_MINOR 0
#define VERSION_MINOR 1
/**
* @brief PATCH version when backwards-compatible bug fixes are made.
*/

View File

@@ -24,6 +24,10 @@
#ifndef __NETWORK_INTERFACE_H_
#define __NETWORK_INTERFACE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include <aws_iot_error.h>
@@ -44,30 +48,31 @@ typedef struct Network Network;
* TLS networking layer to create a TLS secured socket.
*/
typedef struct {
char *pRootCALocation; ///< Pointer to string containing the filename (including path) of the root CA file.
char *pDeviceCertLocation; ///< Pointer to string containing the filename (including path) of the device certificate.
char *pDevicePrivateKeyLocation; ///< Pointer to string containing the filename (including path) of the device private key file.
char *pDestinationURL; ///< Pointer to string containing the endpoint of the MQTT service.
uint16_t DestinationPort; ///< Integer defining the connection port of the MQTT service.
uint32_t timeout_ms; ///< Unsigned integer defining the TLS handshake timeout value in milliseconds.
bool ServerVerificationFlag; ///< Boolean. True = perform server certificate hostname validation. False = skip validation \b NOT recommended.
}TLSConnectParams;
char *pRootCALocation; ///< Pointer to string containing the filename (including path) of the root CA file.
char *pDeviceCertLocation; ///< Pointer to string containing the filename (including path) of the device certificate.
char *pDevicePrivateKeyLocation; ///< Pointer to string containing the filename (including path) of the device private key file.
char *pDestinationURL; ///< Pointer to string containing the endpoint of the MQTT service.
uint16_t DestinationPort; ///< Integer defining the connection port of the MQTT service.
uint32_t timeout_ms; ///< Unsigned integer defining the TLS handshake timeout value in milliseconds.
bool ServerVerificationFlag; ///< Boolean. True = perform server certificate hostname validation. False = skip validation \b NOT recommended.
} TLSConnectParams;
/**
* @brief Network Structure
*
* Structure for defining a network connection.
*/
struct Network{
IoT_Error_t (*connect) (Network *, TLSConnectParams *);
IoT_Error_t (*read) (Network *, unsigned char *, size_t, Timer *, size_t *); ///< Function pointer pointing to the network function to read from the network
IoT_Error_t (*write) (Network *, unsigned char *, size_t, Timer *, size_t *); ///< Function pointer pointing to the network function to write to the network
IoT_Error_t (*disconnect) (Network *); ///< Function pointer pointing to the network function to disconnect from the network
IoT_Error_t (*isConnected) (Network *); ///< Function pointer pointing to the network function to check if physical layer is connected
IoT_Error_t (*destroy) (Network *); ///< Function pointer pointing to the network function to destroy the network object
struct Network {
IoT_Error_t (*connect)(Network *, TLSConnectParams *);
TLSConnectParams tlsConnectParams; ///< TLSConnect params structure containing the common connection parameters
TLSDataParams tlsDataParams; ///< TLSData params structure containing the connection data parameters that are specific to the library being used
IoT_Error_t (*read)(Network *, unsigned char *, size_t, Timer *, size_t *); ///< Function pointer pointing to the network function to read from the network
IoT_Error_t (*write)(Network *, unsigned char *, size_t, Timer *, size_t *); ///< Function pointer pointing to the network function to write to the network
IoT_Error_t (*disconnect)(Network *); ///< Function pointer pointing to the network function to disconnect from the network
IoT_Error_t (*isConnected)(Network *); ///< Function pointer pointing to the network function to check if physical layer is connected
IoT_Error_t (*destroy)(Network *); ///< Function pointer pointing to the network function to destroy the network object
TLSConnectParams tlsConnectParams; ///< TLSConnect params structure containing the common connection parameters
TLSDataParams tlsDataParams; ///< TLSData params structure containing the connection data parameters that are specific to the library being used
};
/**
@@ -113,7 +118,7 @@ IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *TLSParams);
* @return integer - number of bytes written or TLS error
* @return IoT_Error_t - successful write or TLS error code
*/
IoT_Error_t iot_tls_write(Network*, unsigned char*, size_t, Timer *, size_t *);
IoT_Error_t iot_tls_write(Network *, unsigned char *, size_t, Timer *, size_t *);
/**
* @brief Read bytes from the network socket
@@ -125,7 +130,7 @@ IoT_Error_t iot_tls_write(Network*, unsigned char*, size_t, Timer *, size_t *);
* @param size_t - pointer to store number of bytes read
* @return IoT_Error_t - successful read or TLS error code
*/
IoT_Error_t iot_tls_read(Network*, unsigned char*, size_t, Timer *, size_t *);
IoT_Error_t iot_tls_read(Network *, unsigned char *, size_t, Timer *, size_t *);
/**
* @brief Disconnect from network socket
@@ -155,4 +160,8 @@ IoT_Error_t iot_tls_destroy(Network *pNetwork);
*/
IoT_Error_t iot_tls_is_connected(Network *pNetwork);
#ifdef __cplusplus
}
#endif
#endif //__NETWORK_INTERFACE_H_

View File

@@ -22,10 +22,15 @@
*/
#include "aws_iot_config.h"
#ifdef _ENABLE_THREAD_SUPPORT_
#ifndef __THREADS_INTERFACE_H_
#define __THREADS_INTERFACE_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* The platform specific timer header that defines the Timer struct
*/
@@ -95,5 +100,9 @@ IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *);
*/
IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *);
#ifdef __cplusplus
}
#endif
#endif /*__THREADS_INTERFACE_H_*/
#endif /*_ENABLE_THREAD_SUPPORT_*/

View File

@@ -27,6 +27,10 @@
#ifndef __TIMER_INTERFACE_H_
#define __TIMER_INTERFACE_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* The platform specific timer header that defines the Timer struct
*/
@@ -94,4 +98,8 @@ uint32_t left_ms(Timer *);
*/
void init_timer(Timer *);
#ifdef __cplusplus
}
#endif
#endif //__TIMER_INTERFACE_H_

View File

@@ -18,6 +18,10 @@
* @brief Linux implementation of the timer interface.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <sys/types.h>
#include <stdint.h>
@@ -32,20 +36,24 @@ bool has_timer_expired(Timer *timer) {
return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0);
}
void countdown_ms(Timer* timer, uint32_t timeout) {
void countdown_ms(Timer *timer, uint32_t timeout) {
struct timeval now;
gettimeofday(&now, NULL);
struct timeval interval = { timeout / 1000, (timeout % 1000) * 1000 };
#ifdef __cplusplus
struct timeval interval = {timeout / 1000, static_cast<int>((timeout % 1000) * 1000)};
#else
struct timeval interval = {timeout / 1000, (int)((timeout % 1000) * 1000)};
#endif
timeradd(&now, &interval, &timer->end_time);
}
uint32_t left_ms(Timer* timer) {
uint32_t left_ms(Timer *timer) {
struct timeval now, res;
gettimeofday(&now, NULL);
timersub(&timer->end_time, &now, &res);
uint32_t result_ms = 0;
if(res.tv_sec >= 0) {
result_ms = (uint32_t)(res.tv_sec * 1000 + res.tv_usec / 1000);
result_ms = (uint32_t) (res.tv_sec * 1000 + res.tv_usec / 1000);
}
return result_ms;
}
@@ -53,10 +61,14 @@ uint32_t left_ms(Timer* timer) {
void countdown_sec(Timer *timer, uint32_t timeout) {
struct timeval now;
gettimeofday(&now, NULL);
struct timeval interval = { timeout, 0 };
struct timeval interval = {timeout, 0};
timeradd(&now, &interval, &timer->end_time);
}
void init_timer(Timer *timer) {
timer->end_time = (struct timeval) { 0, 0 };
timer->end_time = (struct timeval) {0, 0};
}
#ifdef __cplusplus
}
#endif

View File

@@ -16,6 +16,10 @@
#ifndef SRC_PROTOCOL_MQTT_AWS_IOT_EMBEDDED_CLIENT_WRAPPER_PLATFORM_LINUX_COMMON_TIMER_PLATFORM_H_
#define SRC_PROTOCOL_MQTT_AWS_IOT_EMBEDDED_CLIENT_WRAPPER_PLATFORM_LINUX_COMMON_TIMER_PLATFORM_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file timer_platform.h
*/
@@ -30,5 +34,8 @@ struct Timer {
struct timeval end_time;
};
#ifdef __cplusplus
}
#endif
#endif /* SRC_PROTOCOL_MQTT_AWS_IOT_EMBEDDED_CLIENT_WRAPPER_PLATFORM_LINUX_COMMON_TIMER_PLATFORM_H_ */

View File

@@ -13,6 +13,10 @@
* permissions and limitations under the License.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <string.h>
#include <timer_platform.h>
@@ -30,21 +34,22 @@
* This is a function to do further verification if needed on the cert received
*/
static IoT_Error_t _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) {
static int _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) {
char buf[1024];
((void) data);
DEBUG("\nVerify requested for (Depth %d):\n", depth);
IOT_DEBUG("\nVerify requested for (Depth %d):\n", depth);
mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
DEBUG("%s", buf);
IOT_DEBUG("%s", buf);
if ((*flags) == 0) {
DEBUG(" This certificate has no flags\n");
if((*flags) == 0) {
IOT_DEBUG(" This certificate has no flags\n");
} else {
DEBUG(buf, sizeof(buf), " ! ", *flags); DEBUG("%s\n", buf);
IOT_DEBUG(buf, sizeof(buf), " ! ", *flags);
IOT_DEBUG("%s\n", buf);
}
return SUCCESS;
return 0;
}
void _iot_tls_set_connect_params(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation,
@@ -72,6 +77,8 @@ IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDevice
pNetwork->isConnected = iot_tls_is_connected;
pNetwork->destroy = iot_tls_destroy;
pNetwork->tlsDataParams.flags = 0;
return SUCCESS;
}
@@ -106,40 +113,42 @@ IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) {
mbedtls_x509_crt_init(&(tlsDataParams->clicert));
mbedtls_pk_init(&(tlsDataParams->pkey));
DEBUG("\n . Seeding the random number generator...");
IOT_DEBUG("\n . Seeding the random number generator...");
mbedtls_entropy_init(&(tlsDataParams->entropy));
if ((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy),
(const unsigned char *) pers, strlen(pers))) != 0) {
ERROR(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret);
if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy),
(const unsigned char *) pers, strlen(pers))) != 0) {
IOT_ERROR(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret);
return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
}
DEBUG(" . Loading the CA root certificate ...");
IOT_DEBUG(" . Loading the CA root certificate ...");
ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation);
if (ret < 0) {
ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing root cert\n\n", -ret);
if(ret < 0) {
IOT_ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing root cert\n\n", -ret);
return NETWORK_X509_ROOT_CRT_PARSE_ERROR;
} DEBUG(" ok (%d skipped)\n", ret);
}
IOT_DEBUG(" ok (%d skipped)\n", ret);
DEBUG(" . Loading the client cert. and key...");
IOT_DEBUG(" . Loading the client cert. and key...");
ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), pNetwork->tlsConnectParams.pDeviceCertLocation);
if (ret != 0) {
ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing device cert\n\n", -ret);
if(ret != 0) {
IOT_ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing device cert\n\n", -ret);
return NETWORK_X509_DEVICE_CRT_PARSE_ERROR;
}
ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, "");
if (ret != 0) {
ERROR(" failed\n ! mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n", -ret);
DEBUG(" path : %s ", pNetwork->tlsConnectParams.pDevicePrivateKeyLocation);
if(ret != 0) {
IOT_ERROR(" failed\n ! mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n", -ret);
IOT_DEBUG(" path : %s ", pNetwork->tlsConnectParams.pDevicePrivateKeyLocation);
return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR;
} DEBUG(" ok\n");
}
IOT_DEBUG(" ok\n");
char portBuffer[6];
snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort);
DEBUG(" . Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer);
if ((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL,
portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) {
ERROR(" failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret);
IOT_DEBUG(" . Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer);
if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL,
portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) {
IOT_ERROR(" failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret);
switch(ret) {
case MBEDTLS_ERR_NET_SOCKET_FAILED:
return NETWORK_ERR_NET_SOCKET_FAILED;
@@ -152,20 +161,20 @@ IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) {
}
ret = mbedtls_net_set_block(&(tlsDataParams->server_fd));
if (ret != 0) {
ERROR(" failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret);
if(ret != 0) {
IOT_ERROR(" failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret);
return SSL_CONNECTION_ERROR;
} DEBUG(" ok\n");
} IOT_DEBUG(" ok\n");
DEBUG(" . Setting up the SSL/TLS structure...");
if ((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
ERROR(" failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret);
IOT_DEBUG(" . Setting up the SSL/TLS structure...");
if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
IOT_ERROR(" failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret);
return SSL_CONNECTION_ERROR;
}
mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL);
if (pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED);
} else {
mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL);
@@ -173,78 +182,81 @@ IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) {
mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg));
mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL);
if ((ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey))) != 0) {
ERROR(" failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret);
if((ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey))) !=
0) {
IOT_ERROR(" failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret);
return SSL_CONNECTION_ERROR;
}
mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms);
if ((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) {
ERROR(" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret);
if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) {
IOT_ERROR(" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret);
return SSL_CONNECTION_ERROR;
}
if ((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) {
ERROR(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) {
IOT_ERROR(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
return SSL_CONNECTION_ERROR;
}
DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state);
mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, mbedtls_net_recv_timeout);
DEBUG(" ok\n");
IOT_DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state);
mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL,
mbedtls_net_recv_timeout);
IOT_DEBUG(" ok\n");
DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state);
DEBUG(" . Performing the SSL/TLS handshake...");
while ((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
ERROR(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret);
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
ERROR(" Unable to verify the server's certificate. "
"Either it is invalid,\n"
" or you didn't set ca_file or ca_path "
"to an appropriate value.\n"
" Alternatively, you may want to use "
"auth_mode=optional for testing purposes.\n");
IOT_DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state);
IOT_DEBUG(" . Performing the SSL/TLS handshake...");
while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) {
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
IOT_ERROR(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret);
if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
IOT_ERROR(" Unable to verify the server's certificate. "
"Either it is invalid,\n"
" or you didn't set ca_file or ca_path "
"to an appropriate value.\n"
" Alternatively, you may want to use "
"auth_mode=optional for testing purposes.\n");
}
return SSL_CONNECTION_ERROR;
}
}
DEBUG(" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl)));
if ((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) {
DEBUG(" [ Record expansion is %d ]\n", ret);
IOT_DEBUG(" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&(tlsDataParams->ssl)),
mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl)));
if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) {
IOT_DEBUG(" [ Record expansion is %d ]\n", ret);
} else {
DEBUG(" [ Record expansion is unknown (compression) ]\n");
IOT_DEBUG(" [ Record expansion is unknown (compression) ]\n");
}
DEBUG(" . Verifying peer X.509 certificate...");
IOT_DEBUG(" . Verifying peer X.509 certificate...");
if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) {
char vrfy_buf[512];
ERROR(" failed\n");
IOT_ERROR(" failed\n");
mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", tlsDataParams->flags);
ERROR("%s\n", vrfy_buf);
IOT_ERROR("%s\n", vrfy_buf);
ret = SSL_CONNECTION_ERROR;
} else {
DEBUG(" ok\n");
IOT_DEBUG(" ok\n");
ret = SUCCESS;
}
} else {
DEBUG(" Server Verification skipped\n");
IOT_DEBUG(" Server Verification skipped\n");
ret = SUCCESS;
}
#ifdef IOT_DEBUG
if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) {
DEBUG(" . Peer certificate information ...\n");
IOT_DEBUG(" . Peer certificate information ...\n");
mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)));
DEBUG("%s\n", buf);
IOT_DEBUG("%s\n", buf);
}
#endif
mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), IOT_SSL_READ_TIMEOUT);
return ret;
return (IoT_Error_t) ret;
}
IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *written_len) {
@@ -253,10 +265,12 @@ IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Ti
int frags, ret;
TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams);
for(written_so_far = 0, frags = 0; written_so_far < len && !has_timer_expired(timer); written_so_far += ret, frags++) {
while(!has_timer_expired(timer) && (ret = mbedtls_ssl_write(&(tlsDataParams->ssl), pMsg + written_so_far, len - written_so_far)) <= 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
ERROR(" failed\n ! mbedtls_ssl_write returned -0x%x\n\n", -ret);
for(written_so_far = 0, frags = 0;
written_so_far < len && !has_timer_expired(timer); written_so_far += ret, frags++) {
while(!has_timer_expired(timer) &&
(ret = mbedtls_ssl_write(&(tlsDataParams->ssl), pMsg + written_so_far, len - written_so_far)) <= 0) {
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
IOT_ERROR(" failed\n ! mbedtls_ssl_write returned -0x%x\n\n", -ret);
/* All other negative return values indicate connection needs to be reset.
* Will be caught in ping request so ignored here */
isErrorFlag = true;
@@ -290,16 +304,16 @@ IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Tim
do {
//mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), timerLeftVal);
ret = mbedtls_ssl_read(&(tlsDataParams->ssl), pMsg, len);
if (ret >= 0) { /* 0 is for EOF */
if(ret >= 0) { /* 0 is for EOF */
rxLen += ret;
} else if (ret != MBEDTLS_ERR_SSL_WANT_READ) {
} else if(ret != MBEDTLS_ERR_SSL_WANT_READ) {
isErrorFlag = true;
}
/* All other negative return values indicate connection needs to be reset.
* Will be caught in ping request so ignored here */
if (rxLen >= len) {
if(rxLen >= len) {
isCompleteFlag = true;
}
timerLeftVal = left_ms(timer);
@@ -321,7 +335,7 @@ IoT_Error_t iot_tls_disconnect(Network *pNetwork) {
int ret = 0;
do {
ret = mbedtls_ssl_close_notify(ssl);
} while (ret == MBEDTLS_ERR_SSL_WANT_WRITE);
} while(ret == MBEDTLS_ERR_SSL_WANT_WRITE);
/* All other negative return values indicate connection needs to be reset.
* No further action required since this is disconnect call */
@@ -344,3 +358,7 @@ IoT_Error_t iot_tls_destroy(Network *pNetwork) {
return SUCCESS;
}
#ifdef __cplusplus
}
#endif

View File

@@ -17,6 +17,7 @@
#include "mbedtls/config.h"
#include "mbedtls/platform.h"
#include "mbedtls/net.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
@@ -27,6 +28,10 @@
#include "mbedtls/debug.h"
#include "mbedtls/timing.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief TLS Connection Parameters
*
@@ -47,4 +52,8 @@ typedef struct _TLSDataParams {
#define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H
#ifdef __cplusplus
}
#endif
#endif //IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H

View File

@@ -18,6 +18,10 @@
#ifndef IOTSDKC_THREADS_PLATFORM_H_H
#define IOTSDKC_THREADS_PLATFORM_H_H
#ifdef __cplusplus
extern "C" {
#endif
#include <pthread.h>
/**
@@ -30,6 +34,10 @@ struct _IoT_Mutex_t {
pthread_mutex_t lock;
};
#ifdef __cplusplus
}
#endif
#endif /* IOTSDKC_THREADS_PLATFORM_H_H */
#endif /* _ENABLE_THREAD_SUPPORT_ */

View File

@@ -16,6 +16,10 @@
#include "threads_platform.h"
#ifdef _ENABLE_THREAD_SUPPORT_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize the provided mutex
*
@@ -99,5 +103,10 @@ IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *pMutex) {
return SUCCESS;
}
#ifdef __cplusplus
}
#endif
#endif /* _ENABLE_THREAD_SUPPORT_ */

View File

@@ -4,15 +4,18 @@ This folder contains several samples that demonstrate various SDK functions. The
* Explore the makefile. The makefile for each sample provides a reference on how to set up makefiles for client applications
* Explore the example. It connects to AWS IoT platform using MQTT and demonstrates few actions that can be performed by the SDK
* Download certificate authority CA file from [Symantec](https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem) and place in location referenced in the example (certs/)
* Ensure you have [created a thing](https://docs.aws.amazon.com/iot/latest/developerguide/create-thing.html) through your AWS IoT Console with name matching the definition AWS_IOT_MY_THING_NAME in the `aws_iot_config.h` file
* Place device identity cert and private key in locations referenced in the example (certs/)
* Ensure the names of the cert files are the same as in the `aws_iot_config.h` file
* Ensure the certificate has an attached policy which allows the proper permissions for AWS IoT
* Build the example using make (`make`)
* Run sample application (./subscribe_publish_sample or ./shadow_sample). The sample will print status messages to stdout
* The following sample applications are included:
* `subscribe_publish_sample` - a simple pub/sub MQTT example
* `shadow_sample` - a simple device shadow example using a connected window example
* `shadow_sample_console_echo` - a sample to work with the AWS IoT Console interactive guide
* All samples are written in C unless otherwise mentioned. The following sample applications are included:
* `subscribe_publish_sample` - a simple pub/sub MQTT example
* `subscribe_publish_cpp_sample` - a simple pub/sub MQTT example written in C++
* `subscribe_publish_library_sample` - a simple pub/sub MQTT example which builds the SDK as a separate library
* `shadow_sample` - a simple device shadow example using a connected window example
* `shadow_sample_console_echo` - a sample to work with the AWS IoT Console interactive guide
## Subscribe Publish Sample
This is a simple pub/sub MQTT example. It connects a single MQTT client to the server and subscribes to a test topic. Then it proceeds to publish messages on this topic and yields after each publish to ensure that the message was received.
@@ -30,4 +33,10 @@ This is a simple pub/sub MQTT example. It connects a single MQTT client to the s
* The yield API should be called periodically to process the PING request as well as read any messages in the receive buffer. It should be called once at least every TTL/2 time periods to ensure disconnect does not happen. There can only be one yield in progress at a time. Therefore, in multi-threaded scenarios one thread can be a dedicated yield thread while other threads handle other operations.
* The sample sends out messages equal to the value set in publish count unless infinite publishing flag is set
For further information on each API please read the API documentation.
For further information on each API please read the API documentation.
## Subscribe Publish Cpp Sample
This is the same sample as above but it is built using a C++ compiler. It demonstrates how the SDK can be used in a C++ program.
## Subscribe Publish Library Sample
This is also the same code as the Subscribe Publish sample. In this case, the SDK is built as a separate library and then used in the sample program.

View File

@@ -1,71 +0,0 @@
#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully.
.prevent_execution:
exit 0
CC = gcc
#remove @ for no make command prints
DEBUG = @
APP_DIR = .
APP_INCLUDE_DIRS += -I $(APP_DIR)
APP_NAME = shadow_sample
APP_SRC_FILES = $(APP_NAME).c
#IoT client directory
IOT_CLIENT_DIR = ../../..
PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls
PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common
IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include
IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn
IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR)
IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR)
IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c')
IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c')
IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c')
IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c')
#TLS - mbedtls
MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS
TLS_LIB_DIR = $(MBEDTLS_DIR)/library
TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include
EXTERNAL_LIBS += -L$(TLS_LIB_DIR)
LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR)
LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(TLS_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a
#Aggregate all include and src directories
INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS)
INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR)
INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS)
SRC_FILES += $(APP_SRC_FILES)
SRC_FILES += $(IOT_SRC_FILES)
# Logging level control
LOG_FLAGS += -DIOT_DEBUG
LOG_FLAGS += -DIOT_INFO
LOG_FLAGS += -DIOT_WARN
LOG_FLAGS += -DIOT_ERROR
COMPILER_FLAGS += -g
COMPILER_FLAGS += $(LOG_FLAGS)
#If the processor is big endian uncomment the compiler flag
#COMPILER_FLAGS += -DREVERSED
MBED_TLS_MAKE_CMD = cd $(MBEDTLS_DIR) && make
PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD)
MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS)
all:
$(PRE_MAKE_CMD)
$(DEBUG)$(MAKE_CMD)
$(POST_MAKE_CMD)
clean:
rm -f $(APP_DIR)/$(APP_NAME)
$(MBED_TLS_MAKE_CMD) clean

View File

@@ -51,6 +51,6 @@
// Auto Reconnect specific config
#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm
#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 8000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect.
#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect.
#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */

View File

@@ -22,19 +22,14 @@
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <memory.h>
#include <sys/time.h>
#include <string.h>
#include <limits.h>
#include <aws_iot_shadow_interface.h>
#include "aws_iot_config.h"
#include "aws_iot_log.h"
#include "aws_iot_version.h"
#include "aws_iot_shadow_interface.h"
#include "aws_iot_shadow_json_data.h"
#include "aws_iot_config.h"
#include "aws_iot_mqtt_client_interface.h"
#include "aws_iot_shadow_interface.h"
/*!
* The goal of this sample application is to demonstrate the capabilities of shadow.
@@ -62,12 +57,19 @@
#define ROOMTEMPERATURE_LOWERLIMIT 25.0f
#define STARTING_ROOMTEMPERATURE ROOMTEMPERATURE_LOWERLIMIT
#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200
static char certDirectory[PATH_MAX + 1] = "../../../certs";
static char HostAddress[255] = AWS_IOT_MQTT_HOST;
static uint32_t port = AWS_IOT_MQTT_PORT;
static uint8_t numPubs = 5;
static void simulateRoomTemperature(float *pRoomTemperature) {
static float deltaChange;
if (*pRoomTemperature >= ROOMTEMPERATURE_UPPERLIMIT) {
if(*pRoomTemperature >= ROOMTEMPERATURE_UPPERLIMIT) {
deltaChange = -0.5f;
} else if (*pRoomTemperature <= ROOMTEMPERATURE_LOWERLIMIT) {
} else if(*pRoomTemperature <= ROOMTEMPERATURE_LOWERLIMIT) {
deltaChange = 0.5f;
}
@@ -75,69 +77,69 @@ static void simulateRoomTemperature(float *pRoomTemperature) {
}
void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status,
const char *pReceivedJsonDocument, void *pContextData) {
const char *pReceivedJsonDocument, void *pContextData) {
IOT_UNUSED(pThingName);
IOT_UNUSED(action);
IOT_UNUSED(pReceivedJsonDocument);
IOT_UNUSED(pContextData);
if (status == SHADOW_ACK_TIMEOUT) {
INFO("Update Timeout--");
} else if (status == SHADOW_ACK_REJECTED) {
INFO("Update RejectedXX");
} else if (status == SHADOW_ACK_ACCEPTED) {
INFO("Update Accepted !!");
if(SHADOW_ACK_TIMEOUT == status) {
IOT_INFO("Update Timeout--");
} else if(SHADOW_ACK_REJECTED == status) {
IOT_INFO("Update RejectedXX");
} else if(SHADOW_ACK_ACCEPTED == status) {
IOT_INFO("Update Accepted !!");
}
}
void windowActuate_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext) {
if (pContext != NULL) {
INFO("Delta - Window state changed to %d", *(bool *)(pContext->pData));
IOT_UNUSED(pJsonString);
IOT_UNUSED(JsonStringDataLen);
if(pContext != NULL) {
IOT_INFO("Delta - Window state changed to %d", *(bool *) (pContext->pData));
}
}
char certDirectory[PATH_MAX + 1] = "../../../certs";
char HostAddress[255] = AWS_IOT_MQTT_HOST;
uint32_t port = AWS_IOT_MQTT_PORT;
uint8_t numPubs = 5;
void parseInputArgsForConnectParams(int argc, char** argv) {
void parseInputArgsForConnectParams(int argc, char **argv) {
int opt;
while (-1 != (opt = getopt(argc, argv, "h:p:c:n:"))) {
switch (opt) {
case 'h':
strcpy(HostAddress, optarg);
DEBUG("Host %s", optarg);
break;
case 'p':
port = atoi(optarg);
DEBUG("arg %s", optarg);
break;
case 'c':
strcpy(certDirectory, optarg);
DEBUG("cert root directory %s", optarg);
break;
case 'n':
numPubs = atoi(optarg);
DEBUG("num pubs %s", optarg);
break;
case '?':
if (optopt == 'c') {
ERROR("Option -%c requires an argument.", optopt);
} else if (isprint(optopt)) {
WARN("Unknown option `-%c'.", optopt);
} else {
WARN("Unknown option character `\\x%x'.", optopt);
}
break;
default:
ERROR("ERROR in command line argument parsing");
break;
while(-1 != (opt = getopt(argc, argv, "h:p:c:n:"))) {
switch(opt) {
case 'h':
strcpy(HostAddress, optarg);
IOT_DEBUG("Host %s", optarg);
break;
case 'p':
port = atoi(optarg);
IOT_DEBUG("arg %s", optarg);
break;
case 'c':
strcpy(certDirectory, optarg);
IOT_DEBUG("cert root directory %s", optarg);
break;
case 'n':
numPubs = atoi(optarg);
IOT_DEBUG("num pubs %s", optarg);
break;
case '?':
if(optopt == 'c') {
IOT_ERROR("Option -%c requires an argument.", optopt);
} else if(isprint(optopt)) {
IOT_WARN("Unknown option `-%c'.", optopt);
} else {
IOT_WARN("Unknown option character `\\x%x'.", optopt);
}
break;
default:
IOT_ERROR("ERROR in command line argument parsing");
break;
}
}
}
#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200
int main(int argc, char** argv) {
int main(int argc, char **argv) {
IoT_Error_t rc = FAILURE;
int32_t i = 0;
@@ -164,16 +166,16 @@ int main(int argc, char** argv) {
char clientKey[PATH_MAX + 1];
char CurrentWD[PATH_MAX + 1];
INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
getcwd(CurrentWD, sizeof(CurrentWD));
snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME);
snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME);
snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME);
DEBUG("rootCA %s", rootCA);
DEBUG("clientCRT %s", clientCRT);
DEBUG("clientKey %s", clientKey);
IOT_DEBUG("rootCA %s", rootCA);
IOT_DEBUG("clientCRT %s", clientCRT);
IOT_DEBUG("clientKey %s", clientKey);
parseInputArgsForConnectParams(argc, argv);
@@ -189,21 +191,22 @@ int main(int argc, char** argv) {
sp.enableAutoReconnect = false;
sp.disconnectHandler = NULL;
INFO("Shadow Init");
IOT_INFO("Shadow Init");
rc = aws_iot_shadow_init(&mqttClient, &sp);
if (SUCCESS != rc) {
ERROR("Shadow Connection Error");
if(SUCCESS != rc) {
IOT_ERROR("Shadow Connection Error");
return rc;
}
ShadowConnectParameters_t scp = ShadowConnectParametersDefault;
scp.pMyThingName = AWS_IOT_MY_THING_NAME;
scp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID;
scp.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID);
INFO("Shadow Connect");
IOT_INFO("Shadow Connect");
rc = aws_iot_shadow_connect(&mqttClient, &scp);
if (SUCCESS != rc) {
ERROR("Shadow Connection Error");
if(SUCCESS != rc) {
IOT_ERROR("Shadow Connection Error");
return rc;
}
@@ -213,56 +216,56 @@ int main(int argc, char** argv) {
* #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL
*/
rc = aws_iot_shadow_set_autoreconnect_status(&mqttClient, true);
if (SUCCESS != rc) {
ERROR("Unable to set Auto Reconnect to true - %d", rc);
if(SUCCESS != rc) {
IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc);
return rc;
}
rc = aws_iot_shadow_register_delta(&mqttClient, &windowActuator);
if (SUCCESS != rc) {
ERROR("Shadow Register Delta Error");
if(SUCCESS != rc) {
IOT_ERROR("Shadow Register Delta Error");
}
temperature = STARTING_ROOMTEMPERATURE;
// loop and publish a change in temperature
while (NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) {
while(NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) {
rc = aws_iot_shadow_yield(&mqttClient, 200);
if (NETWORK_ATTEMPTING_RECONNECT == rc) {
if(NETWORK_ATTEMPTING_RECONNECT == rc) {
sleep(1);
// If the client is attempting to reconnect we will skip the rest of the loop.
continue;
}
INFO("\n=======================================================================================\n");
INFO("On Device: window state %s", windowOpen?"true":"false");
IOT_INFO("\n=======================================================================================\n");
IOT_INFO("On Device: window state %s", windowOpen ? "true" : "false");
simulateRoomTemperature(&temperature);
rc = aws_iot_shadow_init_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);
if (rc == SUCCESS) {
if(SUCCESS == rc) {
rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 2, &temperatureHandler,
&windowActuator);
if (rc == SUCCESS) {
&windowActuator);
if(SUCCESS == rc) {
rc = aws_iot_finalize_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);
if (rc == SUCCESS) {
INFO("Update Shadow: %s", JsonDocumentBuffer);
if(SUCCESS == rc) {
IOT_INFO("Update Shadow: %s", JsonDocumentBuffer);
rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, JsonDocumentBuffer,
ShadowUpdateStatusCallback, NULL, 4, true);
ShadowUpdateStatusCallback, NULL, 4, true);
}
}
}
INFO("*****************************************************************************************\n");
IOT_INFO("*****************************************************************************************\n");
sleep(1);
}
if (SUCCESS != rc) {
ERROR("An error occurred in the loop %d", rc);
if(SUCCESS != rc) {
IOT_ERROR("An error occurred in the loop %d", rc);
}
INFO("Disconnecting");
IOT_INFO("Disconnecting");
rc = aws_iot_shadow_disconnect(&mqttClient);
if (SUCCESS != rc) {
ERROR("Disconnect error %d", rc);
if(SUCCESS != rc) {
IOT_ERROR("Disconnect error %d", rc);
}
return rc;

View File

@@ -1,74 +0,0 @@
#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully.
.prevent_execution:
exit 0
CC = gcc
#remove @ for no make command prints
DEBUG = @
APP_DIR = .
APP_INCLUDE_DIRS += -I $(APP_DIR)
APP_NAME = shadow_console_echo
APP_SRC_FILES = $(APP_NAME).c
#IoT client directory
IOT_CLIENT_DIR = ../../..
PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls
PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common
IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include
IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn
IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR)
IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR)
IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c')
IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c')
IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c')
IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c')
#TLS - mbedtls
MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS
TLS_LIB_DIR = $(MBEDTLS_DIR)/library
TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include
EXTERNAL_LIBS += -L$(TLS_LIB_DIR)
LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR)
LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(TLS_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a
#Aggregate all include and src directories
INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS)
INCLUDE_ALL_DIRS += $(MQTT_INCLUDE_DIR)
INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR)
INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS)
SRC_FILES += $(MQTT_SRC_FILES)
SRC_FILES += $(APP_SRC_FILES)
SRC_FILES += $(IOT_SRC_FILES)
# Logging level control
LOG_FLAGS += -DIOT_DEBUG
LOG_FLAGS += -DIOT_INFO
LOG_FLAGS += -DIOT_WARN
LOG_FLAGS += -DIOT_ERROR
COMPILER_FLAGS += -g
COMPILER_FLAGS += $(LOG_FLAGS)
#If the processor is big endian uncomment the compiler flag
#COMPILER_FLAGS += -DREVERSED
MBED_TLS_MAKE_CMD = cd $(MBEDTLS_DIR) && make
PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD)
MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS)
all:
$(PRE_MAKE_CMD)
$(DEBUG)$(MAKE_CMD)
$(POST_MAKE_CMD)
clean:
rm -f $(APP_DIR)/$(APP_NAME)
$(MBED_TLS_MAKE_CMD) clean

View File

@@ -51,6 +51,6 @@
// Auto Reconnect specific config
#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm
#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 8000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect.
#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect.
#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */

View File

@@ -19,11 +19,11 @@
#include <unistd.h>
#include <limits.h>
#include "aws_iot_config.h"
#include "aws_iot_log.h"
#include "aws_iot_version.h"
#include "aws_iot_mqtt_client_interface.h"
#include "aws_iot_shadow_interface.h"
#include "aws_iot_config.h"
/**
* @file shadow_console_echo.c
@@ -82,16 +82,16 @@ int main(int argc, char** argv) {
char clientKey[PATH_MAX + 1];
char CurrentWD[PATH_MAX + 1];
INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
getcwd(CurrentWD, sizeof(CurrentWD));
snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME);
snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME);
snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME);
DEBUG("rootCA %s", rootCA);
DEBUG("clientCRT %s", clientCRT);
DEBUG("clientKey %s", clientKey);
IOT_DEBUG("rootCA %s", rootCA);
IOT_DEBUG("clientCRT %s", clientCRT);
IOT_DEBUG("clientKey %s", clientKey);
parseInputArgsForConnectParams(argc, argv);
@@ -107,21 +107,22 @@ int main(int argc, char** argv) {
sp.enableAutoReconnect = false;
sp.disconnectHandler = NULL;
INFO("Shadow Init");
IOT_INFO("Shadow Init");
rc = aws_iot_shadow_init(&mqttClient, &sp);
if (SUCCESS != rc) {
ERROR("Shadow Connection Error");
IOT_ERROR("Shadow Connection Error");
return rc;
}
ShadowConnectParameters_t scp = ShadowConnectParametersDefault;
scp.pMyThingName = AWS_IOT_MY_THING_NAME;
scp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID;
scp.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID);
INFO("Shadow Connect");
IOT_INFO("Shadow Connect");
rc = aws_iot_shadow_connect(&mqttClient, &scp);
if (SUCCESS != rc) {
ERROR("Shadow Connection Error");
IOT_ERROR("Shadow Connection Error");
return rc;
}
@@ -132,7 +133,7 @@ int main(int argc, char** argv) {
*/
rc = aws_iot_shadow_set_autoreconnect_status(&mqttClient, true);
if(SUCCESS != rc){
ERROR("Unable to set Auto Reconnect to true - %d", rc);
IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc);
return rc;
}
@@ -161,7 +162,7 @@ int main(int argc, char** argv) {
}
if (messageArrivedOnDelta) {
INFO("\nSending delta message back %s\n", stringToEchoDelta);
IOT_INFO("\nSending delta message back %s\n", stringToEchoDelta);
rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, stringToEchoDelta, UpdateStatusCallback, NULL, 2, true);
messageArrivedOnDelta = false;
}
@@ -171,14 +172,14 @@ int main(int argc, char** argv) {
}
if (SUCCESS != rc) {
ERROR("An error occurred in the loop %d", rc);
IOT_ERROR("An error occurred in the loop %d", rc);
}
INFO("Disconnecting");
IOT_INFO("Disconnecting");
rc = aws_iot_shadow_disconnect(&mqttClient);
if (SUCCESS != rc) {
ERROR("Disconnect error %d", rc);
IOT_ERROR("Disconnect error %d", rc);
}
return rc;
@@ -194,7 +195,7 @@ int main(int argc, char** argv) {
bool buildJSONForReported(char *pJsonDocument, size_t maxSizeOfJsonDocument, const char *pReceivedDeltaData, uint32_t lengthDelta) {
int32_t ret;
if (pJsonDocument == NULL) {
if (NULL == pJsonDocument) {
return false;
}
@@ -220,27 +221,27 @@ void parseInputArgsForConnectParams(int argc, char** argv) {
switch (opt) {
case 'h':
strcpy(HostAddress, optarg);
DEBUG("Host %s", optarg);
IOT_DEBUG("Host %s", optarg);
break;
case 'p':
port = atoi(optarg);
DEBUG("arg %s", optarg);
IOT_DEBUG("arg %s", optarg);
break;
case 'c':
strcpy(certDirectory, optarg);
DEBUG("cert root directory %s", optarg);
IOT_DEBUG("cert root directory %s", optarg);
break;
case '?':
if (optopt == 'c') {
ERROR("Option -%c requires an argument.", optopt);
IOT_ERROR("Option -%c requires an argument.", optopt);
} else if (isprint(optopt)) {
WARN("Unknown option `-%c'.", optopt);
IOT_WARN("Unknown option `-%c'.", optopt);
} else {
WARN("Unknown option character `\\x%x'.", optopt);
IOT_WARN("Unknown option character `\\x%x'.", optopt);
}
break;
default:
ERROR("ERROR in command line argument parsing");
IOT_ERROR("ERROR in command line argument parsing");
break;
}
}
@@ -249,8 +250,9 @@ void parseInputArgsForConnectParams(int argc, char** argv) {
void DeltaCallback(const char *pJsonValueBuffer, uint32_t valueLength, jsonStruct_t *pJsonStruct_t) {
IOT_UNUSED(pJsonStruct_t);
DEBUG("Received Delta message %.*s", valueLength, pJsonValueBuffer);
IOT_DEBUG("Received Delta message %.*s", valueLength, pJsonValueBuffer);
if (buildJSONForReported(stringToEchoDelta, SHADOW_MAX_SIZE_OF_RX_BUFFER, pJsonValueBuffer, valueLength)) {
messageArrivedOnDelta = true;
@@ -259,12 +261,16 @@ void DeltaCallback(const char *pJsonValueBuffer, uint32_t valueLength, jsonStruc
void UpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status,
const char *pReceivedJsonDocument, void *pContextData) {
IOT_UNUSED(pThingName);
IOT_UNUSED(action);
IOT_UNUSED(pReceivedJsonDocument);
IOT_UNUSED(pContextData);
if (status == SHADOW_ACK_TIMEOUT) {
INFO("Update Timeout--");
} else if (status == SHADOW_ACK_REJECTED) {
INFO("Update RejectedXX");
} else if (status == SHADOW_ACK_ACCEPTED) {
INFO("Update Accepted !!");
if(SHADOW_ACK_TIMEOUT == status) {
IOT_INFO("Update Timeout--");
} else if(SHADOW_ACK_REJECTED == status) {
IOT_INFO("Update RejectedXX");
} else if(SHADOW_ACK_ACCEPTED == status) {
IOT_INFO("Update Accepted !!");
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_config.h
* @brief AWS IoT specific configuration file
*/
#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_
#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_
// Get from console
// =================================================
#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow
#define AWS_IOT_MQTT_PORT 8883 ///< default port for MQTT/S
#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device
#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with
#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name
#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name
#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename
// =================================================
// MQTT PubSub
#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow
#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped.
#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow
// Thing Shadow specific configs
#define SHADOW_MAX_SIZE_OF_RX_BUFFER AWS_IOT_MQTT_RX_BUF_LEN+1 ///< Maximum size of the SHADOW buffer to store the received Shadow message
#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments"
#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id
#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON
#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested
#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time
#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published
#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name
#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger
#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name
// Auto Reconnect specific config
#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm
#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect.
#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */

View File

@@ -0,0 +1,260 @@
/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file subscribe_publish_cpp_sample.cpp
* @brief simple MQTT publish and subscribe on the same topic in C++
*
* This example takes the parameters from the aws_iot_config.h file and establishes a connection to the AWS IoT MQTT Platform.
* It subscribes and publishes to the same topic - "sdkTest/sub"
*
* If all the certs are correct, you should see the messages received by the application in a loop.
*
* The application takes in the certificate path, host name , port and the number of times the publish should happen.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include "aws_iot_config.h"
#include "aws_iot_log.h"
#include "aws_iot_version.h"
#include "aws_iot_mqtt_client_interface.h"
/**
* @brief Default cert location
*/
char certDirectory[PATH_MAX + 1] = "../../../certs";
/**
* @brief Default MQTT HOST URL is pulled from the aws_iot_config.h
*/
char HostAddress[255] = AWS_IOT_MQTT_HOST;
/**
* @brief Default MQTT port is pulled from the aws_iot_config.h
*/
uint32_t port = AWS_IOT_MQTT_PORT;
/**
* @brief This parameter will avoid infinite loop of publish and exit the program after certain number of publishes
*/
uint32_t publishCount = 0;
void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
IOT_UNUSED(pData);
IOT_UNUSED(pClient);
IOT_INFO("Subscribe callback");
IOT_INFO("%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, params->payload);
}
void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) {
IOT_WARN("MQTT Disconnect");
IoT_Error_t rc = FAILURE;
if(NULL == pClient) {
return;
}
IOT_UNUSED(data);
if(aws_iot_is_autoreconnect_enabled(pClient)) {
IOT_INFO("Auto Reconnect is enabled, Reconnecting attempt will start now");
} else {
IOT_WARN("Auto Reconnect not enabled. Starting manual reconnect...");
rc = aws_iot_mqtt_attempt_reconnect(pClient);
if(NETWORK_RECONNECTED == rc) {
IOT_WARN("Manual Reconnect Successful");
} else {
IOT_WARN("Manual Reconnect Failed - %d", rc);
}
}
}
void parseInputArgsForConnectParams(int argc, char **argv) {
int opt;
while(-1 != (opt = getopt(argc, argv, "h:p:c:x:"))) {
switch(opt) {
case 'h':
strcpy(HostAddress, optarg);
IOT_DEBUG("Host %s", optarg);
break;
case 'p':
port = atoi(optarg);
IOT_DEBUG("arg %s", optarg);
break;
case 'c':
strcpy(certDirectory, optarg);
IOT_DEBUG("cert root directory %s", optarg);
break;
case 'x':
publishCount = atoi(optarg);
IOT_DEBUG("publish %s times\n", optarg);
break;
case '?':
if(optopt == 'c') {
IOT_ERROR("Option -%c requires an argument.", optopt);
} else if(isprint(optopt)) {
IOT_WARN("Unknown option `-%c'.", optopt);
} else {
IOT_WARN("Unknown option character `\\x%x'.", optopt);
}
break;
default:
IOT_ERROR("Error in command line argument parsing");
break;
}
}
}
int main(int argc, char **argv) {
bool infinitePublishFlag = true;
char rootCA[PATH_MAX + 1];
char clientCRT[PATH_MAX + 1];
char clientKey[PATH_MAX + 1];
char CurrentWD[PATH_MAX + 1];
char cPayload[100];
int32_t i = 0;
IoT_Error_t rc = FAILURE;
AWS_IoT_Client client;
IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault;
IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault;
IoT_Publish_Message_Params paramsQOS0;
IoT_Publish_Message_Params paramsQOS1;
parseInputArgsForConnectParams(argc, argv);
IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
getcwd(CurrentWD, sizeof(CurrentWD));
snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME);
snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME);
snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME);
IOT_DEBUG("rootCA %s", rootCA);
IOT_DEBUG("clientCRT %s", clientCRT);
IOT_DEBUG("clientKey %s", clientKey);
mqttInitParams.enableAutoReconnect = false; // We enable this later below
mqttInitParams.pHostURL = HostAddress;
mqttInitParams.port = port;
mqttInitParams.pRootCALocation = rootCA;
mqttInitParams.pDeviceCertLocation = clientCRT;
mqttInitParams.pDevicePrivateKeyLocation = clientKey;
mqttInitParams.mqttCommandTimeout_ms = 20000;
mqttInitParams.tlsHandshakeTimeout_ms = 5000;
mqttInitParams.isSSLHostnameVerify = true;
mqttInitParams.disconnectHandler = disconnectCallbackHandler;
mqttInitParams.disconnectHandlerData = NULL;
rc = aws_iot_mqtt_init(&client, &mqttInitParams);
if(SUCCESS != rc) {
IOT_ERROR("aws_iot_mqtt_init returned error : %d ", rc);
return rc;
}
connectParams.keepAliveIntervalInSec = 10;
connectParams.isCleanSession = true;
connectParams.MQTTVersion = MQTT_3_1_1;
connectParams.pClientID = (char *)AWS_IOT_MQTT_CLIENT_ID;
connectParams.clientIDLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID);
connectParams.isWillMsgPresent = false;
IOT_INFO("Connecting...");
rc = aws_iot_mqtt_connect(&client, &connectParams);
if(SUCCESS != rc) {
IOT_ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port);
return rc;
}
/*
* Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h
* #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL
* #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL
*/
rc = aws_iot_mqtt_autoreconnect_set_status(&client, true);
if(SUCCESS != rc) {
IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc);
return rc;
}
IOT_INFO("Subscribing...");
rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL);
if(SUCCESS != rc) {
IOT_ERROR("Error subscribing : %d ", rc);
return rc;
}
sprintf(cPayload, "%s : %d ", "hello from SDK", i);
paramsQOS0.qos = QOS0;
paramsQOS0.payload = (void *) cPayload;
paramsQOS0.isRetained = 0;
paramsQOS1.qos = QOS1;
paramsQOS1.payload = (void *) cPayload;
paramsQOS1.isRetained = 0;
if(publishCount != 0) {
infinitePublishFlag = false;
}
while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc)
&& (publishCount > 0 || infinitePublishFlag)) {
//Max time the yield function will wait for read messages
rc = aws_iot_mqtt_yield(&client, 100);
if(NETWORK_ATTEMPTING_RECONNECT == rc) {
// If the client is attempting to reconnect we will skip the rest of the loop.
continue;
}
IOT_INFO("-->sleep");
sleep(1);
sprintf(cPayload, "%s : %d ", "hello from SDK QOS0", i++);
paramsQOS0.payloadLen = strlen(cPayload);
rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, &paramsQOS0);
if(publishCount > 0) {
publishCount--;
}
sprintf(cPayload, "%s : %d ", "hello from SDK QOS1", i++);
paramsQOS1.payloadLen = strlen(cPayload);
do {
rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, &paramsQOS1);
if(publishCount > 0) {
publishCount--;
}
} while(MQTT_REQUEST_TIMEOUT_ERROR == rc && (publishCount > 0 || infinitePublishFlag));
}
if(SUCCESS != rc) {
IOT_ERROR("An error occurred in the loop.\n");
} else {
IOT_INFO("Publish done\n");
}
return rc;
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_config.h
* @brief AWS IoT specific configuration file
*/
#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_
#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_
// Get from console
// =================================================
#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow
#define AWS_IOT_MQTT_PORT 8883 ///< default port for MQTT/S
#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device
#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with
#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name
#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name
#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename
// =================================================
// MQTT PubSub
#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow
#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped.
#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow
// Thing Shadow specific configs
#define SHADOW_MAX_SIZE_OF_RX_BUFFER AWS_IOT_MQTT_RX_BUF_LEN+1 ///< Maximum size of the SHADOW buffer to store the received Shadow message
#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments"
#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id
#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON
#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested
#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time
#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published
#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name
#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger
#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name
// Auto Reconnect specific config
#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm
#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect.
#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */

View File

@@ -0,0 +1,260 @@
/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file subscribe_publish_library_sample.c
* @brief simple MQTT publish and subscribe on the same topic using the SDK as a library
*
* This example takes the parameters from the aws_iot_config.h file and establishes a connection to the AWS IoT MQTT Platform.
* It subscribes and publishes to the same topic - "sdkTest/sub"
*
* If all the certs are correct, you should see the messages received by the application in a loop.
*
* The application takes in the certificate path, host name , port and the number of times the publish should happen.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include "aws_iot_config.h"
#include "aws_iot_log.h"
#include "aws_iot_version.h"
#include "aws_iot_mqtt_client_interface.h"
/**
* @brief Default cert location
*/
char certDirectory[PATH_MAX + 1] = "../../../certs";
/**
* @brief Default MQTT HOST URL is pulled from the aws_iot_config.h
*/
char HostAddress[255] = AWS_IOT_MQTT_HOST;
/**
* @brief Default MQTT port is pulled from the aws_iot_config.h
*/
uint32_t port = AWS_IOT_MQTT_PORT;
/**
* @brief This parameter will avoid infinite loop of publish and exit the program after certain number of publishes
*/
uint32_t publishCount = 0;
void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
IOT_UNUSED(pData);
IOT_UNUSED(pClient);
IOT_INFO("Subscribe callback");
IOT_INFO("%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, params->payload);
}
void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) {
IOT_WARN("MQTT Disconnect");
IoT_Error_t rc = FAILURE;
if(NULL == pClient) {
return;
}
IOT_UNUSED(data);
if(aws_iot_is_autoreconnect_enabled(pClient)) {
IOT_INFO("Auto Reconnect is enabled, Reconnecting attempt will start now");
} else {
IOT_WARN("Auto Reconnect not enabled. Starting manual reconnect...");
rc = aws_iot_mqtt_attempt_reconnect(pClient);
if(NETWORK_RECONNECTED == rc) {
IOT_WARN("Manual Reconnect Successful");
} else {
IOT_WARN("Manual Reconnect Failed - %d", rc);
}
}
}
void parseInputArgsForConnectParams(int argc, char **argv) {
int opt;
while(-1 != (opt = getopt(argc, argv, "h:p:c:x:"))) {
switch(opt) {
case 'h':
strcpy(HostAddress, optarg);
IOT_DEBUG("Host %s", optarg);
break;
case 'p':
port = atoi(optarg);
IOT_DEBUG("arg %s", optarg);
break;
case 'c':
strcpy(certDirectory, optarg);
IOT_DEBUG("cert root directory %s", optarg);
break;
case 'x':
publishCount = atoi(optarg);
IOT_DEBUG("publish %s times\n", optarg);
break;
case '?':
if(optopt == 'c') {
IOT_ERROR("Option -%c requires an argument.", optopt);
} else if(isprint(optopt)) {
IOT_WARN("Unknown option `-%c'.", optopt);
} else {
IOT_WARN("Unknown option character `\\x%x'.", optopt);
}
break;
default:
IOT_ERROR("Error in command line argument parsing");
break;
}
}
}
int main(int argc, char **argv) {
bool infinitePublishFlag = true;
char rootCA[PATH_MAX + 1];
char clientCRT[PATH_MAX + 1];
char clientKey[PATH_MAX + 1];
char CurrentWD[PATH_MAX + 1];
char cPayload[100];
int32_t i = 0;
IoT_Error_t rc = FAILURE;
AWS_IoT_Client client;
IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault;
IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault;
IoT_Publish_Message_Params paramsQOS0;
IoT_Publish_Message_Params paramsQOS1;
parseInputArgsForConnectParams(argc, argv);
IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
getcwd(CurrentWD, sizeof(CurrentWD));
snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME);
snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME);
snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME);
IOT_DEBUG("rootCA %s", rootCA);
IOT_DEBUG("clientCRT %s", clientCRT);
IOT_DEBUG("clientKey %s", clientKey);
mqttInitParams.enableAutoReconnect = false; // We enable this later below
mqttInitParams.pHostURL = HostAddress;
mqttInitParams.port = port;
mqttInitParams.pRootCALocation = rootCA;
mqttInitParams.pDeviceCertLocation = clientCRT;
mqttInitParams.pDevicePrivateKeyLocation = clientKey;
mqttInitParams.mqttCommandTimeout_ms = 20000;
mqttInitParams.tlsHandshakeTimeout_ms = 5000;
mqttInitParams.isSSLHostnameVerify = true;
mqttInitParams.disconnectHandler = disconnectCallbackHandler;
mqttInitParams.disconnectHandlerData = NULL;
rc = aws_iot_mqtt_init(&client, &mqttInitParams);
if(SUCCESS != rc) {
IOT_ERROR("aws_iot_mqtt_init returned error : %d ", rc);
return rc;
}
connectParams.keepAliveIntervalInSec = 10;
connectParams.isCleanSession = true;
connectParams.MQTTVersion = MQTT_3_1_1;
connectParams.pClientID = AWS_IOT_MQTT_CLIENT_ID;
connectParams.clientIDLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID);
connectParams.isWillMsgPresent = false;
IOT_INFO("Connecting...");
rc = aws_iot_mqtt_connect(&client, &connectParams);
if(SUCCESS != rc) {
IOT_ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port);
return rc;
}
/*
* Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h
* #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL
* #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL
*/
rc = aws_iot_mqtt_autoreconnect_set_status(&client, true);
if(SUCCESS != rc) {
IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc);
return rc;
}
IOT_INFO("Subscribing...");
rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL);
if(SUCCESS != rc) {
IOT_ERROR("Error subscribing : %d ", rc);
return rc;
}
sprintf(cPayload, "%s : %d ", "hello from SDK", i);
paramsQOS0.qos = QOS0;
paramsQOS0.payload = (void *) cPayload;
paramsQOS0.isRetained = 0;
paramsQOS1.qos = QOS1;
paramsQOS1.payload = (void *) cPayload;
paramsQOS1.isRetained = 0;
if(publishCount != 0) {
infinitePublishFlag = false;
}
while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc)
&& (publishCount > 0 || infinitePublishFlag)) {
//Max time the yield function will wait for read messages
rc = aws_iot_mqtt_yield(&client, 100);
if(NETWORK_ATTEMPTING_RECONNECT == rc) {
// If the client is attempting to reconnect we will skip the rest of the loop.
continue;
}
IOT_INFO("-->sleep");
sleep(1);
sprintf(cPayload, "%s : %d ", "hello from SDK QOS0", i++);
paramsQOS0.payloadLen = strlen(cPayload);
rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, &paramsQOS0);
if(publishCount > 0) {
publishCount--;
}
sprintf(cPayload, "%s : %d ", "hello from SDK QOS1", i++);
paramsQOS1.payloadLen = strlen(cPayload);
do {
rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, &paramsQOS1);
if(publishCount > 0) {
publishCount--;
}
} while(MQTT_REQUEST_TIMEOUT_ERROR == rc && (publishCount > 0 || infinitePublishFlag));
}
if(SUCCESS != rc) {
IOT_ERROR("An error occurred in the loop.\n");
} else {
IOT_INFO("Publish done\n");
}
return rc;
}

View File

@@ -1,69 +0,0 @@
#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully.
.prevent_execution:
exit 0
CC = gcc
#remove @ for no make command prints
DEBUG = @
APP_DIR = .
APP_INCLUDE_DIRS += -I $(APP_DIR)
APP_NAME = subscribe_publish_sample
APP_SRC_FILES = $(APP_NAME).c
#IoT client directory
IOT_CLIENT_DIR = ../../..
PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls
PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common
IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include
IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn
IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR)
IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR)
IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c')
IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c')
IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c')
IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c')
#TLS - mbedtls
MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS
TLS_LIB_DIR = $(MBEDTLS_DIR)/library
TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include
EXTERNAL_LIBS += -L$(TLS_LIB_DIR)
LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR)
LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(TLS_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread
#Aggregate all include and src directories
INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS)
INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR)
INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS)
SRC_FILES += $(APP_SRC_FILES)
SRC_FILES += $(IOT_SRC_FILES)
# Logging level control
LOG_FLAGS += -DIOT_DEBUG
LOG_FLAGS += -DIOT_INFO
LOG_FLAGS += -DIOT_WARN
LOG_FLAGS += -DIOT_ERROR
COMPILER_FLAGS += $(LOG_FLAGS)
#If the processor is big endian uncomment the compiler flag
#COMPILER_FLAGS += -DREVERSED
MBED_TLS_MAKE_CMD = cd $(MBEDTLS_DIR) && make
PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD)
MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS)
all:
$(PRE_MAKE_CMD)
$(DEBUG)$(MAKE_CMD)
$(POST_MAKE_CMD)
clean:
rm -f $(APP_DIR)/$(APP_NAME)
$(MBED_TLS_MAKE_CMD) clean

View File

@@ -51,6 +51,6 @@
// Auto Reconnect specific config
#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm
#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 8000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect.
#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect.
#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */

View File

@@ -29,44 +29,13 @@
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <memory.h>
#include <sys/time.h>
#include <limits.h>
#include <aws_iot_mqtt_client.h>
#include <string.h>
#include "aws_iot_config.h"
#include "aws_iot_log.h"
#include "aws_iot_version.h"
#include "aws_iot_mqtt_client_interface.h"
#include "aws_iot_config.h"
void MQTTcallbackHandler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
INFO("Subscribe callback");
INFO("%.*s\t%.*s", topicNameLen, topicName, (int)params->payloadLen, params->payload);
}
void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) {
WARN("MQTT Disconnect");
IoT_Error_t rc = FAILURE;
if(NULL == data) {
return;
}
AWS_IoT_Client *client = (AWS_IoT_Client *)data;
if(aws_iot_is_autoreconnect_enabled(client)){
INFO("Auto Reconnect is enabled, Reconnecting attempt will start now");
}else{
WARN("Auto Reconnect not enabled. Starting manual reconnect...");
rc = aws_iot_mqtt_attempt_reconnect(client);
if(NETWORK_RECONNECTED == rc){
WARN("Manual Reconnect Successful");
}else{
WARN("Manual Reconnect Failed - %d", rc);
}
}
}
/**
* @brief Default cert location
@@ -88,99 +57,137 @@ uint32_t port = AWS_IOT_MQTT_PORT;
*/
uint32_t publishCount = 0;
void parseInputArgsForConnectParams(int argc, char** argv) {
void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
IOT_UNUSED(pData);
IOT_UNUSED(pClient);
IOT_INFO("Subscribe callback");
IOT_INFO("%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, params->payload);
}
void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) {
IOT_WARN("MQTT Disconnect");
IoT_Error_t rc = FAILURE;
if(NULL == pClient) {
return;
}
IOT_UNUSED(data);
if(aws_iot_is_autoreconnect_enabled(pClient)) {
IOT_INFO("Auto Reconnect is enabled, Reconnecting attempt will start now");
} else {
IOT_WARN("Auto Reconnect not enabled. Starting manual reconnect...");
rc = aws_iot_mqtt_attempt_reconnect(pClient);
if(NETWORK_RECONNECTED == rc) {
IOT_WARN("Manual Reconnect Successful");
} else {
IOT_WARN("Manual Reconnect Failed - %d", rc);
}
}
}
void parseInputArgsForConnectParams(int argc, char **argv) {
int opt;
while (-1 != (opt = getopt(argc, argv, "h:p:c:x:"))) {
switch (opt) {
case 'h':
strcpy(HostAddress, optarg);
DEBUG("Host %s", optarg);
break;
case 'p':
port = atoi(optarg);
DEBUG("arg %s", optarg);
break;
case 'c':
strcpy(certDirectory, optarg);
DEBUG("cert root directory %s", optarg);
break;
case 'x':
publishCount = atoi(optarg);
DEBUG("publish %s times\n", optarg);
break;
case '?':
if (optopt == 'c') {
ERROR("Option -%c requires an argument.", optopt);
} else if (isprint(optopt)) {
WARN("Unknown option `-%c'.", optopt);
} else {
WARN("Unknown option character `\\x%x'.", optopt);
}
break;
default:
ERROR("Error in command line argument parsing");
break;
while(-1 != (opt = getopt(argc, argv, "h:p:c:x:"))) {
switch(opt) {
case 'h':
strcpy(HostAddress, optarg);
IOT_DEBUG("Host %s", optarg);
break;
case 'p':
port = atoi(optarg);
IOT_DEBUG("arg %s", optarg);
break;
case 'c':
strcpy(certDirectory, optarg);
IOT_DEBUG("cert root directory %s", optarg);
break;
case 'x':
publishCount = atoi(optarg);
IOT_DEBUG("publish %s times\n", optarg);
break;
case '?':
if(optopt == 'c') {
IOT_ERROR("Option -%c requires an argument.", optopt);
} else if(isprint(optopt)) {
IOT_WARN("Unknown option `-%c'.", optopt);
} else {
IOT_WARN("Unknown option character `\\x%x'.", optopt);
}
break;
default:
IOT_ERROR("Error in command line argument parsing");
break;
}
}
}
int main(int argc, char** argv) {
IoT_Error_t rc = FAILURE;
int32_t i = 0;
int main(int argc, char **argv) {
bool infinitePublishFlag = true;
char rootCA[PATH_MAX + 1];
char clientCRT[PATH_MAX + 1];
char clientKey[PATH_MAX + 1];
char CurrentWD[PATH_MAX + 1];
char cPayload[100];
int32_t i = 0;
IoT_Error_t rc = FAILURE;
AWS_IoT_Client client;
IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault;
IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault;
IoT_Publish_Message_Params paramsQOS0;
IoT_Publish_Message_Params paramsQOS1;
parseInputArgsForConnectParams(argc, argv);
INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
getcwd(CurrentWD, sizeof(CurrentWD));
snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME);
snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME);
snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME);
DEBUG("rootCA %s", rootCA);
DEBUG("clientCRT %s", clientCRT);
DEBUG("clientKey %s", clientKey);
IoT_Client_Init_Params mqttInitParams;
IOT_DEBUG("rootCA %s", rootCA);
IOT_DEBUG("clientCRT %s", clientCRT);
IOT_DEBUG("clientKey %s", clientKey);
mqttInitParams.enableAutoReconnect = false; // We enable this later below
mqttInitParams.pHostURL = HostAddress;
mqttInitParams.pHostURL = HostAddress;
mqttInitParams.port = port;
mqttInitParams.pRootCALocation = rootCA;
mqttInitParams.pDeviceCertLocation = clientCRT;
mqttInitParams.pDevicePrivateKeyLocation = clientKey;
mqttInitParams.mqttCommandTimeout_ms = 2000;
mqttInitParams.mqttCommandTimeout_ms = 20000;
mqttInitParams.tlsHandshakeTimeout_ms = 5000;
mqttInitParams.isSSLHostnameVerify = true;
mqttInitParams.disconnectHandler = disconnectCallbackHandler;
mqttInitParams.disconnectHandlerData = (void *)&client;
mqttInitParams.disconnectHandlerData = NULL;
rc = aws_iot_mqtt_init(&client, &mqttInitParams);
if(SUCCESS != rc) {
ERROR("aws_iot_mqtt_init returned error : %d ", rc);
IOT_ERROR("aws_iot_mqtt_init returned error : %d ", rc);
return rc;
}
IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault;
connectParams.keepAliveIntervalInSec = 10;
connectParams.isCleanSession = true;
connectParams.MQTTVersion = MQTT_3_1_1;
connectParams.pClientID = "CSDK-test-device";
connectParams.pClientID = AWS_IOT_MQTT_CLIENT_ID;
connectParams.clientIDLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID);
connectParams.isWillMsgPresent = false;
INFO("Connecting...");
IOT_INFO("Connecting...");
rc = aws_iot_mqtt_connect(&client, &connectParams);
if(SUCCESS != rc) {
ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port);
IOT_ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port);
return rc;
}
/*
* Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h
@@ -189,70 +196,65 @@ int main(int argc, char** argv) {
*/
rc = aws_iot_mqtt_autoreconnect_set_status(&client, true);
if(SUCCESS != rc) {
ERROR("Unable to set Auto Reconnect to true - %d", rc);
IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc);
return rc;
}
INFO("Subscribing...");
rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, MQTTcallbackHandler, NULL);
IOT_INFO("Subscribing...");
rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL);
if(SUCCESS != rc) {
ERROR("Error subscribing : %d ", rc);
IOT_ERROR("Error subscribing : %d ", rc);
return rc;
}
char cPayload[100];
sprintf(cPayload, "%s : %d ", "hello from SDK", i);
IoT_Publish_Message_Params paramsQOS0;
paramsQOS0.qos = QOS0;
paramsQOS0.payload = (void *) cPayload;
paramsQOS0.isRetained = 0;
IoT_Publish_Message_Params paramsQOS1;
paramsQOS1.qos = QOS1;
paramsQOS1.payload = (void *) cPayload;
paramsQOS1.isRetained = 0;
if (publishCount != 0) {
if(publishCount != 0) {
infinitePublishFlag = false;
}
while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc)
&& (publishCount > 0 || infinitePublishFlag)) {
&& (publishCount > 0 || infinitePublishFlag)) {
//Max time the yield function will wait for read messages
rc = aws_iot_mqtt_yield(&client, 100);
if(NETWORK_ATTEMPTING_RECONNECT == rc){
INFO("-->sleep");
sleep(1);
if(NETWORK_ATTEMPTING_RECONNECT == rc) {
// If the client is attempting to reconnect we will skip the rest of the loop.
continue;
}
INFO("-->sleep");
IOT_INFO("-->sleep");
sleep(1);
sprintf(cPayload, "%s : %d ", "hello from SDK QOS0", i++);
paramsQOS0.payloadLen = strlen(cPayload) + 1;
paramsQOS0.payloadLen = strlen(cPayload);
rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, &paramsQOS0);
if (publishCount > 0) {
if(publishCount > 0) {
publishCount--;
}
INFO("-->sleep");
sleep(1);
sprintf(cPayload, "%s : %d ", "hello from SDK QOS1", i++);
paramsQOS1.payloadLen = strlen(cPayload) + 1;
paramsQOS1.payloadLen = strlen(cPayload);
do {
rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, &paramsQOS1);
if (publishCount > 0) {
if(publishCount > 0) {
publishCount--;
}
} while(MQTT_REQUEST_TIMEOUT_ERROR == rc && (publishCount > 0 || infinitePublishFlag));
}
if(SUCCESS != rc) {
ERROR("An error occurred in the loop.\n");
IOT_ERROR("An error occurred in the loop.\n");
} else {
INFO("Publish done\n");
IOT_INFO("Publish done\n");
}
return rc;
}

View File

@@ -22,18 +22,30 @@
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "aws_iot_json_utils.h"
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#ifdef __cplusplus
#include <cinttypes>
#else
#include <inttypes.h>
#endif
#include "aws_iot_log.h"
int8_t jsoneq(const char *json, jsmntok_t *tok, const char *s) {
if (tok->type == JSMN_STRING) {
if ((int) strlen(s) == tok->end - tok->start) {
if (strncmp(json + tok->start, s, (size_t)(tok->end - tok->start)) == 0) {
if(tok->type == JSMN_STRING) {
if((int) strlen(s) == tok->end - tok->start) {
if(strncmp(json + tok->start, s, (size_t) (tok->end - tok->start)) == 0) {
return 0;
}
}
@@ -42,13 +54,13 @@ int8_t jsoneq(const char *json, jsmntok_t *tok, const char *s) {
}
IoT_Error_t parseUnsignedInteger32Value(uint32_t *i, const char *jsonString, jsmntok_t *token) {
if (token->type != JSMN_PRIMITIVE) {
WARN("Token was not an integer");
if(token->type != JSMN_PRIMITIVE) {
IOT_WARN("Token was not an integer");
return JSON_PARSE_ERROR;
}
if (1 != sscanf(jsonString + token->start, "%"SCNu32, i)) {
WARN("Token was not an integer.");
if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%" SCNu32, i))) {
IOT_WARN("Token was not an unsigned integer.");
return JSON_PARSE_ERROR;
}
@@ -56,13 +68,13 @@ IoT_Error_t parseUnsignedInteger32Value(uint32_t *i, const char *jsonString, jsm
}
IoT_Error_t parseUnsignedInteger16Value(uint16_t *i, const char *jsonString, jsmntok_t *token) {
if (token->type != JSMN_PRIMITIVE) {
WARN("Token was not an integer");
if(token->type != JSMN_PRIMITIVE) {
IOT_WARN("Token was not an integer");
return JSON_PARSE_ERROR;
}
if (1 != sscanf(jsonString + token->start, "%"SCNu16, i)) {
WARN("Token was not an integer.");
if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%" SCNu16, i))) {
IOT_WARN("Token was not an unsigned integer.");
return JSON_PARSE_ERROR;
}
@@ -70,13 +82,13 @@ IoT_Error_t parseUnsignedInteger16Value(uint16_t *i, const char *jsonString, jsm
}
IoT_Error_t parseUnsignedInteger8Value(uint8_t *i, const char *jsonString, jsmntok_t *token) {
if (token->type != JSMN_PRIMITIVE) {
WARN("Token was not an integer");
if(token->type != JSMN_PRIMITIVE) {
IOT_WARN("Token was not an integer");
return JSON_PARSE_ERROR;
}
if (1 != sscanf(jsonString + token->start, "%"SCNu8, i)) {
WARN("Token was not an integer.");
if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%" SCNu8, i))) {
IOT_WARN("Token was not an unsigned integer.");
return JSON_PARSE_ERROR;
}
@@ -84,13 +96,13 @@ IoT_Error_t parseUnsignedInteger8Value(uint8_t *i, const char *jsonString, jsmnt
}
IoT_Error_t parseInteger32Value(int32_t *i, const char *jsonString, jsmntok_t *token) {
if (token->type != JSMN_PRIMITIVE) {
WARN("Token was not an integer");
if(token->type != JSMN_PRIMITIVE) {
IOT_WARN("Token was not an integer");
return JSON_PARSE_ERROR;
}
if (1 != sscanf(jsonString + token->start, "%"SCNi32, i)) {
WARN("Token was not an integer.");
if(1 != sscanf(jsonString + token->start, "%" SCNi32, i)) {
IOT_WARN("Token was not an integer.");
return JSON_PARSE_ERROR;
}
@@ -98,13 +110,13 @@ IoT_Error_t parseInteger32Value(int32_t *i, const char *jsonString, jsmntok_t *t
}
IoT_Error_t parseInteger16Value(int16_t *i, const char *jsonString, jsmntok_t *token) {
if (token->type != JSMN_PRIMITIVE) {
WARN("Token was not an integer");
if(token->type != JSMN_PRIMITIVE) {
IOT_WARN("Token was not an integer");
return JSON_PARSE_ERROR;
}
if (1 != sscanf(jsonString + token->start, "%"SCNi16, i)) {
WARN("Token was not an integer.");
if(1 != sscanf(jsonString + token->start, "%" SCNi16, i)) {
IOT_WARN("Token was not an integer.");
return JSON_PARSE_ERROR;
}
@@ -112,13 +124,13 @@ IoT_Error_t parseInteger16Value(int16_t *i, const char *jsonString, jsmntok_t *t
}
IoT_Error_t parseInteger8Value(int8_t *i, const char *jsonString, jsmntok_t *token) {
if (token->type != JSMN_PRIMITIVE) {
WARN("Token was not an integer");
if(token->type != JSMN_PRIMITIVE) {
IOT_WARN("Token was not an integer");
return JSON_PARSE_ERROR;
}
if (1 != sscanf(jsonString + token->start, "%"SCNi8, i)) {
WARN("Token was not an integer.");
if(1 != sscanf(jsonString + token->start, "%" SCNi8, i)) {
IOT_WARN("Token was not an integer.");
return JSON_PARSE_ERROR;
}
@@ -126,13 +138,13 @@ IoT_Error_t parseInteger8Value(int8_t *i, const char *jsonString, jsmntok_t *tok
}
IoT_Error_t parseFloatValue(float *f, const char *jsonString, jsmntok_t *token) {
if (token->type != JSMN_PRIMITIVE) {
WARN("Token was not a float.");
if(token->type != JSMN_PRIMITIVE) {
IOT_WARN("Token was not a float.");
return JSON_PARSE_ERROR;
}
if (1 != sscanf(jsonString + token->start, "%f", f)) {
WARN("Token was not a float.");
if(1 != sscanf(jsonString + token->start, "%f", f)) {
IOT_WARN("Token was not a float.");
return JSON_PARSE_ERROR;
}
@@ -140,13 +152,13 @@ IoT_Error_t parseFloatValue(float *f, const char *jsonString, jsmntok_t *token)
}
IoT_Error_t parseDoubleValue(double *d, const char *jsonString, jsmntok_t *token) {
if (token->type != JSMN_PRIMITIVE) {
WARN("Token was not a double.");
if(token->type != JSMN_PRIMITIVE) {
IOT_WARN("Token was not a double.");
return JSON_PARSE_ERROR;
}
if (1 != sscanf(jsonString + token->start, "%lf", d)) {
WARN("Token was not a double.");
if(1 != sscanf(jsonString + token->start, "%lf", d)) {
IOT_WARN("Token was not a double.");
return JSON_PARSE_ERROR;
}
@@ -154,19 +166,19 @@ IoT_Error_t parseDoubleValue(double *d, const char *jsonString, jsmntok_t *token
}
IoT_Error_t parseBooleanValue(bool *b, const char *jsonString, jsmntok_t *token) {
if (token->type != JSMN_PRIMITIVE) {
WARN("Token was not a primitive.");
if(token->type != JSMN_PRIMITIVE) {
IOT_WARN("Token was not a primitive.");
return JSON_PARSE_ERROR;
}
if (jsonString[token->start] == 't' && jsonString[token->start + 1] == 'r' && jsonString[token->start + 2] == 'u'
&& jsonString[token->start + 3] == 'e') {
if(jsonString[token->start] == 't' && jsonString[token->start + 1] == 'r' && jsonString[token->start + 2] == 'u'
&& jsonString[token->start + 3] == 'e') {
*b = true;
} else if (jsonString[token->start] == 'f' && jsonString[token->start + 1] == 'a'
&& jsonString[token->start + 2] == 'l' && jsonString[token->start + 3] == 's'
&& jsonString[token->start + 4] == 'e') {
} else if(jsonString[token->start] == 'f' && jsonString[token->start + 1] == 'a'
&& jsonString[token->start + 2] == 'l' && jsonString[token->start + 3] == 's'
&& jsonString[token->start + 4] == 'e') {
*b = false;
} else {
WARN("Token was not a bool.");
IOT_WARN("Token was not a bool.");
return JSON_PARSE_ERROR;
}
return SUCCESS;
@@ -174,12 +186,16 @@ IoT_Error_t parseBooleanValue(bool *b, const char *jsonString, jsmntok_t *token)
IoT_Error_t parseStringValue(char *buf, const char *jsonString, jsmntok_t *token) {
uint16_t size = 0;
if (token->type != JSMN_STRING) {
WARN("Token was not a string.");
if(token->type != JSMN_STRING) {
IOT_WARN("Token was not a string.");
return JSON_PARSE_ERROR;
}
size = (uint16_t)(token->end - token->start);
size = (uint16_t) (token->end - token->start);
memcpy(buf, jsonString + token->start, size);
buf[size] = '\0';
return SUCCESS;
}
#ifdef __cplusplus
}
#endif

View File

@@ -35,6 +35,10 @@
* @brief MQTT client API definitions
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "aws_iot_log.h"
#include "aws_iot_mqtt_client_interface.h"
@@ -42,6 +46,7 @@
#include "threads_interface.h"
#endif
const IoT_Client_Init_Params iotClientInitParamsDefault = IoT_Client_Init_Params_initializer;
const IoT_MQTT_Will_Options iotMqttWillOptionsDefault = IoT_MQTT_Will_Options_Initializer;
const IoT_Client_Connect_Params iotClientConnectParamsDefault = IoT_Client_Connect_Params_initializer;
@@ -154,7 +159,9 @@ IoT_Error_t aws_iot_mqtt_init(AWS_IoT_Client *pClient, IoT_Client_Init_Params *p
FUNC_ENTRY;
if(NULL == pClient || NULL == pInitParams || NULL == pInitParams->pHostURL || pInitParams->port == 0) {
if(NULL == pClient || NULL == pInitParams || NULL == pInitParams->pHostURL || 0 == pInitParams->port ||
NULL == pInitParams->pRootCALocation || NULL == pInitParams->pDevicePrivateKeyLocation ||
NULL == pInitParams->pDeviceCertLocation) {
FUNC_EXIT_RC(NULL_VALUE_ERROR);
}
@@ -171,6 +178,7 @@ IoT_Error_t aws_iot_mqtt_init(AWS_IoT_Client *pClient, IoT_Client_Init_Params *p
pClient->clientData.counterNetworkDisconnected = 0;
pClient->clientData.disconnectHandler = pInitParams->disconnectHandler;
pClient->clientData.disconnectHandlerData = pInitParams->disconnectHandlerData;
pClient->clientData.nextPacketId = 1;
/* Initialize default connection options */
rc = aws_iot_mqtt_set_connect_params(pClient, &default_options);
@@ -215,7 +223,7 @@ IoT_Error_t aws_iot_mqtt_init(AWS_IoT_Client *pClient, IoT_Client_Init_Params *p
}
uint16_t aws_iot_mqtt_get_next_packet_id(AWS_IoT_Client *pClient) {
return pClient->clientData.nextPacketId = (uint16_t)((MAX_PACKET_ID == pClient->clientData.nextPacketId) ? 1 : (
return pClient->clientData.nextPacketId = (uint16_t) ((MAX_PACKET_ID == pClient->clientData.nextPacketId) ? 1 : (
pClient->clientData.nextPacketId + 1));
}
@@ -225,7 +233,7 @@ bool aws_iot_mqtt_is_client_connected(AWS_IoT_Client *pClient) {
FUNC_ENTRY;
if(NULL == pClient) {
WARN(" Client is null! ");
IOT_WARN(" Client is null! ");
FUNC_EXIT_RC(false);
}
@@ -259,7 +267,7 @@ bool aws_iot_mqtt_is_client_connected(AWS_IoT_Client *pClient) {
bool aws_iot_is_autoreconnect_enabled(AWS_IoT_Client *pClient) {
FUNC_ENTRY;
if(NULL == pClient) {
WARN(" Client is null! ");
IOT_WARN(" Client is null! ");
FUNC_EXIT_RC(false);
}
@@ -295,3 +303,7 @@ void aws_iot_mqtt_reset_network_disconnected_count(AWS_IoT_Client *pClient) {
pClient->clientData.counterNetworkDisconnected = 0;
}
#ifdef __cplusplus
}
#endif

View File

@@ -36,6 +36,10 @@
* @brief MQTT client internal API definitions
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <aws_iot_mqtt_client.h>
#include <unistd.h>
#include "aws_iot_mqtt_client_common_internal.h"
@@ -55,14 +59,14 @@ size_t aws_iot_mqtt_internal_write_len_to_buffer(unsigned char *buf, uint32_t le
FUNC_ENTRY;
do {
encodedByte = (unsigned char)(length % 128);
encodedByte = (unsigned char) (length % 128);
length /= 128;
/* if there are more digits to encode, set the top bit of this digit */
if(length > 0) {
encodedByte |= 0x80;
}
buf[outLen++] = encodedByte;
}while(length > 0);
} while(length > 0);
FUNC_EXIT_RC(outLen);
}
@@ -104,9 +108,9 @@ uint32_t aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(uin
/* now remaining_length field (MQTT 3.1.1 - 2.2.3)*/
if(rem_len < 128) {
rem_len += 1;
} else if (rem_len < 16384) {
} else if(rem_len < 16384) {
rem_len += 2;
} else if (rem_len < 2097152) {
} else if(rem_len < 2097152) {
rem_len += 3;
} else {
rem_len += 4;
@@ -124,8 +128,8 @@ uint32_t aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(uin
uint16_t aws_iot_mqtt_internal_read_uint16_t(unsigned char **pptr) {
unsigned char *ptr = *pptr;
uint16_t len = 0;
uint8_t firstByte = (uint8_t)(*ptr);
uint8_t secondByte = (uint8_t)(*(ptr + 1));
uint8_t firstByte = (uint8_t) (*ptr);
uint8_t secondByte = (uint8_t) (*(ptr + 1));
len = (uint16_t) (secondByte + (256 * firstByte));
*pptr += 2;
@@ -138,9 +142,9 @@ uint16_t aws_iot_mqtt_internal_read_uint16_t(unsigned char **pptr) {
* @param anInt the integer to write
*/
void aws_iot_mqtt_internal_write_uint_16(unsigned char **pptr, uint16_t anInt) {
**pptr = (unsigned char)(anInt / 256);
**pptr = (unsigned char) (anInt / 256);
(*pptr)++;
**pptr = (unsigned char)(anInt % 256);
**pptr = (unsigned char) (anInt % 256);
(*pptr)++;
}
@@ -166,10 +170,12 @@ void aws_iot_mqtt_internal_write_char(unsigned char **pptr, unsigned char c) {
}
void aws_iot_mqtt_internal_write_utf8_string(unsigned char **pptr, const char *string, uint16_t stringLen) {
/* Nothing that calls this function will have a size larger than 2 bytes (MQTT 3.1.1 - 1.5.3) */
/* Nothing that calls this function will have a stringLen with a size larger than 2 bytes (MQTT 3.1.1 - 1.5.3) */
aws_iot_mqtt_internal_write_uint_16(pptr, stringLen);
memcpy(*pptr, string, stringLen);
*pptr += stringLen;
if(stringLen > 0) {
memcpy(*pptr, string, stringLen);
*pptr += stringLen;
}
}
/**
@@ -236,7 +242,7 @@ IoT_Error_t aws_iot_mqtt_internal_init_header(MQTTHeader *pHeader, MessageTypes
break;
default:
/* Should never happen */
FUNC_EXIT_RC(FAILURE);
FUNC_EXIT_RC(FAILURE);
}
pHeader->bits.dup = (1 == dup) ? 0x01 : 0x00;
@@ -284,7 +290,8 @@ IoT_Error_t aws_iot_mqtt_internal_send_packet(AWS_IoT_Client *pClient, size_t le
sent = 0;
while(sent < length && !has_timer_expired(pTimer)) {
rc = pClient->networkStack.write(&(pClient->networkStack), &pClient->clientData.writeBuf[sent], length, pTimer, &sentLen);
rc = pClient->networkStack.write(&(pClient->networkStack), &pClient->clientData.writeBuf[sent], length, pTimer,
&sentLen);
if(SUCCESS != rc) {
/* there was an error writing the data */
break;
@@ -364,14 +371,14 @@ static IoT_Error_t _aws_iot_mqtt_internal_read_packet(AWS_IoT_Client *pClient, T
}
/* if the buffer is too short then the message will be dropped silently */
if (rem_len >= pClient->clientData.readBufSize) {
if(rem_len >= pClient->clientData.readBufSize) {
bytes_to_be_read = pClient->clientData.readBufSize;
do {
rc = pClient->networkStack.read(&(pClient->networkStack), pClient->clientData.readBuf, bytes_to_be_read,
pTimer, &read_len);
if(SUCCESS == rc) {
total_bytes_read += read_len;
if((rem_len - total_bytes_read) >= pClient->clientData.readBufSize){
if((rem_len - total_bytes_read) >= pClient->clientData.readBufSize) {
bytes_to_be_read = pClient->clientData.readBufSize;
} else {
bytes_to_be_read = rem_len - total_bytes_read;
@@ -382,11 +389,12 @@ static IoT_Error_t _aws_iot_mqtt_internal_read_packet(AWS_IoT_Client *pClient, T
}
/* put the original remaining length into the read buffer */
len += aws_iot_mqtt_internal_write_len_to_buffer(pClient->clientData.readBuf + 1, (uint32_t)rem_len);
len += aws_iot_mqtt_internal_write_len_to_buffer(pClient->clientData.readBuf + 1, (uint32_t) rem_len);
/* 3. read the rest of the buffer using a callback to supply the rest of the data */
if(rem_len > 0) {
rc = pClient->networkStack.read(&(pClient->networkStack), pClient->clientData.readBuf + len, rem_len, pTimer, &read_len);
rc = pClient->networkStack.read(&(pClient->networkStack), pClient->clientData.readBuf + len, rem_len, pTimer,
&read_len);
if(SUCCESS != rc || read_len != rem_len) {
return FAILURE;
}
@@ -459,14 +467,15 @@ static IoT_Error_t _aws_iot_mqtt_internal_deliver_message(AWS_IoT_Client *pClien
/* Find the right message handler - indexed by topic */
for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++itr) {
if(NULL != pClient->clientData.messageHandlers[itr].topicName) {
if (((topicNameLen == pClient->clientData.messageHandlers[itr].topicNameLen)
&& (strncmp(pTopicName, (char *) pClient->clientData.messageHandlers[itr].topicName, topicNameLen) == 0))
|| _aws_iot_mqtt_internal_is_topic_matched((char *) pClient->clientData.messageHandlers[itr].topicName,
pTopicName, topicNameLen)) {
if(((topicNameLen == pClient->clientData.messageHandlers[itr].topicNameLen)
&&
(strncmp(pTopicName, (char *) pClient->clientData.messageHandlers[itr].topicName, topicNameLen) == 0))
|| _aws_iot_mqtt_internal_is_topic_matched((char *) pClient->clientData.messageHandlers[itr].topicName,
pTopicName, topicNameLen)) {
if(NULL != pClient->clientData.messageHandlers[itr].pApplicationHandler) {
pClient->clientData.messageHandlers[itr].pApplicationHandler(pClient, pTopicName, topicNameLen,
pMessageParams,
pClient->clientData.messageHandlers[itr].pApplicationHandlerData);
pMessageParams,
pClient->clientData.messageHandlers[itr].pApplicationHandlerData);
}
}
}
@@ -491,7 +500,8 @@ static IoT_Error_t _aws_iot_mqtt_internal_handle_publish(AWS_IoT_Client *pClient
rc = aws_iot_mqtt_internal_deserialize_publish(&msg.isDup, &msg.qos, &msg.isRetained,
&msg.id, &topicName, &topicNameLen,
(unsigned char **) &msg.payload, &msg.payloadLen, pClient->clientData.readBuf,
(unsigned char **) &msg.payload, &msg.payloadLen,
pClient->clientData.readBuf,
pClient->clientData.readBufSize);
if(SUCCESS != rc) {
@@ -608,7 +618,7 @@ IoT_Error_t aws_iot_mqtt_internal_wait_for_read(AWS_IoT_Client *pClient, uint8_t
break;
}
rc = aws_iot_mqtt_internal_cycle_read(pClient, pTimer, &read_packet_type);
}while(NETWORK_DISCONNECTED_ERROR != rc && read_packet_type != packetType);
} while(NETWORK_DISCONNECTED_ERROR != rc && read_packet_type != packetType);
if(MQTT_REQUEST_TIMEOUT_ERROR != rc && NETWORK_DISCONNECTED_ERROR != rc && read_packet_type != packetType) {
FUNC_EXIT_RC(FAILURE);
@@ -654,7 +664,11 @@ IoT_Error_t aws_iot_mqtt_internal_serialize_zero(unsigned char *pTxBuf, size_t t
/* write remaining length */
ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, 0);
*pSerializedLength = (uint32_t)(ptr - pTxBuf);
*pSerializedLength = (uint32_t) (ptr - pTxBuf);
FUNC_EXIT_RC(SUCCESS);
}
#ifdef __cplusplus
}
#endif

View File

@@ -35,12 +35,16 @@
* @brief MQTT client connect API definition and related functions
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <aws_iot_mqtt_client.h>
#include "aws_iot_mqtt_client_interface.h"
#include "aws_iot_mqtt_client_common_internal.h"
typedef union {
uint8_t all; /**< all connect flags */
uint8_t all; /**< all connect flags */
#if defined(REVERSED)
struct
{
@@ -53,21 +57,27 @@ typedef union {
unsigned int : 1; /**< unused */
} bits;
#else
struct
{
unsigned int : 1; /**< unused */
unsigned int cleansession : 1; /**< cleansession flag */
unsigned int will : 1; /**< will flag */
unsigned int willQoS : 2; /**< will QoS value */
unsigned int willRetain : 1; /**< will retain setting */
unsigned int password : 1; /**< 3.1 password */
unsigned int username : 1; /**< 3.1 user name */
struct {
unsigned int : 1;
/**< unused */
unsigned int cleansession : 1;
/**< cleansession flag */
unsigned int will : 1;
/**< will flag */
unsigned int willQoS : 2;
/**< will QoS value */
unsigned int willRetain : 1;
/**< will retain setting */
unsigned int password : 1;
/**< 3.1 password */
unsigned int username : 1; /**< 3.1 user name */
} bits;
#endif
} MQTT_Connect_Header_Flags; /**< connect flags byte */
} MQTT_Connect_Header_Flags;
/**< connect flags byte */
typedef union {
uint8_t all; /**< all connack flags */
uint8_t all; /**< all connack flags */
#if defined(REVERSED)
struct
{
@@ -75,22 +85,23 @@ typedef union {
unsigned int : 7; /**< unused */
} bits;
#else
struct
{
unsigned int : 7; /**< unused */
struct {
unsigned int : 7;
/**< unused */
unsigned int sessionpresent : 1; /**< session present flag */
} bits;
#endif
} MQTT_Connack_Header_Flags; /**< connack flags byte */
} MQTT_Connack_Header_Flags;
/**< connack flags byte */
typedef enum {
CONNACK_CONNECTION_ACCEPTED = 0,
CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = 1,
CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = 1,
CONNACK_IDENTIFIER_REJECTED_ERROR = 2,
CONNACK_SERVER_UNAVAILABLE_ERROR = 3,
CONNACK_BAD_USERDATA_ERROR = 4,
CONNACK_NOT_AUTHORIZED_ERROR = 5
} MQTT_Connack_Return_Codes; /**< Connect request response codes from server */
} MQTT_Connack_Return_Codes; /**< Connect request response codes from server */
/**
@@ -147,10 +158,20 @@ static IoT_Error_t _aws_iot_mqtt_serialize_connect(unsigned char *pTxBuf, size_t
FUNC_ENTRY;
if(NULL == pTxBuf || NULL == pConnectParams || NULL == pSerializedLen) {
if(NULL == pTxBuf || NULL == pConnectParams || NULL == pSerializedLen ||
(NULL == pConnectParams->pClientID && 0 != pConnectParams->clientIDLen) ||
(NULL != pConnectParams->pClientID && 0 == pConnectParams->clientIDLen)) {
FUNC_EXIT_RC(NULL_VALUE_ERROR);
}
/* Check needed here before we start writing to the Tx buffer */
switch(pConnectParams->MQTTVersion) {
case MQTT_3_1_1:
break;
default:
return MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR;
}
ptr = pTxBuf;
len = _aws_iot_get_connect_packet_length(pConnectParams);
if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(len) > txBufLen) {
@@ -168,8 +189,8 @@ static IoT_Error_t _aws_iot_mqtt_serialize_connect(unsigned char *pTxBuf, size_t
// Enable if adding support for more versions
//if(MQTT_3_1_1 == pConnectParams->MQTTVersion) {
aws_iot_mqtt_internal_write_utf8_string(&ptr, "MQTT", 4);
aws_iot_mqtt_internal_write_char(&ptr, (char) 4);
aws_iot_mqtt_internal_write_utf8_string(&ptr, "MQTT", 4);
aws_iot_mqtt_internal_write_char(&ptr, (unsigned char) pConnectParams->MQTTVersion);
//}
flags.all = 0;
@@ -190,9 +211,17 @@ static IoT_Error_t _aws_iot_mqtt_serialize_connect(unsigned char *pTxBuf, size_t
aws_iot_mqtt_internal_write_char(&ptr, flags.all);
aws_iot_mqtt_internal_write_uint_16(&ptr, pConnectParams->keepAliveIntervalInSec);
aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pClientID, pConnectParams->clientIDLen);
/* If the code have passed the check for incorrect values above, no client id was passed as argument */
if(NULL == pConnectParams->pClientID) {
aws_iot_mqtt_internal_write_uint_16(&ptr, 0);
} else {
aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pClientID, pConnectParams->clientIDLen);
}
if(pConnectParams->isWillMsgPresent) {
aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pTopicName, pConnectParams->will.topicNameLen);
aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pTopicName,
pConnectParams->will.topicNameLen);
aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pMessage, pConnectParams->will.msgLen);
}
@@ -204,7 +233,7 @@ static IoT_Error_t _aws_iot_mqtt_serialize_connect(unsigned char *pTxBuf, size_t
aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pPassword, pConnectParams->passwordLen);
}
*pSerializedLen = (size_t)(ptr - pTxBuf);
*pSerializedLen = (size_t) (ptr - pTxBuf);
FUNC_EXIT_RC(SUCCESS);
}
@@ -255,10 +284,11 @@ static IoT_Error_t _aws_iot_mqtt_deserialize_connack(unsigned char *pSessionPres
FUNC_EXIT_RC(rc);
}
/* CONNACK remaining length should always be 2 as per MQTT 3.1.1 spec */
curdata += (readBytesLen);
enddata = curdata + decodedLen;
if(enddata - curdata < 2) {
FUNC_EXIT_RC(FAILURE);
if(2 != (enddata - curdata)) {
FUNC_EXIT_RC(MQTT_DECODE_REMAINING_LENGTH_ERROR);
}
flags.all = aws_iot_mqtt_internal_read_char(&curdata);
@@ -268,8 +298,8 @@ static IoT_Error_t _aws_iot_mqtt_deserialize_connack(unsigned char *pSessionPres
case CONNACK_CONNECTION_ACCEPTED:
*pConnackRc = MQTT_CONNACK_CONNECTION_ACCEPTED;
break;
case CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR:
*pConnackRc = MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR;
case CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR:
*pConnackRc = MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR;
break;
case CONNACK_IDENTIFIER_REJECTED_ERROR:
*pConnackRc = MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR;
@@ -353,9 +383,6 @@ static IoT_Error_t _aws_iot_mqtt_internal_connect(AWS_IoT_Client *pClient, IoT_C
FUNC_ENTRY;
init_timer(&connect_timer);
countdown_ms(&connect_timer, pClient->clientData.commandTimeoutMs);
if(NULL != pConnectParams) {
/* override default options if new options were supplied */
rc = aws_iot_mqtt_set_connect_params(pClient, pConnectParams);
@@ -370,10 +397,14 @@ static IoT_Error_t _aws_iot_mqtt_internal_connect(AWS_IoT_Client *pClient, IoT_C
FUNC_EXIT_RC(rc);
}
init_timer(&connect_timer);
countdown_ms(&connect_timer, pClient->clientData.commandTimeoutMs);
pClient->clientData.keepAliveInterval = pClient->clientData.options.keepAliveIntervalInSec;
rc = _aws_iot_mqtt_serialize_connect(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, &(pClient->clientData.options), &len);
rc = _aws_iot_mqtt_serialize_connect(pClient->clientData.writeBuf, pClient->clientData.writeBufSize,
&(pClient->clientData.options), &len);
if(SUCCESS != rc || 0 >= len) {
FUNC_EXIT_RC(MQTT_CONNECTION_ERROR);
FUNC_EXIT_RC(rc);
}
/* send the connect packet */
@@ -389,7 +420,8 @@ static IoT_Error_t _aws_iot_mqtt_internal_connect(AWS_IoT_Client *pClient, IoT_C
}
/* Received CONNACK, check the return code */
rc = _aws_iot_mqtt_deserialize_connack((unsigned char *)&sessionPresent, &connack_rc, pClient->clientData.readBuf, pClient->clientData.readBufSize);
rc = _aws_iot_mqtt_deserialize_connack((unsigned char *) &sessionPresent, &connack_rc, pClient->clientData.readBuf,
pClient->clientData.readBufSize);
if(SUCCESS != rc) {
FUNC_EXIT_RC(rc);
}
@@ -398,8 +430,8 @@ static IoT_Error_t _aws_iot_mqtt_internal_connect(AWS_IoT_Client *pClient, IoT_C
FUNC_EXIT_RC(connack_rc);
}
pClient->clientStatus.isPingOutstanding = 0;
countdown_sec(&pClient->pingTimer, pClient->clientData.keepAliveInterval);
pClient->clientStatus.isPingOutstanding = false;
countdown_sec(&pClient->pingTimer, pClient->clientData.keepAliveInterval / (uint32_t) 2);
FUNC_EXIT_RC(SUCCESS);
}
@@ -468,8 +500,9 @@ IoT_Error_t _aws_iot_mqtt_internal_disconnect(AWS_IoT_Client *pClient) {
FUNC_ENTRY;
rc = aws_iot_mqtt_internal_serialize_zero(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, DISCONNECT,
&serialized_len);
rc = aws_iot_mqtt_internal_serialize_zero(pClient->clientData.writeBuf, pClient->clientData.writeBufSize,
DISCONNECT,
&serialized_len);
if(SUCCESS != rc) {
FUNC_EXIT_RC(rc);
}
@@ -583,3 +616,6 @@ IoT_Error_t aws_iot_mqtt_attempt_reconnect(AWS_IoT_Client *pClient) {
FUNC_EXIT_RC(NETWORK_RECONNECTED);
}
#ifdef __cplusplus
}
#endif

View File

@@ -36,6 +36,10 @@
* @brief MQTT client publish API definitions
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "aws_iot_mqtt_client_common_internal.h"
/**
@@ -55,7 +59,7 @@ static IoT_Error_t _aws_iot_mqtt_read_string_with_len(char **stringVar, uint16_t
if(enddata - (*pptr) > 1) {
*stringLen = aws_iot_mqtt_internal_read_uint16_t(pptr); /* increments pptr to point past length */
if(&(*pptr)[*stringLen] <= enddata) {
*stringVar = (char*)*pptr;
*stringVar = (char *) *pptr;
*pptr += *stringLen;
rc = SUCCESS;
}
@@ -97,7 +101,7 @@ static IoT_Error_t _aws_iot_mqtt_internal_serialize_publish(unsigned char *pTxBu
ptr = pTxBuf;
rem_len = 0;
rem_len += (uint32_t)(topicNameLen + payloadLen + 2);
rem_len += (uint32_t) (topicNameLen + payloadLen + 2);
if(qos > 0) {
rem_len += 2; /* packetId */
}
@@ -122,7 +126,7 @@ static IoT_Error_t _aws_iot_mqtt_internal_serialize_publish(unsigned char *pTxBu
memcpy(ptr, pPayload, payloadLen);
ptr += payloadLen;
*pSerializedLen = (uint32_t)(ptr - pTxBuf);
*pSerializedLen = (uint32_t) (ptr - pTxBuf);
FUNC_EXIT_RC(SUCCESS);
}
@@ -167,7 +171,7 @@ IoT_Error_t aws_iot_mqtt_internal_serialize_ack(unsigned char *pTxBuf, size_t tx
ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, 2); /* write remaining length */
aws_iot_mqtt_internal_write_uint_16(&ptr, packetId);
*pSerializedLen = (uint32_t)(ptr - pTxBuf);
*pSerializedLen = (uint32_t) (ptr - pTxBuf);
FUNC_EXIT_RC(SUCCESS);
}
@@ -261,7 +265,7 @@ IoT_Error_t aws_iot_mqtt_publish(AWS_IoT_Client *pClient, const char *pTopicName
FUNC_ENTRY;
if(NULL == pClient || NULL == pTopicName || NULL == pParams) {
if(NULL == pClient || NULL == pTopicName || 0 == topicNameLen || NULL == pParams) {
FUNC_EXIT_RC(NULL_VALUE_ERROR);
}
@@ -338,7 +342,7 @@ IoT_Error_t aws_iot_mqtt_internal_deserialize_publish(uint8_t *dup, QoS *qos,
}
*dup = header.bits.dup;
*qos = (QoS)header.bits.qos;
*qos = (QoS) header.bits.qos;
*retained = header.bits.retain;
/* read remaining length */
@@ -360,7 +364,7 @@ IoT_Error_t aws_iot_mqtt_internal_deserialize_publish(uint8_t *dup, QoS *qos,
*pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curData);
}
*payloadLen = (size_t)(endData - curData);
*payloadLen = (size_t) (endData - curData);
*payload = curData;
FUNC_EXIT_RC(SUCCESS);
@@ -418,3 +422,7 @@ IoT_Error_t aws_iot_mqtt_internal_deserialize_ack(unsigned char *pPacketType, un
FUNC_EXIT_RC(SUCCESS);
}
#ifdef __cplusplus
}
#endif

View File

@@ -35,6 +35,10 @@
* @brief MQTT client subscribe API definitions
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "aws_iot_mqtt_client_common_internal.h"
/**
@@ -68,7 +72,7 @@ static IoT_Error_t _aws_iot_mqtt_serialize_subscribe(unsigned char *pTxBuf, size
rem_len = 2; /* packetId */
for(itr = 0; itr < topicCount; ++itr) {
rem_len += (uint32_t)(pTopicNameLenList[itr] + 2 + 1); /* topic + length + req_qos */
rem_len += (uint32_t) (pTopicNameLenList[itr] + 2 + 1); /* topic + length + req_qos */
}
if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) {
@@ -92,7 +96,7 @@ static IoT_Error_t _aws_iot_mqtt_serialize_subscribe(unsigned char *pTxBuf, size
aws_iot_mqtt_internal_write_char(&ptr, (unsigned char) pRequestedQoSs[itr]);
}
*pSerializedLen = (uint32_t)(ptr - pTxBuf);
*pSerializedLen = (uint32_t) (ptr - pTxBuf);
FUNC_EXIT_RC(SUCCESS);
}
@@ -135,7 +139,7 @@ static IoT_Error_t _aws_iot_mqtt_deserialize_suback(uint16_t *pPacketId, uint32_
}
header.byte = aws_iot_mqtt_internal_read_char(&curData);
if (SUBACK != header.bits.type) {
if(SUBACK != header.bits.type) {
FUNC_EXIT_RC(FAILURE);
}
@@ -147,7 +151,7 @@ static IoT_Error_t _aws_iot_mqtt_deserialize_suback(uint16_t *pPacketId, uint32_
curData += (readBytesLen);
endData = curData + decodedLen;
if (endData - curData < 2) {
if(endData - curData < 2) {
FUNC_EXIT_RC(FAILURE);
}
@@ -158,7 +162,7 @@ static IoT_Error_t _aws_iot_mqtt_deserialize_suback(uint16_t *pPacketId, uint32_
if(*pGrantedQoSCount > maxExpectedQoSCount) {
FUNC_EXIT_RC(FAILURE);
}
pGrantedQoSs[(*pGrantedQoSCount)++] = (QoS)aws_iot_mqtt_internal_read_char(&curData);
pGrantedQoSs[(*pGrantedQoSCount)++] = (QoS) aws_iot_mqtt_internal_read_char(&curData);
}
FUNC_EXIT_RC(SUCCESS);
@@ -215,7 +219,7 @@ static IoT_Error_t _aws_iot_mqtt_internal_subscribe(AWS_IoT_Client *pClient, con
rxPacketId = 0;
rc = _aws_iot_mqtt_serialize_subscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0,
txPacketId, 1, &pTopicName, &topicNameLen, &qos, &serializedLen);
txPacketId, 1, &pTopicName, &topicNameLen, &qos, &serializedLen);
if(SUCCESS != rc) {
FUNC_EXIT_RC(rc);
}
@@ -296,7 +300,7 @@ IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicNa
}
clientState = aws_iot_mqtt_get_client_state(pClient);
if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) {
if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) {
FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR);
}
@@ -306,7 +310,7 @@ IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicNa
}
subRc = _aws_iot_mqtt_internal_subscribe(pClient, pTopicName, topicNameLen, qos,
pApplicationHandler, pApplicationHandlerData);
pApplicationHandler, pApplicationHandlerData);
rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS, clientState);
if(SUCCESS == subRc && SUCCESS != rc) {
@@ -409,14 +413,16 @@ IoT_Error_t aws_iot_mqtt_resubscribe(AWS_IoT_Client *pClient) {
FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR);
}
rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE, CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS);
rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE,
CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS);
if(SUCCESS != rc) {
FUNC_EXIT_RC(rc);
}
resubRc = _aws_iot_mqtt_internal_resubscribe(pClient);
rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS, CLIENT_STATE_CONNECTED_IDLE);
rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS,
CLIENT_STATE_CONNECTED_IDLE);
if(SUCCESS == resubRc && SUCCESS != rc) {
resubRc = rc;
}
@@ -424,3 +430,7 @@ IoT_Error_t aws_iot_mqtt_resubscribe(AWS_IoT_Client *pClient) {
FUNC_EXIT_RC(resubRc);
}
#ifdef __cplusplus
}
#endif

View File

@@ -35,6 +35,10 @@
* @brief MQTT client unsubscribe API definitions
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "aws_iot_mqtt_client_common_internal.h"
/**
@@ -61,7 +65,7 @@ static IoT_Error_t _aws_iot_mqtt_serialize_unsubscribe(unsigned char *pTxBuf, si
FUNC_ENTRY;
for(i = 0; i < count; ++i) {
rem_len += (uint32_t)(pTopicNameLenList[i] + 2); /* topic + length */
rem_len += (uint32_t) (pTopicNameLenList[i] + 2); /* topic + length */
}
if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) {
@@ -82,7 +86,7 @@ static IoT_Error_t _aws_iot_mqtt_serialize_unsubscribe(unsigned char *pTxBuf, si
aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicNameList[i], pTopicNameLenList[i]);
}
*pSerializedLen = (uint32_t)(ptr - pTxBuf);
*pSerializedLen = (uint32_t) (ptr - pTxBuf);
FUNC_EXIT_RC(SUCCESS);
}
@@ -125,7 +129,8 @@ static IoT_Error_t _aws_iot_mqtt_deserialize_unsuback(uint16_t *pPacketId, unsig
*
* @return An IoT Error Type defining successful/failed unsubscribe call
*/
static IoT_Error_t _aws_iot_mqtt_internal_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, uint16_t topicFilterLen) {
static IoT_Error_t _aws_iot_mqtt_internal_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter,
uint16_t topicFilterLen) {
/* No NULL checks because this is a static internal function */
Timer timer;
@@ -133,9 +138,22 @@ static IoT_Error_t _aws_iot_mqtt_internal_unsubscribe(AWS_IoT_Client *pClient, c
uint32_t serializedLen = 0;
uint32_t i = 0;
IoT_Error_t rc;
bool subscriptionExists = false;
FUNC_ENTRY;
/* Remove from message handler array */
for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) {
if(pClient->clientData.messageHandlers[i].topicName != NULL &&
(strcmp(pClient->clientData.messageHandlers[i].topicName, pTopicFilter) == 0)) {
subscriptionExists = true;
}
}
if(false == subscriptionExists) {
FUNC_EXIT_RC(FAILURE);
}
init_timer(&timer);
countdown_ms(&timer, pClient->clientData.commandTimeoutMs);
@@ -200,12 +218,13 @@ IoT_Error_t aws_iot_mqtt_unsubscribe(AWS_IoT_Client *pClient, const char *pTopic
return NETWORK_DISCONNECTED_ERROR;
}
ClientState clientState = aws_iot_mqtt_get_client_state(pClient);
ClientState clientState = aws_iot_mqtt_get_client_state(pClient);
if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) {
return MQTT_CLIENT_NOT_IDLE_ERROR;
}
IoT_Error_t rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS);
IoT_Error_t rc = aws_iot_mqtt_set_client_state(pClient, clientState,
CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS);
if(SUCCESS != rc) {
rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS, clientState);
return rc;
@@ -221,3 +240,7 @@ IoT_Error_t aws_iot_mqtt_unsubscribe(AWS_IoT_Client *pClient, const char *pTopic
return unsubRc;
}
#ifdef __cplusplus
}
#endif

View File

@@ -35,34 +35,38 @@
* @brief MQTT client yield API definitions
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "aws_iot_mqtt_client_common_internal.h"
/**
* This is for the case when the aws_iot_mqtt_internal_send_packet Fails.
*/
static void _aws_iot_mqtt_force_client_disconnect(AWS_IoT_Client *pClient) {
pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_ERROR;
pClient->networkStack.disconnect(&(pClient->networkStack));
pClient->networkStack.destroy(&(pClient->networkStack));
pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_ERROR;
pClient->networkStack.disconnect(&(pClient->networkStack));
pClient->networkStack.destroy(&(pClient->networkStack));
}
static IoT_Error_t _aws_iot_mqtt_handle_disconnect(AWS_IoT_Client *pClient) {
IoT_Error_t rc;
IoT_Error_t rc;
FUNC_ENTRY;
rc = aws_iot_mqtt_disconnect(pClient);
if(rc != SUCCESS) {
// If the aws_iot_mqtt_internal_send_packet prevents us from sending a disconnect packet then we have to clean the stack
_aws_iot_mqtt_force_client_disconnect(pClient);
}
if(rc != SUCCESS) {
// If the aws_iot_mqtt_internal_send_packet prevents us from sending a disconnect packet then we have to clean the stack
_aws_iot_mqtt_force_client_disconnect(pClient);
}
if(NULL != pClient->clientData.disconnectHandler) {
pClient->clientData.disconnectHandler(pClient, pClient->clientData.disconnectHandlerData);
}
if(NULL != pClient->clientData.disconnectHandler) {
pClient->clientData.disconnectHandler(pClient, pClient->clientData.disconnectHandlerData);
}
/* Reset to 0 since this was not a manual disconnect */
pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_ERROR;
/* Reset to 0 since this was not a manual disconnect */
pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_ERROR;
FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR);
}
@@ -72,35 +76,35 @@ static IoT_Error_t _aws_iot_mqtt_handle_reconnect(AWS_IoT_Client *pClient) {
FUNC_ENTRY;
if(!has_timer_expired(&(pClient->reconnectDelayTimer))) {
/* Timer has not expired. Not time to attempt reconnect yet.
* Return attempting reconnect */
if(!has_timer_expired(&(pClient->reconnectDelayTimer))) {
/* Timer has not expired. Not time to attempt reconnect yet.
* Return attempting reconnect */
FUNC_EXIT_RC(NETWORK_ATTEMPTING_RECONNECT);
}
}
rc = NETWORK_PHYSICAL_LAYER_DISCONNECTED;
if(NULL != pClient->networkStack.isConnected) {
rc = NETWORK_PHYSICAL_LAYER_DISCONNECTED;
if(NULL != pClient->networkStack.isConnected) {
rc = pClient->networkStack.isConnected(&(pClient->networkStack));
}
}
if(NETWORK_PHYSICAL_LAYER_CONNECTED == rc) {
rc = aws_iot_mqtt_attempt_reconnect(pClient);
if(NETWORK_RECONNECTED == rc) {
if(NETWORK_PHYSICAL_LAYER_CONNECTED == rc) {
rc = aws_iot_mqtt_attempt_reconnect(pClient);
if(NETWORK_RECONNECTED == rc) {
rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE,
CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS);
if(SUCCESS != rc) {
FUNC_EXIT_RC(rc);
}
FUNC_EXIT_RC(NETWORK_RECONNECTED);
}
}
}
}
pClient->clientData.currentReconnectWaitInterval *= 2;
pClient->clientData.currentReconnectWaitInterval *= 2;
if(AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL < pClient->clientData.currentReconnectWaitInterval) {
if(AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL < pClient->clientData.currentReconnectWaitInterval) {
FUNC_EXIT_RC(NETWORK_RECONNECT_TIMED_OUT_ERROR);
}
countdown_ms(&(pClient->reconnectDelayTimer), pClient->clientData.currentReconnectWaitInterval);
}
countdown_ms(&(pClient->reconnectDelayTimer), pClient->clientData.currentReconnectWaitInterval);
FUNC_EXIT_RC(rc);
}
@@ -109,44 +113,46 @@ static IoT_Error_t _aws_iot_mqtt_keep_alive(AWS_IoT_Client *pClient) {
Timer timer;
size_t serialized_len;
if(NULL == pClient) {
FUNC_ENTRY;
if(NULL == pClient) {
FUNC_EXIT_RC(NULL_VALUE_ERROR);
}
}
if(0 == pClient->clientData.keepAliveInterval) {
if(0 == pClient->clientData.keepAliveInterval) {
FUNC_EXIT_RC(SUCCESS);
}
}
if(!has_timer_expired(&pClient->pingTimer)) {
if(!has_timer_expired(&pClient->pingTimer)) {
FUNC_EXIT_RC(SUCCESS);
}
}
if(pClient->clientStatus.isPingOutstanding) {
rc = _aws_iot_mqtt_handle_disconnect(pClient);
if(pClient->clientStatus.isPingOutstanding) {
rc = _aws_iot_mqtt_handle_disconnect(pClient);
FUNC_EXIT_RC(rc);
}
}
/* there is no ping outstanding - send one */
/* there is no ping outstanding - send one */
init_timer(&timer);
countdown_ms(&timer, pClient->clientData.commandTimeoutMs);
serialized_len = 0;
rc = aws_iot_mqtt_internal_serialize_zero(pClient->clientData.writeBuf, pClient->clientData.writeBufSize,
countdown_ms(&timer, pClient->clientData.commandTimeoutMs);
serialized_len = 0;
rc = aws_iot_mqtt_internal_serialize_zero(pClient->clientData.writeBuf, pClient->clientData.writeBufSize,
PINGREQ, &serialized_len);
if(SUCCESS != rc) {
if(SUCCESS != rc) {
FUNC_EXIT_RC(rc);
}
}
/* send the ping packet */
rc = aws_iot_mqtt_internal_send_packet(pClient, serialized_len, &timer);
if(SUCCESS != rc) {
//If sending a PING fails we can no longer determine if we are connected. In this case we decide we are disconnected and begin reconnection attempts
rc = _aws_iot_mqtt_handle_disconnect(pClient);
/* send the ping packet */
rc = aws_iot_mqtt_internal_send_packet(pClient, serialized_len, &timer);
if(SUCCESS != rc) {
//If sending a PING fails we can no longer determine if we are connected. In this case we decide we are disconnected and begin reconnection attempts
rc = _aws_iot_mqtt_handle_disconnect(pClient);
FUNC_EXIT_RC(rc);
}
}
pClient->clientStatus.isPingOutstanding = 1;
/* start a timer to wait for PINGRESP from server */
countdown_sec(&pClient->pingTimer, pClient->clientData.keepAliveInterval / (uint32_t)2);
pClient->clientStatus.isPingOutstanding = true;
/* start a timer to wait for PINGRESP from server */
countdown_sec(&pClient->pingTimer, pClient->clientData.keepAliveInterval / (uint32_t) 2);
FUNC_EXIT_RC(SUCCESS);
}
@@ -205,7 +211,7 @@ static IoT_Error_t _aws_iot_mqtt_internal_yield(AWS_IoT_Client *pClient, uint32_
if(1 == pClient->clientStatus.isAutoReconnectEnabled) {
yieldRc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_DISCONNECTED_ERROR,
CLIENT_STATE_PENDING_RECONNECT);
if (SUCCESS != yieldRc) {
if(SUCCESS != yieldRc) {
FUNC_EXIT_RC(yieldRc);
}
@@ -249,7 +255,7 @@ IoT_Error_t aws_iot_mqtt_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms) {
IoT_Error_t rc, yieldRc;
ClientState clientState;
if(NULL == pClient) {
if(NULL == pClient || 0 == timeout_ms) {
FUNC_EXIT_RC(NULL_VALUE_ERROR);
}
@@ -282,8 +288,9 @@ IoT_Error_t aws_iot_mqtt_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms) {
yieldRc = _aws_iot_mqtt_internal_yield(pClient, timeout_ms);
if(NETWORK_DISCONNECTED_ERROR != yieldRc && NETWORK_ATTEMPTING_RECONNECT != yieldRc) {
rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS, CLIENT_STATE_CONNECTED_IDLE);
if (SUCCESS == yieldRc && SUCCESS != rc) {
rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS,
CLIENT_STATE_CONNECTED_IDLE);
if(SUCCESS == yieldRc && SUCCESS != rc) {
yieldRc = rc;
}
}
@@ -291,3 +298,7 @@ IoT_Error_t aws_iot_mqtt_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms) {
FUNC_EXIT_RC(yieldRc);
}
#ifdef __cplusplus
}
#endif

View File

@@ -13,8 +13,18 @@
* permissions and limitations under the License.
*/
#include <aws_iot_mqtt_client_interface.h>
#include <aws_iot_shadow_interface.h>
/**
* @file aws_iot_shadow.c
* @brief Shadow client API definitions
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <string.h>
#include "aws_iot_mqtt_client_interface.h"
#include "aws_iot_shadow_interface.h"
#include "aws_iot_error.h"
#include "aws_iot_log.h"
#include "aws_iot_shadow_actions.h"
@@ -22,18 +32,11 @@
#include "aws_iot_shadow_key.h"
#include "aws_iot_shadow_records.h"
const ShadowInitParameters_t ShadowInitParametersDefault = {
.pHost = AWS_IOT_MQTT_HOST,
.port = AWS_IOT_MQTT_PORT,
.pRootCA = NULL,
.pClientCRT = NULL,
.pClientKey = NULL
};
const ShadowInitParameters_t ShadowInitParametersDefault = {(char *) AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, NULL, NULL,
NULL, false, NULL};
const ShadowConnectParameters_t ShadowConnectParametersDefault = {
.pMyThingName = AWS_IOT_MY_THING_NAME,
.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID
};
const ShadowConnectParameters_t ShadowConnectParametersDefault = {(char *) AWS_IOT_MY_THING_NAME,
(char *) AWS_IOT_MQTT_CLIENT_ID, 0};
void aws_iot_shadow_reset_last_received_version(void) {
shadowJsonVersionNum = 0;
@@ -52,52 +55,59 @@ void aws_iot_shadow_disable_discard_old_delta_msgs(void) {
}
IoT_Error_t aws_iot_shadow_init(AWS_IoT_Client *pClient, ShadowInitParameters_t *pParams) {
if (pClient == NULL) {
return NULL_VALUE_ERROR;
IoT_Client_Init_Params mqttInitParams;
IoT_Error_t rc;
FUNC_ENTRY;
if(NULL == pClient || NULL == pParams) {
FUNC_EXIT_RC(NULL_VALUE_ERROR);
}
IoT_Client_Init_Params mqttInitParams;
mqttInitParams.enableAutoReconnect = pParams->enableAutoReconnect;
mqttInitParams.pHostURL = pParams->pHost;
mqttInitParams.pHostURL = pParams->pHost;
mqttInitParams.port = pParams->port;
mqttInitParams.pRootCALocation = pParams->pRootCA;
mqttInitParams.pDeviceCertLocation = pParams->pClientCRT;
mqttInitParams.pDevicePrivateKeyLocation = pParams->pClientKey;
mqttInitParams.mqttCommandTimeout_ms = 2000;
mqttInitParams.tlsHandshakeTimeout_ms = 10000;
mqttInitParams.mqttCommandTimeout_ms = 20000;
mqttInitParams.tlsHandshakeTimeout_ms = 5000;
mqttInitParams.isSSLHostnameVerify = true;
mqttInitParams.disconnectHandler = pParams->disconnectHandler;
IoT_Error_t rc = aws_iot_mqtt_init(pClient, &mqttInitParams);
rc = aws_iot_mqtt_init(pClient, &mqttInitParams);
if(SUCCESS != rc) {
return rc;
FUNC_EXIT_RC(rc);
}
resetClientTokenSequenceNum();
aws_iot_shadow_reset_last_received_version();
initDeltaTokens();
return SUCCESS;
FUNC_EXIT_RC(SUCCESS);
}
IoT_Error_t aws_iot_shadow_connect(AWS_IoT_Client *pClient, ShadowConnectParameters_t *pParams) {
if(NULL == pClient || NULL == pParams || NULL == pParams->pMqttClientId) {
return NULL_VALUE_ERROR;
}
IoT_Error_t rc = SUCCESS;
char deleteAcceptedTopic[MAX_SHADOW_TOPIC_LENGTH_BYTES];
uint16_t deleteAcceptedTopicLen;
IoT_Client_Connect_Params ConnectParams = iotClientConnectParamsDefault;
FUNC_ENTRY;
if(NULL == pClient || NULL == pParams || NULL == pParams->pMqttClientId) {
FUNC_EXIT_RC(NULL_VALUE_ERROR);
}
snprintf(myThingName, MAX_SIZE_OF_THING_NAME, "%s", pParams->pMyThingName);
snprintf(mqttClientID, MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES, "%s", pParams->pMqttClientId);
DEBUG("Thing Name %s", myThingName);
DEBUG("MQTT Client ID %s", mqttClientID);
ConnectParams.keepAliveIntervalInSec = 10;
ConnectParams.MQTTVersion = MQTT_3_1_1;
ConnectParams.isCleanSession = true;
ConnectParams.isWillMsgPresent = false;
ConnectParams.pClientID = pParams->pMqttClientId;
ConnectParams.clientIDLen = pParams->mqttClientIdLen;
ConnectParams.pPassword = NULL;
ConnectParams.pUsername = NULL;
@@ -107,7 +117,15 @@ IoT_Error_t aws_iot_shadow_connect(AWS_IoT_Client *pClient, ShadowConnectParamet
initializeRecords(pClient);
}
return rc;
if(NULL != pParams->deleteActionHandler) {
snprintf(deleteAcceptedTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES,
"$aws/things/%s/shadow/delete/accepted", myThingName);
deleteAcceptedTopicLen = (uint16_t) strlen(deleteAcceptedTopic);
rc = aws_iot_mqtt_subscribe(pClient, deleteAcceptedTopic, deleteAcceptedTopicLen, QOS1,
pParams->deleteActionHandler, (void *) myThingName);
}
FUNC_EXIT_RC(rc);
}
IoT_Error_t aws_iot_shadow_register_delta(AWS_IoT_Client *pMqttClient, jsonStruct_t *pStruct) {
@@ -123,63 +141,85 @@ IoT_Error_t aws_iot_shadow_register_delta(AWS_IoT_Client *pMqttClient, jsonStruc
}
IoT_Error_t aws_iot_shadow_yield(AWS_IoT_Client *pClient, uint32_t timeout) {
if(NULL == pClient) {
return NULL_VALUE_ERROR;
}
HandleExpiredResponseCallbacks();
return aws_iot_mqtt_yield(pClient, timeout);
}
IoT_Error_t aws_iot_shadow_disconnect(AWS_IoT_Client *pClient) {return aws_iot_mqtt_disconnect(pClient);
IoT_Error_t aws_iot_shadow_disconnect(AWS_IoT_Client *pClient) {
return aws_iot_mqtt_disconnect(pClient);
}
IoT_Error_t aws_iot_shadow_update(AWS_IoT_Client *pClient, const char *pThingName, char *pJsonString,
fpActionCallback_t callback, void *pContextData, uint8_t timeout_seconds,
bool isPersistentSubscribe) {
fpActionCallback_t callback, void *pContextData, uint8_t timeout_seconds,
bool isPersistentSubscribe) {
IoT_Error_t rc;
if(NULL == pClient) {
return NULL_VALUE_ERROR;
FUNC_EXIT_RC(NULL_VALUE_ERROR);
}
if(!aws_iot_mqtt_is_client_connected(pClient)) {
return MQTT_CONNECTION_ERROR;
FUNC_EXIT_RC(MQTT_CONNECTION_ERROR);
}
return iot_shadow_action(pThingName, SHADOW_UPDATE, pJsonString, callback, pContextData,
timeout_seconds, isPersistentSubscribe);
rc = aws_iot_shadow_internal_action(pThingName, SHADOW_UPDATE, pJsonString, callback, pContextData,
timeout_seconds, isPersistentSubscribe);
FUNC_EXIT_RC(rc);
}
IoT_Error_t aws_iot_shadow_delete(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback,
void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe) {
if(NULL == pClient) {
return NULL_VALUE_ERROR;
}
if (!aws_iot_mqtt_is_client_connected(pClient)) {
return MQTT_CONNECTION_ERROR;
}
void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe) {
char deleteRequestJsonBuf[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE];
iot_shadow_delete_request_json(deleteRequestJsonBuf);
return iot_shadow_action(pThingName, SHADOW_DELETE, deleteRequestJsonBuf, callback, pContextData,
timeout_seconds, isPersistentSubscribe);
IoT_Error_t rc;
FUNC_ENTRY;
if(NULL == pClient) {
FUNC_EXIT_RC(NULL_VALUE_ERROR);
}
if(!aws_iot_mqtt_is_client_connected(pClient)) {
FUNC_EXIT_RC(MQTT_CONNECTION_ERROR);
}
aws_iot_shadow_internal_delete_request_json(deleteRequestJsonBuf);
rc = aws_iot_shadow_internal_action(pThingName, SHADOW_DELETE, deleteRequestJsonBuf, callback, pContextData,
timeout_seconds, isPersistentSubscribe);
FUNC_EXIT_RC(rc);
}
IoT_Error_t aws_iot_shadow_get(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback,
void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe) {
if(NULL == pClient) {
return NULL_VALUE_ERROR;
}
if (!aws_iot_mqtt_is_client_connected(pClient)) {
return MQTT_CONNECTION_ERROR;
}
void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe) {
char getRequestJsonBuf[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE];
IoT_Error_t rc;
iot_shadow_get_request_json(getRequestJsonBuf);
FUNC_ENTRY;
return iot_shadow_action(pThingName, SHADOW_GET, getRequestJsonBuf, callback, pContextData,
timeout_seconds, isPersistentSubscribe);
if(NULL == pClient) {
FUNC_EXIT_RC(NULL_VALUE_ERROR);
}
if(!aws_iot_mqtt_is_client_connected(pClient)) {
FUNC_EXIT_RC(MQTT_CONNECTION_ERROR);
}
aws_iot_shadow_internal_get_request_json(getRequestJsonBuf);
rc = aws_iot_shadow_internal_action(pThingName, SHADOW_GET, getRequestJsonBuf, callback, pContextData,
timeout_seconds, isPersistentSubscribe);
FUNC_EXIT_RC(rc);
}
IoT_Error_t aws_iot_shadow_set_autoreconnect_status(AWS_IoT_Client *pClient, bool newStatus) {
return aws_iot_mqtt_autoreconnect_set_status(pClient, newStatus);
}
#ifdef __cplusplus
}
#endif

View File

@@ -13,6 +13,15 @@
* permissions and limitations under the License.
*/
/**
* @file aws_iot_shadow_actions.c
* @brief Shadow client Action API definitions
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "aws_iot_shadow_actions.h"
#include "aws_iot_log.h"
@@ -20,34 +29,30 @@
#include "aws_iot_shadow_records.h"
#include "aws_iot_config.h"
IoT_Error_t iot_shadow_action(const char *pThingName, ShadowActions_t action,
const char *pJsonDocumentToBeSent, fpActionCallback_t callback, void *pCallbackContext,
uint32_t timeout_seconds, bool isSticky) {
IoT_Error_t aws_iot_shadow_internal_action(const char *pThingName, ShadowActions_t action,
const char *pJsonDocumentToBeSent, fpActionCallback_t callback,
void *pCallbackContext, uint32_t timeout_seconds, bool isSticky) {
IoT_Error_t ret_val = SUCCESS;
bool isCallbackPresent = false;
bool isClientTokenPresent = false;
bool isAckWaitListFree = false;
uint8_t indexAckWaitList;
if(pThingName == NULL || pJsonDocumentToBeSent == NULL){
return NULL_VALUE_ERROR;
}
if (callback != NULL) {
isCallbackPresent = true;
}
char extractedClientToken[MAX_SIZE_CLIENT_ID_WITH_SEQUENCE];
FUNC_ENTRY;
if(NULL == pThingName || NULL == pJsonDocumentToBeSent) {
FUNC_EXIT_RC(NULL_VALUE_ERROR);
}
isClientTokenPresent = extractClientToken(pJsonDocumentToBeSent, extractedClientToken);
if (isClientTokenPresent && isCallbackPresent) {
if (getNextFreeIndexOfAckWaitList(&indexAckWaitList)) {
if(isClientTokenPresent && (NULL != callback)) {
if(getNextFreeIndexOfAckWaitList(&indexAckWaitList)) {
isAckWaitListFree = true;
}
if(isAckWaitListFree) {
if (!isSubscriptionPresent(pThingName, action)) {
if(!isSubscriptionPresent(pThingName, action)) {
ret_val = subscribeToShadowActionAcks(pThingName, action, isSticky);
} else {
incrementSubscriptionCnt(pThingName, action, isSticky);
@@ -58,14 +63,18 @@ IoT_Error_t iot_shadow_action(const char *pThingName, ShadowActions_t action,
}
}
if (ret_val == SUCCESS) {
if(SUCCESS == ret_val) {
ret_val = publishToShadowAction(pThingName, action, pJsonDocumentToBeSent);
}
if (isClientTokenPresent && isCallbackPresent && ret_val == SUCCESS && isAckWaitListFree) {
if(isClientTokenPresent && (NULL != callback) && (SUCCESS == ret_val) && isAckWaitListFree) {
addToAckWaitList(indexAckWaitList, pThingName, action, extractedClientToken, callback, pCallbackContext,
timeout_seconds);
timeout_seconds);
}
return ret_val;
FUNC_EXIT_RC(ret_val);
}
#ifdef __cplusplus
}
#endif

View File

@@ -13,11 +13,25 @@
* permissions and limitations under the License.
*/
/**
* @file aws_iot_shadow_json.c
* @brief Shadow client JSON parsing API definitions
*/
#ifdef __cplusplus
extern "C" {
#include <cinttypes>
#else
#include <inttypes.h>
#endif
#include "aws_iot_shadow_json.h"
#include <string.h>
#include <stdbool.h>
#include <inttypes.h>
#include "aws_iot_json_utils.h"
#include "aws_iot_log.h"
#include "aws_iot_shadow_key.h"
@@ -41,18 +55,18 @@ static void emptyJsonWithClientToken(char *pJsonDocument) {
sprintf(pJsonDocument + strlen(pJsonDocument), "\"}");
}
void iot_shadow_get_request_json(char *pJsonDocument) {
void aws_iot_shadow_internal_get_request_json(char *pJsonDocument) {
emptyJsonWithClientToken(pJsonDocument);
}
void iot_shadow_delete_request_json(char *pJsonDocument) {
void aws_iot_shadow_internal_delete_request_json(char *pJsonDocument) {
emptyJsonWithClientToken(pJsonDocument);
}
static inline IoT_Error_t checkReturnValueOfSnPrintf(int32_t snPrintfReturn, size_t maxSizeOfJsonDocument) {
if(snPrintfReturn < 0) {
return SHADOW_JSON_ERROR;
} else if((size_t)snPrintfReturn >= maxSizeOfJsonDocument) {
} else if((size_t) snPrintfReturn >= maxSizeOfJsonDocument) {
return SHADOW_JSON_BUFFER_TRUNCATED;
}
return SUCCESS;
@@ -281,17 +295,17 @@ static IoT_Error_t convertDataToString(char *pStringBuffer, size_t maxSizoString
}
if(type == SHADOW_JSON_INT32) {
snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%"PRIi32",", *(int32_t *) (pData));
snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIi32",", *(int32_t *) (pData));
} else if(type == SHADOW_JSON_INT16) {
snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%"PRIi16",", *(int16_t *) (pData));
snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIi16",", *(int16_t *) (pData));
} else if(type == SHADOW_JSON_INT8) {
snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%"PRIi8",", *(int8_t *) (pData));
snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIi8",", *(int8_t *) (pData));
} else if(type == SHADOW_JSON_UINT32) {
snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%"PRIu32",", *(uint32_t *) (pData));
snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIu32",", *(uint32_t *) (pData));
} else if(type == SHADOW_JSON_UINT16) {
snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%"PRIu16",", *(uint16_t *) (pData));
snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIu16",", *(uint16_t *) (pData));
} else if(type == SHADOW_JSON_UINT8) {
snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%"PRIu8",", *(uint8_t *) (pData));
snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIu8",", *(uint8_t *) (pData));
} else if(type == SHADOW_JSON_DOUBLE) {
snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%f,", *(double *) (pData));
} else if(type == SHADOW_JSON_FLOAT) {
@@ -319,13 +333,13 @@ bool isJsonValidAndParse(const char *pJsonDocument, void *pJsonHandler, int32_t
sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0]));
if(tokenCount < 0) {
WARN("Failed to parse JSON: %d\n", tokenCount);
IOT_WARN("Failed to parse JSON: %d\n", tokenCount);
return false;
}
/* Assume the top-level element is an object */
if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) {
WARN("Top Level is not an object\n");
IOT_WARN("Top Level is not an object\n");
return false;
}
@@ -338,23 +352,23 @@ bool isJsonValidAndParse(const char *pJsonDocument, void *pJsonHandler, int32_t
static IoT_Error_t UpdateValueIfNoObject(const char *pJsonString, jsonStruct_t *pDataStruct, jsmntok_t token) {
IoT_Error_t ret_val = SUCCESS;
if(pDataStruct->type == SHADOW_JSON_BOOL) {
ret_val = parseBooleanValue(pDataStruct->pData, pJsonString, &token);
ret_val = parseBooleanValue((bool *) pDataStruct->pData, pJsonString, &token);
} else if(pDataStruct->type == SHADOW_JSON_INT32) {
ret_val = parseInteger32Value(pDataStruct->pData, pJsonString, &token);
ret_val = parseInteger32Value((int32_t *) pDataStruct->pData, pJsonString, &token);
} else if(pDataStruct->type == SHADOW_JSON_INT16) {
ret_val = parseInteger16Value(pDataStruct->pData, pJsonString, &token);
ret_val = parseInteger16Value((int16_t *) pDataStruct->pData, pJsonString, &token);
} else if(pDataStruct->type == SHADOW_JSON_INT8) {
ret_val = parseInteger8Value(pDataStruct->pData, pJsonString, &token);
ret_val = parseInteger8Value((int8_t *) pDataStruct->pData, pJsonString, &token);
} else if(pDataStruct->type == SHADOW_JSON_UINT32) {
ret_val = parseUnsignedInteger32Value(pDataStruct->pData, pJsonString, &token);
ret_val = parseUnsignedInteger32Value((uint32_t *) pDataStruct->pData, pJsonString, &token);
} else if(pDataStruct->type == SHADOW_JSON_UINT16) {
ret_val = parseUnsignedInteger16Value(pDataStruct->pData, pJsonString, &token);
ret_val = parseUnsignedInteger16Value((uint16_t *) pDataStruct->pData, pJsonString, &token);
} else if(pDataStruct->type == SHADOW_JSON_UINT8) {
ret_val = parseUnsignedInteger8Value(pDataStruct->pData, pJsonString, &token);
ret_val = parseUnsignedInteger8Value((uint8_t *) pDataStruct->pData, pJsonString, &token);
} else if(pDataStruct->type == SHADOW_JSON_FLOAT) {
ret_val = parseFloatValue(pDataStruct->pData, pJsonString, &token);
ret_val = parseFloatValue((float *) pDataStruct->pData, pJsonString, &token);
} else if(pDataStruct->type == SHADOW_JSON_DOUBLE) {
ret_val = parseDoubleValue(pDataStruct->pData, pJsonString, &token);
ret_val = parseDoubleValue((double *) pDataStruct->pData, pJsonString, &token);
}
return ret_val;
@@ -371,7 +385,7 @@ bool isJsonKeyMatchingAndUpdateValue(const char *pJsonDocument, void *pJsonHandl
for(i = 1; i < tokenCount; i++) {
if(jsoneq(pJsonDocument, &(jsonTokenStruct[i]), pDataStruct->pKey) == 0) {
dataToken = jsonTokenStruct[i + 1];
dataLength = (uint32_t)(dataToken.end - dataToken.start);
dataLength = (uint32_t) (dataToken.end - dataToken.start);
UpdateValueIfNoObject(pJsonDocument, pDataStruct, dataToken);
*pDataPosition = dataToken.start;
*pDataLength = dataLength;
@@ -390,7 +404,7 @@ bool isReceivedJsonValid(const char *pJsonDocument) {
sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0]));
if(tokenCount < 0) {
WARN("Failed to parse JSON: %d\n", tokenCount);
IOT_WARN("Failed to parse JSON: %d\n", tokenCount);
return false;
}
@@ -412,7 +426,7 @@ bool extractClientToken(const char *pJsonDocument, char *pExtractedClientToken)
sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0]));
if(tokenCount < 0) {
WARN("Failed to parse JSON: %d\n", tokenCount);
IOT_WARN("Failed to parse JSON: %d\n", tokenCount);
return false;
}
@@ -424,7 +438,7 @@ bool extractClientToken(const char *pJsonDocument, char *pExtractedClientToken)
for(i = 1; i < tokenCount; i++) {
if(jsoneq(pJsonDocument, &jsonTokenStruct[i], SHADOW_CLIENT_TOKEN_STRING) == 0) {
ClientJsonToken = jsonTokenStruct[i + 1];
length = (uint8_t)(ClientJsonToken.end - ClientJsonToken.start);
length = (uint8_t) (ClientJsonToken.end - ClientJsonToken.start);
strncpy(pExtractedClientToken, pJsonDocument + ClientJsonToken.start, length);
pExtractedClientToken[length] = '\0';
return true;
@@ -451,3 +465,7 @@ bool extractVersionNumber(const char *pJsonDocument, void *pJsonHandler, int32_t
return false;
}
#ifdef __cplusplus
}
#endif

View File

@@ -13,6 +13,15 @@
* permissions and limitations under the License.
*/
/**
* @file aws_iot_mqtt_client_subscribe.c
* @brief MQTT client subscribe API definitions
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "aws_iot_shadow_records.h"
#include <string.h>
@@ -104,7 +113,6 @@ IoT_Error_t registerJsonTokenOnDelta(jsonStruct_t *pStruct) {
snprintf(shadowDeltaTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/update/delta", myThingName);
rc = aws_iot_mqtt_subscribe(pMqttClient, shadowDeltaTopic, (uint16_t) strlen(shadowDeltaTopic), QOS0,
shadow_delta_callback, NULL);
DEBUG("delta topic %s", shadowDeltaTopic);
deltaTopicSubscribedFlag = true;
}
@@ -138,30 +146,32 @@ static void topicNameFromThingAndAction(char *pTopic, const char *pThingName, Sh
char actionBuf[10];
char ackTypeBuf[10];
if(action == SHADOW_GET) {
strcpy(actionBuf, "get");
} else if(action == SHADOW_UPDATE) {
strcpy(actionBuf, "update");
} else if(action == SHADOW_DELETE) {
strcpy(actionBuf, "delete");
if(SHADOW_GET == action) {
strncpy(actionBuf, "get", 10);
} else if(SHADOW_UPDATE == action) {
strncpy(actionBuf, "update", 10);
} else if(SHADOW_DELETE == action) {
strncpy(actionBuf, "delete", 10);
}
if(ackType == SHADOW_ACCEPTED) {
strcpy(ackTypeBuf, "accepted");
} else if(ackType == SHADOW_REJECTED) {
strcpy(ackTypeBuf, "rejected");
if(SHADOW_ACCEPTED == ackType) {
strncpy(ackTypeBuf, "accepted", 10);
} else if(SHADOW_REJECTED == ackType) {
strncpy(ackTypeBuf, "rejected", 10);
}
if(ackType == SHADOW_ACTION) {
sprintf(pTopic, "$aws/things/%s/shadow/%s", pThingName, actionBuf);
if(SHADOW_ACTION == ackType) {
snprintf(pTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/%s", pThingName, actionBuf);
} else {
sprintf(pTopic, "$aws/things/%s/shadow/%s/%s", pThingName, actionBuf, ackTypeBuf);
snprintf(pTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/%s/%s", pThingName, actionBuf,
ackTypeBuf);
}
}
static bool isAckForMyThingName(const char *pTopicName) {
if(strstr(pTopicName, myThingName) != NULL &&
((strstr(pTopicName, "get/accepted") != NULL) || (strstr(pTopicName, "delta") != NULL))) {
((strstr(pTopicName, "get/accepted") != NULL) || (strstr(pTopicName, "update/accepted") != NULL) ||
(strstr(pTopicName, "delta") != NULL))) {
return true;
}
return false;
@@ -179,7 +189,7 @@ static void AckStatusCallback(AWS_IoT_Client *pClient, char *topicName, uint16_t
IOT_UNUSED(pData);
if(params->payloadLen > SHADOW_MAX_SIZE_OF_RX_BUFFER) {
WARN("Payload larger than RX Buffer");
IOT_WARN("Payload larger than RX Buffer");
return;
}
@@ -187,7 +197,7 @@ static void AckStatusCallback(AWS_IoT_Client *pClient, char *topicName, uint16_t
shadowRxBuf[params->payloadLen] = '\0'; // jsmn_parse relies on a string
if(!isJsonValidAndParse(shadowRxBuf, pJsonHandler, &tokenCount)) {
WARN("Received JSON is not valid");
IOT_WARN("Received JSON is not valid");
return;
}
@@ -254,7 +264,7 @@ static void unsubscribeFromAcceptedAndRejected(uint8_t index) {
if((indexSubList >= 0)) {
if(!SubscriptionList[indexSubList].isSticky && (SubscriptionList[indexSubList].count == 1)) {
ret_val = aws_iot_mqtt_unsubscribe(pMqttClient, TemporaryTopicNameAccepted,
(uint16_t)strlen(TemporaryTopicNameAccepted));
(uint16_t) strlen(TemporaryTopicNameAccepted));
if(ret_val == SUCCESS) {
SubscriptionList[indexSubList].isFree = true;
}
@@ -267,7 +277,7 @@ static void unsubscribeFromAcceptedAndRejected(uint8_t index) {
if((indexSubList >= 0)) {
if(!SubscriptionList[indexSubList].isSticky && (SubscriptionList[indexSubList].count == 1)) {
ret_val = aws_iot_mqtt_unsubscribe(pMqttClient, TemporaryTopicNameRejected,
(uint16_t)strlen(TemporaryTopicNameRejected));
(uint16_t) strlen(TemporaryTopicNameRejected));
if(ret_val == SUCCESS) {
SubscriptionList[indexSubList].isFree = true;
}
@@ -331,7 +341,7 @@ IoT_Error_t subscribeToShadowActionAcks(const char *pThingName, ShadowActions_t
if(indexAcceptedSubList >= 0 && indexRejectedSubList >= 0) {
topicNameFromThingAndAction(SubscriptionList[indexAcceptedSubList].Topic, pThingName, action, SHADOW_ACCEPTED);
ret_val = aws_iot_mqtt_subscribe(pMqttClient, SubscriptionList[indexAcceptedSubList].Topic,
(uint16_t)strlen(SubscriptionList[indexAcceptedSubList].Topic), QOS0,
(uint16_t) strlen(SubscriptionList[indexAcceptedSubList].Topic), QOS0,
AckStatusCallback, NULL);
if(ret_val == SUCCESS) {
SubscriptionList[indexAcceptedSubList].count = 1;
@@ -339,7 +349,7 @@ IoT_Error_t subscribeToShadowActionAcks(const char *pThingName, ShadowActions_t
topicNameFromThingAndAction(SubscriptionList[indexRejectedSubList].Topic, pThingName, action,
SHADOW_REJECTED);
ret_val = aws_iot_mqtt_subscribe(pMqttClient, SubscriptionList[indexRejectedSubList].Topic,
(uint16_t)strlen(SubscriptionList[indexRejectedSubList].Topic), QOS0,
(uint16_t) strlen(SubscriptionList[indexRejectedSubList].Topic), QOS0,
AckStatusCallback, NULL);
if(ret_val == SUCCESS) {
SubscriptionList[indexRejectedSubList].count = 1;
@@ -364,7 +374,7 @@ IoT_Error_t subscribeToShadowActionAcks(const char *pThingName, ShadowActions_t
}
if(SubscriptionList[indexAcceptedSubList].count == 1) {
aws_iot_mqtt_unsubscribe(pMqttClient, SubscriptionList[indexAcceptedSubList].Topic,
(uint16_t)strlen(SubscriptionList[indexAcceptedSubList].Topic));
(uint16_t) strlen(SubscriptionList[indexAcceptedSubList].Topic));
}
}
@@ -392,28 +402,39 @@ void incrementSubscriptionCnt(const char *pThingName, ShadowActions_t action, bo
IoT_Error_t publishToShadowAction(const char *pThingName, ShadowActions_t action, const char *pJsonDocumentToBeSent) {
IoT_Error_t ret_val = SUCCESS;
char TemporaryTopicName[MAX_SHADOW_TOPIC_LENGTH_BYTES];
IoT_Publish_Message_Params msgParams;
if(NULL == pThingName || NULL == pJsonDocumentToBeSent) {
return NULL_VALUE_ERROR;
}
topicNameFromThingAndAction(TemporaryTopicName, pThingName, action, SHADOW_ACTION);
IoT_Publish_Message_Params msgParams;// = MQTTMessageParamsDefault;
msgParams.qos = QOS0;
msgParams.payloadLen = strlen(pJsonDocumentToBeSent) + 1;
msgParams.payloadLen = strlen(pJsonDocumentToBeSent);
msgParams.payload = (char *) pJsonDocumentToBeSent;
ret_val = aws_iot_mqtt_publish(pMqttClient, TemporaryTopicName, (uint16_t)strlen(TemporaryTopicName), &msgParams);
ret_val = aws_iot_mqtt_publish(pMqttClient, TemporaryTopicName, (uint16_t) strlen(TemporaryTopicName), &msgParams);
return ret_val;
}
bool getNextFreeIndexOfAckWaitList(uint8_t *pIndex) {
uint8_t i;
if(pIndex != NULL) {
for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) {
if(AckWaitList[i].isFree) {
*pIndex = i;
return true;
}
bool rc = false;
if(NULL == pIndex) {
return false;
}
for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) {
if(AckWaitList[i].isFree) {
*pIndex = i;
rc = true;
break;
}
}
return false;
return rc;
}
void addToAckWaitList(uint8_t indexAckWaitList, const char *pThingName, ShadowActions_t action,
@@ -452,6 +473,9 @@ static void shadow_delta_callback(AWS_IoT_Client *pClient, char *topicName,
void *pJsonHandler = NULL;
int32_t DataPosition;
uint32_t dataLength;
uint32_t tempVersionNumber = 0;
FUNC_ENTRY;
IOT_UNUSED(pClient);
IOT_UNUSED(topicName);
@@ -459,7 +483,7 @@ static void shadow_delta_callback(AWS_IoT_Client *pClient, char *topicName,
IOT_UNUSED(pData);
if(params->payloadLen > SHADOW_MAX_SIZE_OF_RX_BUFFER) {
WARN("Payload larger than RX Buffer");
IOT_WARN("Payload larger than RX Buffer");
return;
}
@@ -467,18 +491,17 @@ static void shadow_delta_callback(AWS_IoT_Client *pClient, char *topicName,
shadowRxBuf[params->payloadLen] = '\0'; // jsmn_parse relies on a string
if(!isJsonValidAndParse(shadowRxBuf, pJsonHandler, &tokenCount)) {
WARN("Received JSON is not valid");
IOT_WARN("Received JSON is not valid");
return;
}
if(shadowDiscardOldDeltaFlag) {
uint32_t tempVersionNumber = 0;
if(extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) {
if(tempVersionNumber > shadowJsonVersionNum) {
shadowJsonVersionNum = tempVersionNumber;
DEBUG("New Version number: %d", shadowJsonVersionNum);
} else {
WARN("Old Delta Message received - Ignoring rx: %d local: %d", tempVersionNumber, shadowJsonVersionNum);
IOT_WARN("Old Delta Message received - Ignoring rx: %d local: %d", tempVersionNumber,
shadowJsonVersionNum);
return;
}
}
@@ -486,12 +509,17 @@ static void shadow_delta_callback(AWS_IoT_Client *pClient, char *topicName,
for(i = 0; i < tokenTableIndex; i++) {
if(!tokenTable[i].isFree) {
if(isJsonKeyMatchingAndUpdateValue(shadowRxBuf, pJsonHandler, tokenCount, tokenTable[i].pStruct,
&dataLength, &DataPosition)) {
if(isJsonKeyMatchingAndUpdateValue(shadowRxBuf, pJsonHandler, tokenCount,
(jsonStruct_t *) tokenTable[i].pStruct, &dataLength, &DataPosition)) {
if(tokenTable[i].callback != NULL) {
tokenTable[i].callback(shadowRxBuf + DataPosition, dataLength, tokenTable[i].pStruct);
tokenTable[i].callback(shadowRxBuf + DataPosition, dataLength,
(jsonStruct_t *) tokenTable[i].pStruct);
}
}
}
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -3,4 +3,7 @@ This folder contains tests to verify SDK functionality. These have been tested t
A description for each folder is given below
## integration
This folder contains integration tests that run directly against the server. For further information on how to run these tests check out the [Integration Test README](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/integration/README.md/).
This folder contains integration tests that run directly against the server. For further information on how to run these tests check out the [Integration Test README](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/integration/README.md/).
## unit
This folder contains unit tests that test SDK functionality against a Mock TLS layer. They are built using the CppUTest testing framework. For further information on how to run these tests check out the [Unit Test README](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/unit/README.md/).

View File

@@ -1,92 +0,0 @@
CC = gcc
DEBUG =
#IoT client directory
IOT_CLIENT_DIR = ../..
APP_DIR = $(IOT_CLIENT_DIR)/tests/integration
APP_NAME = integration_tests_mbedtls
MT_APP_NAME = integration_tests_mbedtls_mt
APP_SRC_FILES = $(shell find $(APP_DIR)/src/ -name '*.c')
MT_APP_SRC_FILES = $(shell find $(APP_DIR)/multithreadingTest/ -name '*.c')
APP_INCLUDE_DIRS = -I $(APP_DIR)/include
PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux
#MbedTLS directory
TEMP_MBEDTLS_SRC_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS
TLS_LIB_DIR = $(TEMP_MBEDTLS_SRC_DIR)/library
TLS_INCLUDE_DIR = -I $(TEMP_MBEDTLS_SRC_DIR)/include
EXTERNAL_LIBS += -L$(TLS_LIB_DIR)
LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR)
LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(TLS_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread
# Logging level control
#LOG_FLAGS += -DIOT_DEBUG
#LOG_FLAGS += -DIOT_TRACE
LOG_FLAGS += -DIOT_INFO
LOG_FLAGS += -DIOT_WARN
LOG_FLAGS += -DIOT_ERROR
COMPILER_FLAGS += $(LOG_FLAGS)
#IoT client directory
PLATFORM_COMMON_DIR = $(PLATFORM_DIR)/common
PLATFORM_THREAD_DIR = $(PLATFORM_DIR)/pthread
PLATFORM_NETWORK_DIR = $(PLATFORM_DIR)/mbedtls
IOT_INCLUDE_DIRS = -I $(PLATFORM_COMMON_DIR)
IOT_INCLUDE_DIRS += -I $(PLATFORM_THREAD_DIR)
IOT_INCLUDE_DIRS += -I $(PLATFORM_NETWORK_DIR)
IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include
IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn
IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c')
IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn/ -name '*.c')
IOT_SRC_FILES += $(shell find $(PLATFORM_NETWORK_DIR)/ -name '*.c')
IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c')
IOT_SRC_FILES += $(shell find $(PLATFORM_THREAD_DIR)/ -name '*.c')
#Aggregate all include and src directories
INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS)
INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS)
INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR)
SRC_FILES += $(APP_SRC_FILES)
SRC_FILES += $(IOT_SRC_FILES)
MT_SRC_FILES += $(MT_APP_SRC_FILES)
MT_SRC_FILES += $(IOT_SRC_FILES)
COMPILER_FLAGS += -g
COMPILER_FLAGS += $(LOG_FLAGS)
PRE_MAKE_CMDS += cd $(TEMP_MBEDTLS_SRC_DIR) && make
MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -g3 -o $(APP_DIR)/$(APP_NAME) $(EXTERNAL_LIBS) $(LD_FLAG) $(INCLUDE_ALL_DIRS);
MAKE_MT_CMD = $(CC) $(MT_SRC_FILES) $(COMPILER_FLAGS) -g3 -D_ENABLE_THREAD_SUPPORT_ -o $(APP_DIR)/$(MT_APP_NAME) $(EXTERNAL_LIBS) $(LD_FLAG) $(INCLUDE_ALL_DIRS);
ifeq ($(CODE_SIZE_ENABLE),Y)
POST_MAKE_CMDS += $(CC) -c $(SRC_FILES) $(INCLUDE_ALL_DIRS) -fstack-usage;
POST_MAKE_CMDS += (size --format=Berkeley *.o > $(APP_NAME)_size_info.txt);
POST_MAKE_CMDS += (cat *.su >> $(APP_NAME)_stack_usage.txt);
POST_MAKE_CMDS += (rm *.o);
POST_MAKE_CMDS += (rm *.su);
CLEAN_CMD += (rm -f $(APP_NAME)_size_info.txt);
CLEAN_CMD += (rm -f $(APP_NAME)_stack_usage.txt);
endif
all:
$(PRE_MAKE_CMDS)
$(DEBUG)$(MAKE_CMD)
$(DEBUG)$(MAKE_MT_CMD)
./$(APP_NAME)
./$(MT_APP_NAME)
$(POST_MAKE_CMDS)
clean:
rm -f $(APP_DIR)/$(APP_NAME)
rm -f $(APP_DIR)/$(MT_APP_NAME)
$(CLEAN_CMD)
ALL_TARGETS_CLEAN += test-integration-assert-clean

View File

@@ -45,7 +45,7 @@
#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name
// Auto Reconnect specific config
#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm
#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 8000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect.
#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm
#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect.
#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */

View File

@@ -38,6 +38,6 @@
int aws_iot_mqtt_tests_basic_connectivity();
int aws_iot_mqtt_tests_multiple_clients();
int autoReconnectTests();
int aws_iot_mqtt_tests_auto_reconnect();
#endif /* TESTS_INTEGRATION_COMMON_H_ */

View File

@@ -61,12 +61,12 @@ static void aws_iot_mqtt_tests_message_aggregator(AWS_IoT_Client *pClient, char
if(((tempRow - 1) < MAX_PUB_THREAD_COUNT) && (tempCol < PUBLISH_COUNT)) {
countArray[tempRow - 1][tempCol]++;
} else {
WARN(" \nUnexpected Thread : %d, Message : %d ", tempRow, tempCol);
IOT_WARN(" \nUnexpected Thread : %d, Message : %d ", tempRow, tempCol);
rxUnexpectedNumberCounter++;
}
rc = aws_iot_mqtt_yield(pClient, 10);
if(MQTT_CLIENT_NOT_IDLE_ERROR != rc) {
ERROR("\n Yield succeeded in callback!!! Client state : %d Rc : %d\n",
IOT_ERROR("\n Yield succeeded in callback!!! Client state : %d Rc : %d\n",
aws_iot_mqtt_get_client_state(pClient), rc);
wrongYieldCount++;
}
@@ -87,7 +87,7 @@ static IoT_Error_t aws_iot_mqtt_tests_subscribe_to_test_topic(AWS_IoT_Client *pC
gettimeofday(&start, NULL);
rc = aws_iot_mqtt_subscribe(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), qos,
aws_iot_mqtt_tests_message_aggregator, NULL);
DEBUG(" Sub response : %d\n", rc);
IOT_DEBUG(" Sub response : %d\n", rc);
gettimeofday(&end, NULL);
timersub(&end, &start, pSubscribeTime);
@@ -106,7 +106,7 @@ static void *aws_iot_mqtt_tests_yield_thread_runner(void *ptr) {
} while(MQTT_CLIENT_NOT_IDLE_ERROR == rc);
if(SUCCESS != rc) {
ERROR("\nYield Returned : %d ", rc);
IOT_ERROR("\nYield Returned : %d ", rc);
}
}
}
@@ -133,7 +133,7 @@ static void *aws_iot_mqtt_tests_publish_thread_runner(void *ptr) {
usleep(THREAD_SLEEP_INTERVAL_USEC);
} while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc);
if(SUCCESS != rc) {
WARN("\nFailed attempt 1 Publishing Thread : %d, Msg : %d, cs : %d --> %d\n ", threadId, itr, rc,
IOT_WARN("\nFailed attempt 1 Publishing Thread : %d, Msg : %d, cs : %d --> %d\n ", threadId, itr, rc,
aws_iot_mqtt_get_client_state(pClient));
do {
rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), &params);
@@ -141,7 +141,7 @@ static void *aws_iot_mqtt_tests_publish_thread_runner(void *ptr) {
} while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc);
rePublishCount++;
if(SUCCESS != rc) {
ERROR("\nFailed attempt 2 Publishing Thread : %d, Msg : %d, cs : %d --> %d Second Attempt \n", threadId,
IOT_ERROR("\nFailed attempt 2 Publishing Thread : %d, Msg : %d, cs : %d --> %d Second Attempt \n", threadId,
itr, rc, aws_iot_mqtt_get_client_state(pClient));
}
}
@@ -164,7 +164,7 @@ static void *aws_iot_mqtt_tests_sub_unsub_thread_runner(void *ptr) {
} while(MQTT_CLIENT_NOT_IDLE_ERROR == rc);
if(SUCCESS != rc) {
ERROR("Subscribe Returned : %d ", rc);
IOT_ERROR("Subscribe Returned : %d ", rc);
}
do {
@@ -173,7 +173,7 @@ static void *aws_iot_mqtt_tests_sub_unsub_thread_runner(void *ptr) {
} while(MQTT_CLIENT_NOT_IDLE_ERROR == rc);
if(SUCCESS != rc) {
ERROR("Unsubscribe Returned : %d ", rc);
IOT_ERROR("Unsubscribe Returned : %d ", rc);
}
}
}
@@ -223,7 +223,7 @@ int aws_iot_mqtt_tests_multi_threading_validation() {
srand((unsigned int)time(NULL));
snprintf(clientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID, rand() % 10000);
DEBUG(" Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey);
IOT_DEBUG(" Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey);
initParams.pHostURL = AWS_IOT_MQTT_HOST;
initParams.port = 8883;
initParams.pRootCALocation = root_CA;
@@ -249,7 +249,7 @@ int aws_iot_mqtt_tests_multi_threading_validation() {
rc = aws_iot_mqtt_connect(&client, &connectParams);
if(SUCCESS != rc) {
ERROR("ERROR Connecting %d\n", rc);
IOT_ERROR("ERROR Connecting %d\n", rc);
return -1;
}
@@ -259,7 +259,7 @@ int aws_iot_mqtt_tests_multi_threading_validation() {
if(SUCCESS == rc) {
printf("\n## Connect Success. Time sec: %d, usec: %d\n", connectTime.tv_sec, connectTime.tv_usec);
} else {
ERROR("## Connect Failed. error code %d\n", rc);
IOT_ERROR("## Connect Failed. error code %d\n", rc);
return -1;
}

View File

@@ -31,7 +31,7 @@ bool captureYieldReturnCode = false;
* This function renames the rootCA.crt file to a temporary name to cause connect failure
*/
int aws_iot_mqtt_tests_block_tls_connect() {
char replaceFileName[] = { "rootCATemp.crt" };
char replaceFileName[] = {"rootCATemp.crt"};
char *pFileNamePosition = NULL;
char mvCommand[2 * PATH_MAX + 10];
@@ -56,7 +56,7 @@ void *aws_iot_mqtt_tests_yield_with_rc(void *ptr) {
struct timeval start, end, result;
static int cntr = 0;
AWS_IoT_Client *pClient = (AWS_IoT_Client *)ptr;
AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr;
while(terminate_yield_with_rc_thread == false
&& (NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc)) {
@@ -73,6 +73,7 @@ void *aws_iot_mqtt_tests_yield_with_rc(void *ptr) {
}
unsigned int disconnectedCounter = 0;
void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) {
disconnectedCounter++;
}
@@ -94,7 +95,7 @@ int aws_iot_mqtt_tests_auto_reconnect() {
snprintf(root_CA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME);
snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME);
snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME);
srand((unsigned int)time(NULL));
srand((unsigned int) time(NULL));
snprintf(clientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID, rand() % 10000);
printf(" Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey);
@@ -104,8 +105,8 @@ int aws_iot_mqtt_tests_auto_reconnect() {
initParams.pRootCALocation = root_CA;
initParams.pDeviceCertLocation = clientCRT;
initParams.pDevicePrivateKeyLocation = clientKey;
initParams.mqttCommandTimeout_ms = 5000;
initParams.tlsHandshakeTimeout_ms = 2000;
initParams.mqttCommandTimeout_ms = 20000;
initParams.tlsHandshakeTimeout_ms = 5000;
initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler;
initParams.enableAutoReconnect = false;
aws_iot_mqtt_init(&client, &initParams);
@@ -114,7 +115,7 @@ int aws_iot_mqtt_tests_auto_reconnect() {
connectParams.keepAliveIntervalInSec = 5;
connectParams.isCleanSession = true;
connectParams.MQTTVersion = MQTT_3_1_1;
connectParams.pClientID = (char *)&clientId;
connectParams.pClientID = (char *) &clientId;
connectParams.clientIDLen = strlen(clientId);
connectParams.isWillMsgPresent = 0;
connectParams.pUsername = NULL;
@@ -123,7 +124,7 @@ int aws_iot_mqtt_tests_auto_reconnect() {
connectParams.passwordLen = 0;
rc = aws_iot_mqtt_connect(&client, &connectParams);
if (rc != SUCCESS) {
if(rc != SUCCESS) {
printf("ERROR Connecting %d\n", rc);
return -1;
}
@@ -136,8 +137,8 @@ int aws_iot_mqtt_tests_auto_reconnect() {
printf("1. Test Disconnect Handler\n");
aws_iot_mqtt_tests_block_tls_connect();
iot_tls_disconnect(&(client.networkStack));
sleep(10);
if (disconnectedCounter == 1) {
sleep(connectParams.keepAliveIntervalInSec + 1);
if(disconnectedCounter == 1) {
printf("Success invoking Disconnect Handler\n");
} else {
aws_iot_mqtt_tests_unblock_tls_connect();
@@ -153,7 +154,7 @@ int aws_iot_mqtt_tests_auto_reconnect() {
*/
printf("2. Test Manual Reconnect, Current Client state : %d \n", aws_iot_mqtt_get_client_state(&client));
rc = aws_iot_mqtt_attempt_reconnect(&client);
if (rc != NETWORK_RECONNECTED) {
if(rc != NETWORK_RECONNECTED) {
printf("ERROR reconnecting manually %d\n", rc);
return -4;
}
@@ -165,8 +166,8 @@ int aws_iot_mqtt_tests_auto_reconnect() {
// ensure atleast 1 cycle of yield is executed to get the yield status to SUCCESS
sleep(1);
if (!captureYieldReturnCode) {
if (yieldRC == NETWORK_ATTEMPTING_RECONNECT) {
if(!captureYieldReturnCode) {
if(yieldRC == NETWORK_ATTEMPTING_RECONNECT) {
printf("Success reconnecting manually\n");
} else {
printf("Failure to reconnect manually\n");
@@ -182,7 +183,7 @@ int aws_iot_mqtt_tests_auto_reconnect() {
printf("3. Test Auto_reconnect \n");
rc = aws_iot_mqtt_autoreconnect_set_status(&client, true);
if (rc != SUCCESS) {
if(rc != SUCCESS) {
printf("Error: Failed to enable auto-reconnect %d \n", rc);
}
@@ -196,36 +197,36 @@ int aws_iot_mqtt_tests_auto_reconnect() {
terminate_yield_with_rc_thread = false;
yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_with_rc, &client);
sleep(10);
if (!captureYieldReturnCode) {
if (yieldRC == NETWORK_ATTEMPTING_RECONNECT) {
sleep(connectParams.keepAliveIntervalInSec + 1);
if(!captureYieldReturnCode) {
if(yieldRC == NETWORK_ATTEMPTING_RECONNECT) {
printf("Success attempting reconnect\n");
} else {
printf("Failure to attempt to reconnect\n");
return -6;
}
}
if(disconnectedCounter == 2){
if(disconnectedCounter == 2) {
printf("Success: disconnect handler invoked on enabling auto-reconnect\n");
} else{
} else {
printf("Failure: disconnect handler not invoked on enabling auto-reconnect : %d\n", disconnectedCounter);
return -7;
}
aws_iot_mqtt_tests_unblock_tls_connect();
sleep(10);
sleep(connectParams.keepAliveIntervalInSec + 1);
captureYieldReturnCode = true;
sleep(5);
if (!captureYieldReturnCode) {
if (yieldRC == SUCCESS) {
sleep(connectParams.keepAliveIntervalInSec + 1);
if(!captureYieldReturnCode) {
if(yieldRC == SUCCESS) {
printf("Success attempting reconnect\n");
} else {
printf("Failure to attempt to reconnect\n");
return -6;
}
}
if(true == aws_iot_mqtt_is_client_connected(&client)){
if(true == aws_iot_mqtt_is_client_connected(&client)) {
printf("Success: is Mqtt connected api\n");
} else{
} else {
printf("Failure: is Mqtt Connected api\n");
return -7;
}

View File

@@ -59,12 +59,12 @@ static void aws_iot_mqtt_tests_message_aggregator(AWS_IoT_Client *pClient, char
if(tempCol > 0 && tempCol <= PUBLISH_COUNT) {
countArray[tempCol - 1]++;
} else {
WARN(" \n Thread : %d, Msg : %d ", tempRow, tempCol);
IOT_WARN(" \n Thread : %d, Msg : %d ", tempRow, tempCol);
rxUnexpectedNumberCounter++;
}
rc = aws_iot_mqtt_yield(pClient, 10);
if(MQTT_CLIENT_NOT_IDLE_ERROR != rc) {
ERROR("\n Yield succeeded in callback!!! Client state : %d Rc : %d\n",
IOT_ERROR("\n Yield succeeded in callback!!! Client state : %d Rc : %d\n",
aws_iot_mqtt_get_client_state(pClient), rc);
wrongYieldCount++;
}
@@ -84,7 +84,7 @@ static IoT_Error_t aws_iot_mqtt_tests_subscribe_to_test_topic(AWS_IoT_Client *pC
gettimeofday(&start, NULL);
rc = aws_iot_mqtt_subscribe(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), qos,
aws_iot_mqtt_tests_message_aggregator, NULL);
DEBUG("Sub response : %d\n", rc);
IOT_DEBUG("Sub response : %d\n", rc);
gettimeofday(&end, NULL);
timersub(&end, &start, pSubscribeTime);
@@ -102,7 +102,7 @@ static void *aws_iot_mqtt_tests_yield_thread_runner(void *ptr) {
} while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); // Client is busy, wait to get lock
if(SUCCESS != rc) {
DEBUG("\nYield Returned : %d ", rc);
IOT_DEBUG("\nYield Returned : %d ", rc);
}
}
}
@@ -129,14 +129,14 @@ static void *aws_iot_mqtt_tests_publish_thread_runner(void *ptr) {
usleep(THREAD_SLEEP_INTERVAL_USEC);
} while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc);
if(rc != SUCCESS) {
WARN("Error Publishing #%d --> %d\n ", i, rc);
IOT_WARN("Error Publishing #%d --> %d\n ", i, rc);
do {
rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), &params);
usleep(THREAD_SLEEP_INTERVAL_USEC);
} while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc);
rePublishCount++;
if(rc != SUCCESS) {
ERROR("Error Publishing #%d --> %d Second Attempt \n", i, rc);
IOT_ERROR("Error Publishing #%d --> %d Second Attempt \n", i, rc);
}
}
}
@@ -160,6 +160,7 @@ int aws_iot_mqtt_tests_basic_connectivity() {
IoT_Error_t rc = SUCCESS;
int i, rxMsgCount = 0, j = 0;
struct timeval connectTime, subscribeTopic;
struct timeval start, end;
unsigned int connectCounter = 0;
int test_result = 0;
ThreadData threadData;
@@ -176,7 +177,7 @@ int aws_iot_mqtt_tests_basic_connectivity() {
countArray[i] = 0;
}
DEBUG("\nConnecting Client ");
IOT_DEBUG("\nConnecting Client ");
do {
getcwd(CurrentWD, sizeof(CurrentWD));
snprintf(root_CA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME);
@@ -187,7 +188,7 @@ int aws_iot_mqtt_tests_basic_connectivity() {
printf("\n\nClient ID : %s \n", clientId);
DEBUG("Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey);
IOT_DEBUG("Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey);
initParams.pHostURL = AWS_IOT_MQTT_HOST;
initParams.port = 8883;
initParams.pRootCALocation = root_CA;
@@ -210,19 +211,18 @@ int aws_iot_mqtt_tests_basic_connectivity() {
connectParams.pPassword = NULL;
connectParams.passwordLen = 0;
gettimeofday(&connectTime, NULL);
rc = aws_iot_mqtt_connect(&client, &connectParams);
if(rc != SUCCESS) {
ERROR("\nERROR Connecting %d\n", rc);
return -1;
}
gettimeofday(&end, NULL);
timersub(&end, &start, &connectTime);
connectCounter++;
} while(rc != SUCCESS && connectCounter < CONNECT_MAX_ATTEMPT_COUNT);
if(rc == SUCCESS) {
DEBUG("## Connect Success. Time sec: %d, usec: %d\n", connectTime.tv_sec, connectTime.tv_usec);
if(SUCCESS == rc) {
IOT_DEBUG("## Connect Success. Time sec: %d, usec: %d\n", connectTime.tv_sec, connectTime.tv_usec);
} else {
ERROR("## Connect Failed. error code %d\n", rc);
IOT_ERROR("## Connect Failed. error code %d\n", rc);
return -1;
}
@@ -254,21 +254,21 @@ int aws_iot_mqtt_tests_basic_connectivity() {
}
}
DEBUG("\n\nResult : \n");
IOT_DEBUG("\n\nResult : \n");
percentOfRxMsg = (float) rxMsgCount * 100 / PUBLISH_COUNT;
if(percentOfRxMsg >= RX_RECEIVE_PERCENTAGE && rxMsgBufferTooBigCounter == 0 && rxUnexpectedNumberCounter == 0 &&
wrongYieldCount == 0) {
DEBUG("\n\nSuccess: %f \%\n", percentOfRxMsg);
DEBUG("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT, rxMsgCount);
DEBUG("QoS 1 re publish count %d\n", rePublishCount);
DEBUG("Connection Attempts %d\n", connectCounter);
DEBUG("Yield count without error during callback %d\n", wrongYieldCount);
IOT_DEBUG("\n\nSuccess: %f \%\n", percentOfRxMsg);
IOT_DEBUG("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT, rxMsgCount);
IOT_DEBUG("QoS 1 re publish count %d\n", rePublishCount);
IOT_DEBUG("Connection Attempts %d\n", connectCounter);
IOT_DEBUG("Yield count without error during callback %d\n", wrongYieldCount);
test_result = 0;
} else {
ERROR("\n\nFailure: %f\n", percentOfRxMsg);
ERROR("\"Received message was too big than anything sent\" count: %d\n", rxMsgBufferTooBigCounter);
ERROR("\"The number received is out of the range\" count: %d\n", rxUnexpectedNumberCounter);
ERROR("Yield count without error during callback %d\n", wrongYieldCount);
IOT_ERROR("\n\nFailure: %f\n", percentOfRxMsg);
IOT_ERROR("\"Received message was too big than anything sent\" count: %d\n", rxMsgBufferTooBigCounter);
IOT_ERROR("\"The number received is out of the range\" count: %d\n", rxUnexpectedNumberCounter);
IOT_ERROR("Yield count without error during callback %d\n", wrongYieldCount);
test_result = -2;
}
aws_iot_mqtt_disconnect(&client);

View File

@@ -40,6 +40,7 @@ static void aws_iot_mqtt_tests_message_aggregator(AWS_IoT_Client *pClient, char
if(10 >= params->payloadLen) {
snprintf(tempBuf, params->payloadLen, params->payload);
printf("\nMsg received : %s", tempBuf);
tempInt = atoi(tempBuf);
if(0 < tempInt && PUBLISH_COUNT >= tempInt) {
countArray[tempInt - 1]++;
@@ -115,13 +116,15 @@ static IoT_Error_t aws_iot_mqtt_tests_subscribe_to_test_topic(AWS_IoT_Client *pC
static void *aws_iot_mqtt_tests_yield_thread_runner(void *ptr) {
IoT_Error_t rc = SUCCESS;
static int cntr = 0;
AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr;
while(SUCCESS == rc && false == terminate_yield_thread) {
usleep(500000);
rc = aws_iot_mqtt_yield(pClient, 100);
do {
usleep(THREAD_SLEEP_INTERVAL_USEC);
rc = aws_iot_mqtt_yield(pClient, 100);
} while(MQTT_CLIENT_NOT_IDLE_ERROR == rc);
if(SUCCESS != rc) {
printf("\nYield Returned : %d ", rc);
IOT_ERROR("\nYield Returned : %d ", rc);
}
}
}

12
tests/unit/README.md Normal file
View File

@@ -0,0 +1,12 @@
## Unit Tests
This folder contains unit tests to verify Embedded C SDK functionality. These have been tested to work with Linux using CppUTest as the testing framework.
CppUTest is not provided along with this code. It needs to be separately downloaded. These tests have been verified to work with CppUTest v3.6, which can be found [here](https://github.com/cpputest/cpputest/tree/v3.6).
Each test contains a comment describing what is being tested. The Tests can be run using the Makefile provided in the root folder for the SDK. There are a total of 187 tests.
To run these tests, follow the below steps:
* Copy the code for CppUTest v3.6 from github to external_libs/CppUTest
* Navigate to SDK Root folder
* run `make run-unit-tests`
This will run all unit tests and generate coverage report in the build_output folder. The report can be viewed by opening <SDK_Root>/build_output/generated-coverage/index.html in a browser.

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_config.h
* @brief IoT Client Unit Testing - IoT Config
*/
#ifndef IOT_TESTS_UNIT_CONFIG_H_
#define IOT_TESTS_UNIT_CONFIG_H_
// Get from console
// =================================================
#define AWS_IOT_MQTT_HOST "localhost"
#define AWS_IOT_MQTT_PORT 8883
#define AWS_IOT_MQTT_CLIENT_ID "C-SDK_UnitTestClient"
#define AWS_IOT_MY_THING_NAME "C-SDK_UnitTestThing"
#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt"
#define AWS_IOT_CERTIFICATE_FILENAME "cert.crt"
#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem"
// =================================================
// MQTT PubSub
#define AWS_IOT_MQTT_TX_BUF_LEN 512
#define AWS_IOT_MQTT_RX_BUF_LEN 512
#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5
// Thing Shadow specific configs
#define SHADOW_MAX_SIZE_OF_RX_BUFFER 512
#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 /** {"clientToken": ">>uniqueClientID<<+sequenceNumber"}*/
#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 /** {"clientToken": ">>uniqueClientID+sequenceNumber<<"}*/
#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 /** >>{"clientToken": "uniqueClientID+sequenceNumber"}<<*/
#define MAX_SIZE_OF_THINGNAME 30
#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10
#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10
#define MAX_JSON_TOKEN_EXPECTED 120
#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60
#define MAX_SIZE_OF_THING_NAME 20
#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME
// Auto Reconnect specific config
#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000
#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000
#endif /* IOT_TESTS_UNIT_CONFIG_H_ */

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_helper_functions.h
* @brief IoT Client Unit Testing - Helper Functions
*/
#ifndef IOT_TESTS_UNIT_HELPER_FUNCTIONS_H_
#define IOT_TESTS_UNIT_HELPER_FUNCTIONS_H_
#include <string.h>
#include "aws_iot_mqtt_client_interface.h"
typedef struct {
unsigned char PacketType;
unsigned int RemainingLength;
unsigned int ProtocolLength;
unsigned char ProtocolName[4];
unsigned int ProtocolLevel;
unsigned char ConnectFlag;
unsigned int KeepAlive;
} ConnectBufferProofread;
void ResetInvalidParameters(void);
void InitMQTTParamsSetup(IoT_Client_Init_Params *params, char *pHost, uint16_t port, bool enableAutoReconnect,
iot_disconnect_handler disconnectHandler);
void ConnectMQTTParamsSetup(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen);
void ConnectMQTTParamsSetup_Detailed(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen,
QoS qos, bool isCleanSession, bool isWillMsgPresent, char *pWillTopicName,
uint16_t willTopicNameLen, char *pWillMessage, uint16_t willMsgLen,
char *pUsername, uint16_t userNameLen, char *pPassword,
uint16_t passwordLen);
void printBuffer(unsigned char *buffer, size_t len);
void setTLSRxBufferForConnack(IoT_Client_Connect_Params *params, unsigned char sessionPresent,
unsigned char connackResponseCode);
void setTLSRxBufferForPuback(void);
void setTLSRxBufferForSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params);
void setTLSRxBufferForDoubleSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params);
void setTLSRxBufferForSubFail(void);
void setTLSRxBufferWithMsgOnSubscribedTopic(char *topicName, size_t topicNameLen, QoS qos,
IoT_Publish_Message_Params params, char *pMsg);
void setTLSRxBufferForUnsuback(void);
void setTLSRxBufferForPingresp(void);
void setTLSRxBufferForConnackAndSuback(IoT_Client_Connect_Params *conParams, unsigned char sessionPresent,
char *topicName, size_t topicNameLen, QoS qos);
unsigned char isLastTLSTxMessagePuback(void);
unsigned char isLastTLSTxMessagePingreq(void);
unsigned char isLastTLSTxMessageDisconnect(void);
void setTLSRxBufferDelay(int seconds, int microseconds);
void ResetTLSBuffer(void);
unsigned char generateMultipleSubTopics(char *des, int boundary);
void encodeRemainingLength(unsigned char *buf, size_t *st, size_t length);
unsigned char *connectTxBufferHeaderParser(ConnectBufferProofread *params, unsigned char *buf);
bool isConnectTxBufFlagCorrect(IoT_Client_Connect_Params *settings, ConnectBufferProofread *readRes);
bool isConnectTxBufPayloadCorrect(IoT_Client_Connect_Params *settings, unsigned char *payloadBuf);
void printPrfrdParams(ConnectBufferProofread *params);
#endif /* IOT_TESTS_UNIT_HELPER_FUNCTIONS_H_ */

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_shadow_helper.h
* @brief IoT Client Unit Testing - Shadow Helper functions
*/
#ifndef IOT_TESTS_UNIT_SHADOW_HELPER_FUNCTIONS_H_
#define IOT_TESTS_UNIT_SHADOW_HELPER_FUNCTIONS_H_
#define AWS_THINGS_TOPIC "$aws/things/"
#define SHADOW_TOPIC "/shadow/"
#define ACCEPTED_TOPIC "/accepted"
#define REJECTED_TOPIC "/rejected"
#define UPDATE_TOPIC "update"
#define GET_TOPIC "get"
#define DELETE_TOPIC "delete"
#define GET_ACCEPTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC GET_TOPIC ACCEPTED_TOPIC
#define GET_REJECTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC GET_TOPIC REJECTED_TOPIC
#define GET_PUB_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC GET_TOPIC
#define DELETE_ACCEPTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC DELETE_TOPIC ACCEPTED_TOPIC
#define DELETE_REJECTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC DELETE_TOPIC REJECTED_TOPIC
#define UPDATE_ACCEPTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC UPDATE_TOPIC ACCEPTED_TOPIC
#define UPDATE_REJECTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC UPDATE_TOPIC REJECTED_TOPIC
#endif /* IOT_TESTS_UNIT_SHADOW_HELPER_FUNCTIONS_H_ */

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_common_tests.cpp
* @brief IoT Client Unit Testing - Common Tests
*/
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness_c.h>
TEST_GROUP_C(CommonTests){
TEST_GROUP_C_SETUP_WRAPPER(CommonTests)
TEST_GROUP_C_TEARDOWN_WRAPPER(CommonTests)
};
TEST_GROUP_C_WRAPPER(CommonTests, NullClientGetState)
TEST_GROUP_C_WRAPPER(CommonTests, NullClientSetAutoreconnect)
TEST_GROUP_C_WRAPPER(CommonTests, UnexpectedAckFiltering)
TEST_GROUP_C_WRAPPER(CommonTests, BigMQTTRxMessageIgnore)
TEST_GROUP_C_WRAPPER(CommonTests, BigMQTTRxMessageReadNextMessage)

View File

@@ -0,0 +1,186 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_common_tests_helper.h
* @brief IoT Client Unit Testing - Common Tests Helper
*/
#include <stdio.h>
#include <string.h>
#include <CppUTest/TestHarness_c.h>
#include "aws_iot_mqtt_client_interface.h"
#include "aws_iot_log.h"
#include "aws_iot_tests_unit_helper_functions.h"
static IoT_Client_Init_Params initParams;
static IoT_Client_Connect_Params connectParams;
static IoT_Publish_Message_Params testPubMsgParams;
static AWS_IoT_Client iotClient;
static char subTopic[10] = "sdk/Test";
static uint16_t subTopicLen = 8;
char cPayload[100];
char cbBuffer[AWS_IOT_MQTT_TX_BUF_LEN + 2];
static void iot_tests_unit_common_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, IoT_Publish_Message_Params *params,
void *pData) {
char *tmp = params->payload;
unsigned int i;
IOT_UNUSED(pClient);
IOT_UNUSED(topicName);
IOT_UNUSED(topicNameLen);
IOT_UNUSED(pData);
for(i = 0; i < params->payloadLen; i++) {
cbBuffer[i] = tmp[i];
}
}
TEST_GROUP_C_SETUP(CommonTests) {
ResetTLSBuffer();
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
initParams.mqttCommandTimeout_ms = 2000;
IoT_Error_t rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("\n\nMQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc);
testPubMsgParams.qos = QOS1;
testPubMsgParams.isRetained = 0;
snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0);
testPubMsgParams.payload = (void *) cPayload;
testPubMsgParams.payloadLen = strlen(cPayload);
ResetTLSBuffer();
}
TEST_GROUP_C_TEARDOWN(CommonTests) {
/* Clean up. Not checking return code here because this is common to all tests.
* A test might have already caused a disconnect by this point.
*/
IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient);
IOT_UNUSED(rc);
}
TEST_C(CommonTests, NullClientGetState) {
ClientState cs = aws_iot_mqtt_get_client_state(NULL);
CHECK_EQUAL_C_INT(CLIENT_STATE_INVALID, cs);
}
TEST_C(CommonTests, NullClientSetAutoreconnect) {
IoT_Error_t rc = aws_iot_mqtt_autoreconnect_set_status(NULL, true);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
// Unexpected Ack section
TEST_C(CommonTests, UnexpectedAckFiltering) {
IoT_Error_t rc = FAILURE;
IOT_DEBUG("\n-->Running CommonTests - Unexpected Ack Filtering\n");
// Assume we are connected and have not done anything yet
// Connack
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
// Puback
setTLSRxBufferForPuback();
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
// Suback: OoS1
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
// Suback: QoS0
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
// Unsuback
setTLSRxBufferForUnsuback();
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
}
TEST_C(CommonTests, BigMQTTRxMessageIgnore) {
uint32_t i = 0;
IoT_Error_t rc = FAILURE;
char expectedCallbackString[AWS_IOT_MQTT_TX_BUF_LEN + 2];
IOT_DEBUG("\n-->Running CommonTests - Ignore Large Incoming Message \n");
setTLSRxBufferForSuback("limitTest/topic1", 16, QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "limitTest/topic1", 16, QOS0, iot_tests_unit_common_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
for(i = 0; i < AWS_IOT_MQTT_TX_BUF_LEN; i++) {
expectedCallbackString[i] = 'X';
}
expectedCallbackString[i + 1] = '\0';
setTLSRxBufferWithMsgOnSubscribedTopic("limitTest/topic1", 16, QOS0, testPubMsgParams, expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(MQTT_RX_BUFFER_TOO_SHORT_ERROR, rc);
}
/**
*
* On receiving a big message into the TLS buffer the MQTT client should flush it out, otherwise it can cause undefined behavior.
*/
TEST_C(CommonTests, BigMQTTRxMessageReadNextMessage) {
uint32_t i = 0;
IoT_Error_t rc = FAILURE;
char expectedCallbackString[AWS_IOT_MQTT_TX_BUF_LEN + 2];
IOT_DEBUG("\n-->Running CommonTests - Clear Buffer when large message received and continue reading \n");
setTLSRxBufferForSuback("limitTest/topic1", 16, QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "limitTest/topic1", 16, QOS0, iot_tests_unit_common_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
for(i = 0; i < AWS_IOT_MQTT_TX_BUF_LEN; i++) {
expectedCallbackString[i] = 'X';
}
expectedCallbackString[i + 1] = '\0';
setTLSRxBufferWithMsgOnSubscribedTopic("limitTest/topic1", 16, QOS0, testPubMsgParams, expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(MQTT_RX_BUFFER_TOO_SHORT_ERROR, rc);
ResetTLSBuffer();
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
expectedCallbackString[3] = '\0';
setTLSRxBufferWithMsgOnSubscribedTopic("limitTest/topic1", 16, QOS1, testPubMsgParams, expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(rc, SUCCESS);
CHECK_EQUAL_C_STRING("XXX", cbBuffer);
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_connect.cpp
* @brief IoT Client Unit Testing - Connect API Tests
*/
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness_c.h>
TEST_GROUP_C(ConnectTests){
TEST_GROUP_C_SETUP_WRAPPER(ConnectTests)
TEST_GROUP_C_TEARDOWN_WRAPPER(ConnectTests)
};
/* B:1 - Init with Null/empty client instance */
TEST_GROUP_C_WRAPPER(ConnectTests, NullClientInit)
/* B:2 - Connect with Null/empty client instance */
TEST_GROUP_C_WRAPPER(ConnectTests, NullClientConnect)
/* B:3 - Connect with Null/Empty endpoint */
TEST_GROUP_C_WRAPPER(ConnectTests, NullHost)
/* B:4 - Connect with Null/Empty port */
TEST_GROUP_C_WRAPPER(ConnectTests, NullPort)
/* B:5 - Connect with Null/Empty root CA path */
TEST_GROUP_C_WRAPPER(ConnectTests, NullRootCAPath)
/* B:6 - Connect with Null/Empty Client certificate path */
TEST_GROUP_C_WRAPPER(ConnectTests, NullClientCertificate)
/* B:7 - Connect with Null/Empty private key Path */
TEST_GROUP_C_WRAPPER(ConnectTests, NullPrivateKeyPath)
/* B:8 - Connect with Null/Empty client ID */
TEST_GROUP_C_WRAPPER(ConnectTests, NullClientID)
/* B:9 - Connect with invalid Endpoint */
TEST_GROUP_C_WRAPPER(ConnectTests, InvalidEndpoint)
/* B:10 - Connect with invalid correct endpoint but invalid port */
TEST_GROUP_C_WRAPPER(ConnectTests, InvalidPort)
/* B:11 - Connect with invalid Root CA path */
TEST_GROUP_C_WRAPPER(ConnectTests, InvalidRootCAPath)
/* B:12 - Connect with invalid Client certificate path */
TEST_GROUP_C_WRAPPER(ConnectTests, InvalidClientCertPath)
/* B:13 - Connect with invalid private key path */
TEST_GROUP_C_WRAPPER(ConnectTests, InvalidPrivateKeyPath)
/* B:14 - Connect, no response timeout */
TEST_GROUP_C_WRAPPER(ConnectTests, NoResponseTimeout)
/* B:15 - Connect, connack malformed, too large */
TEST_GROUP_C_WRAPPER(ConnectTests, ConnackTooLarge)
/* B:16 - Connect, connack malformed, fixed header corrupted */
TEST_GROUP_C_WRAPPER(ConnectTests, FixedHeaderCorrupted)
/* B:17 - Connect, connack malformed, invalid remaining length */
TEST_GROUP_C_WRAPPER(ConnectTests, InvalidRemainingLength)
/* B:18 - Connect, connack returned error, unacceptable protocol version */
TEST_GROUP_C_WRAPPER(ConnectTests, UnacceptableProtocolVersion)
/* B:19 - Connect, connack returned error, identifier rejected */
TEST_GROUP_C_WRAPPER(ConnectTests, IndentifierRejected)
/* B:20 - Connect, connack returned error, Server unavailable */
TEST_GROUP_C_WRAPPER(ConnectTests, ServerUnavailable)
/* B:21 - Connect, connack returned error, bad user name or password */
TEST_GROUP_C_WRAPPER(ConnectTests, BadUserNameOrPassword)
/* B:22 - Connect, connack returned error, not authorized */
TEST_GROUP_C_WRAPPER(ConnectTests, NotAuthorized)
/* B:23 - Connect, connack return after half command timeout delay, success */
TEST_GROUP_C_WRAPPER(ConnectTests, SuccessAfterDelayedConnack)
/* B:24 - Connect, connack returned success */
TEST_GROUP_C_WRAPPER(ConnectTests, ConnectSuccess)
/* B:25 - Connect, flag settings and parameters are recorded in buffer */
TEST_GROUP_C_WRAPPER(ConnectTests, FlagSettingsAndParamsAreRecordedIntoBuf)
/* B:26 - Connect attempt, Disconnect, Manually reconnect */
TEST_GROUP_C_WRAPPER(ConnectTests, ConnectDisconnectConnect)
/* B:27 - Connect attempt, Clean session, Subscribe */
TEST_GROUP_C_WRAPPER(ConnectTests, cleanSessionInitSubscribers)
/* B:28 - Connect attempt, power cycle with clean session false */
TEST_GROUP_C_WRAPPER(ConnectTests, PowerCycleWithCleanSessionFalse)

View File

@@ -0,0 +1,720 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_connect_helper.c
* @brief IoT Client Unit Testing - Connect API Tests Helper
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <CppUTest/TestHarness_c.h>
#include <aws_iot_mqtt_client.h>
#include "aws_iot_tests_unit_mock_tls_params.h"
#include "aws_iot_tests_unit_helper_functions.h"
#include "aws_iot_log.h"
static bool unitTestIsMqttConnected = false;
static IoT_Client_Init_Params initParams;
static IoT_Client_Connect_Params connectParams;
static AWS_IoT_Client iotClient;
static IoT_Publish_Message_Params testPubMsgParams;
static ConnectBufferProofread prfrdParams;
static char subTopic1[12] = "sdk/Topic1";
static char subTopic2[12] = "sdk/Topic2";
#define NO_MSG_XXXX "XXXX"
static char CallbackMsgStringclean[100] = NO_MSG_XXXX;
static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
char *tmp = params->payload;
unsigned int i;
if(NULL == pClient || NULL == topicName || 0 == topicNameLen) {
return;
}
IOT_UNUSED(pData);
for(i = 0; i < (params->payloadLen); i++) {
CallbackMsgStringclean[i] = tmp[i];
}
}
TEST_GROUP_C_SETUP(ConnectTests) {
IoT_Error_t rc = SUCCESS;
unitTestIsMqttConnected = false;
rc = aws_iot_mqtt_disconnect(&iotClient);
ResetTLSBuffer();
ResetInvalidParameters();
}
TEST_GROUP_C_TEARDOWN(ConnectTests) {
/* Clean up. Not checking return code here because this is common to all tests.
* A test might have already caused a disconnect by this point.
*/
IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient);
IOT_UNUSED(rc);
}
/* B:1 - Init with Null/empty client instance */
TEST_C(ConnectTests, NullClientInit) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:1 - Init with Null/empty client instance \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(NULL, &initParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
IOT_DEBUG("-->Success - B:1 - Init with Null/empty client instance \n");
}
/* B:2 - Connect with Null/empty client instance */
TEST_C(ConnectTests, NullClientConnect) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:2 - Connect with Null/empty client instance \n");
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(NULL, &connectParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
IOT_DEBUG("-->Success - B:2 - Connect with Null/empty client instance \n");
}
/* B:3 - Connect with Null/Empty endpoint */
TEST_C(ConnectTests, NullHost) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:3 - Connect with Null/Empty endpoint \n");
InitMQTTParamsSetup(&initParams, NULL, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_C(SUCCESS != rc);
IOT_DEBUG("-->Success - B:3 - Connect with Null/Empty endpoint \n");
}
/* B:4 - Connect with Null/Empty port */
TEST_C(ConnectTests, NullPort) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:4 - Connect with Null/Empty port \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, 0, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_C(SUCCESS != rc);
IOT_DEBUG("-->Success - B:4 - Connect with Null/Empty port \n");
}
/* B:5 - Connect with Null/Empty root CA path */
TEST_C(ConnectTests, NullRootCAPath) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:6 - Connect with Null/Empty root CA path \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
initParams.pRootCALocation = NULL;
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
IOT_DEBUG("-->Success - B:6 - Connect with Null/Empty root CA path \n");
}
/* B:6 - Connect with Null/Empty Client certificate path */
TEST_C(ConnectTests, NullClientCertificate) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:7 - Connect with Null/Empty Client certificate path \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
initParams.pDeviceCertLocation = NULL;
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
IOT_DEBUG("-->Success - B:7 - Connect with Null/Empty Client certificate path \n");
}
/* B:7 - Connect with Null/Empty private key Path */
TEST_C(ConnectTests, NullPrivateKeyPath) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:8 - Connect with Null/Empty private key Path \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
initParams.pDevicePrivateKeyLocation = NULL;
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
IOT_DEBUG("-->Success - B:8 - Connect with Null/Empty private key Path \n");
}
/* B:8 - Connect with Null/Empty client ID */
TEST_C(ConnectTests, NullClientID) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:8 - Connect with Null/Empty client ID \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferForConnack(&connectParams, 0, 0);
/* If no client id is passed but a length was passed, return error */
ConnectMQTTParamsSetup(&connectParams, NULL, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
/* If client id is passed but 0 length was passed, return error */
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
/* If client id is NULL and length is 0 then request succeeds */
ConnectMQTTParamsSetup(&connectParams, NULL, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("-->Success - B:8 - Connect with Null/Empty client ID \n");
}
/* B:9 - Connect with invalid Endpoint */
TEST_C(ConnectTests, InvalidEndpoint) {
IoT_Error_t rc = SUCCESS;
char invalidEndPoint[20];
snprintf(invalidEndPoint, 20, "invalid");
IOT_DEBUG("-->Running Connect Tests - B:9 - Connect with invalid Endpoint \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
invalidEndpointFilter = invalidEndPoint;
initParams.pHostURL = invalidEndpointFilter;
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_C(SUCCESS != rc);
IOT_DEBUG("-->Success - B:9 - Connect with invalid Endpoint \n");
}
/* B:10 - Connect with invalid correct endpoint but invalid port */
TEST_C(ConnectTests, InvalidPort) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:10 - Connect with invalid correct endpoint but invalid port \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
invalidPortFilter = 1234;
initParams.port = invalidPortFilter;
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_C(SUCCESS != rc);
IOT_DEBUG("-->Success - B:10 - Connect with invalid correct endpoint but invalid port \n");
}
/* B:11 - Connect with invalid Root CA path */
TEST_C(ConnectTests, InvalidRootCAPath) {
IoT_Error_t rc = SUCCESS;
char invalidRootCAPath[20];
snprintf(invalidRootCAPath, 20, "invalid");
IOT_DEBUG("-->Running Connect Tests - B:11 - Connect with invalid Root CA path \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
invalidRootCAPathFilter = invalidRootCAPath;
initParams.pRootCALocation = invalidRootCAPathFilter;
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_C(SUCCESS != rc);
IOT_DEBUG("-->Success - B:11 - Connect with invalid Root CA path \n");
}
/* B:12 - Connect with invalid Client certificate path */
TEST_C(ConnectTests, InvalidClientCertPath) {
IoT_Error_t rc = SUCCESS;
char invalidCertPath[20];
snprintf(invalidCertPath, 20, "invalid");
IOT_DEBUG("-->Running Connect Tests - B:12 - Connect with invalid Client certificate path \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
invalidCertPathFilter = invalidCertPath;
initParams.pDeviceCertLocation = invalidCertPathFilter;
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_C(SUCCESS != rc);
IOT_DEBUG("-->Success - B:12 - Connect with invalid Client certificate path \n");
}
/* B:13 - Connect with invalid private key path */
TEST_C(ConnectTests, InvalidPrivateKeyPath) {
IoT_Error_t rc = SUCCESS;
char invalidPrivKeyPath[20];
snprintf(invalidPrivKeyPath, 20, "invalid");
IOT_DEBUG("-->Running Connect Tests - B:13 - Connect with invalid private key path \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
invalidPrivKeyPathFilter = invalidPrivKeyPath;
initParams.pDevicePrivateKeyLocation = invalidPrivKeyPathFilter;
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_C(SUCCESS != rc);
IOT_DEBUG("-->Success - B:13 - Connect with invalid private key path \n");
}
/* B:14 - Connect, no response timeout */
TEST_C(ConnectTests, NoResponseTimeout) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:14 - Connect, no response timeout \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc);
IOT_DEBUG("-->Success - B:14 - Connect, no response timeout \n");
}
/* B:15 - Connect, connack malformed, too large */
TEST_C(ConnectTests, ConnackTooLarge) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:15 - Connect, connack malformed, too large \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
RxBuffer.pBuffer[1] = (char) (0x15); /* Set remaining length to a larger than expected value */
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_C(SUCCESS != rc);
IOT_DEBUG("-->Success - B:15 - Connect, connack malformed, too large \n");
}
/* B:16 - Connect, connack malformed, fixed header corrupted */
TEST_C(ConnectTests, FixedHeaderCorrupted) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:16 - Connect, connack malformed, fixed header corrupted \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
RxBuffer.pBuffer[0] = (char) (0x00);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_C(SUCCESS != rc);
IOT_DEBUG("-->Success - B:16 - Connect, connack malformed, fixed header corrupted \n");
}
/* B:17 - Connect, connack malformed, invalid remaining length */
TEST_C(ConnectTests, InvalidRemainingLength) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:17 - Connect, connack malformed, invalid remaining length \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
RxBuffer.pBuffer[1] = (char) (0x00);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(MQTT_DECODE_REMAINING_LENGTH_ERROR, rc);
IOT_DEBUG("-->Success - B:17 - Connect, connack malformed, invalid remaining length \n");
}
/* B:18 - Connect, connack returned error, unacceptable protocol version */
TEST_C(ConnectTests, UnacceptableProtocolVersion) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:18 - Connect, connack returned error, unacceptable protocol version \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
connectParams.MQTTVersion = 7;
setTLSRxBufferForConnack(&connectParams, 0, 1);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR, rc);
IOT_DEBUG("-->Success - B:18 - Connect, connack returned error, unacceptable protocol version \n");
}
/* B:19 - Connect, connack returned error, identifier rejected */
TEST_C(ConnectTests, IndentifierRejected) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:19 - Connect, connack returned error, identifier rejected \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 2);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR, rc);
IOT_DEBUG("-->Success - B:19 - Connect, connack returned error, identifier rejected \n");
}
/* B:20 - Connect, connack returned error, Server unavailable */
TEST_C(ConnectTests, ServerUnavailable) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:20 - Connect, connack returned error, Server unavailable \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 3);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR, rc);
IOT_DEBUG("-->Success - B:20 - Connect, connack returned error, Server unavailable \n");
}
/* B:21 - Connect, connack returned error, bad user name or password */
TEST_C(ConnectTests, BadUserNameOrPassword) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:21 - Connect, connack returned error, bad user name or password \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 4);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(MQTT_CONNACK_BAD_USERDATA_ERROR, rc);
IOT_DEBUG("-->Success - B:21 - Connect, connack returned error, bad user name or password \n");
}
/* B:22 - Connect, connack returned error, not authorized */
TEST_C(ConnectTests, NotAuthorized) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("\n-->Running Connect Tests - B:22 - Connect, connack returned error, not authorized \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 5);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(MQTT_CONNACK_NOT_AUTHORIZED_ERROR, rc);
IOT_DEBUG("\n-->Success - B:22 - Connect, connack returned error, not authorized \n");
}
/* B:23 - Connect, connack return after half command timeout delay, success */
TEST_C(ConnectTests, SuccessAfterDelayedConnack) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:23 - Connect, connack return after half command timeout delay, success \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
setTLSRxBufferDelay(0, (int) initParams.mqttCommandTimeout_ms/2);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("-->Success - B:23 - Connect, connack return after half command timeout delay, success \n");
}
/* B:24 - Connect, connack returned success */
TEST_C(ConnectTests, ConnectSuccess) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:24 - Connect, connack returned success \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("-->Success - B:24 - Connect, connack returned success \n");
}
/* B:25 - Connect, flag settings and parameters are recorded in buffer */
TEST_C(ConnectTests, FlagSettingsAndParamsAreRecordedIntoBuf) {
IoT_Error_t rc = SUCCESS;
unsigned char *currPayload = NULL;
IOT_DEBUG("-->Running Connect Tests - B:25 - Connect, flag settings and parameters are recorded in buffer \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
ConnectMQTTParamsSetup_Detailed(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID),
QOS1, false, true, "willTopicName", (uint16_t) strlen("willTopicName"), "willMsg",
(uint16_t) strlen("willMsg"), NULL, 0, NULL, 0);
connectParams.keepAliveIntervalInSec = (1 << 16) - 1;
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
currPayload = connectTxBufferHeaderParser(&prfrdParams, TxBuffer.pBuffer);
CHECK_C(true == isConnectTxBufFlagCorrect(&connectParams, &prfrdParams));
CHECK_C(true == isConnectTxBufPayloadCorrect(&connectParams, currPayload));
IOT_DEBUG("-->Success - B:25 - Connect, flag settings and parameters are recorded in buffer \n");
}
/* B:26 - Connect attempt, Disconnect, Manually reconnect */
TEST_C(ConnectTests, ConnectDisconnectConnect) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Connect Tests - B:26 - Connect attempt, Disconnect, Manually reconnect \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
// connect
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
// check the is_connected call
unitTestIsMqttConnected = aws_iot_mqtt_is_client_connected(&iotClient);
CHECK_EQUAL_C_INT(true, unitTestIsMqttConnected);
// disconnect
rc = aws_iot_mqtt_disconnect(&iotClient);
CHECK_EQUAL_C_INT(SUCCESS, rc);
// check the is_connected call
unitTestIsMqttConnected = aws_iot_mqtt_is_client_connected(&iotClient);
CHECK_EQUAL_C_INT(false, unitTestIsMqttConnected);
ResetTLSBuffer();
setTLSRxBufferForConnack(&connectParams, 0, 0);
// connect
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
// check the is_connected call
unitTestIsMqttConnected = aws_iot_mqtt_is_client_connected(&iotClient);
CHECK_EQUAL_C_INT(true, unitTestIsMqttConnected);
IOT_DEBUG("-->Success - B:26 - Connect attempt, Disconnect, Manually reconnect \n");
}
/* B:27 - Connect attempt, Clean session, Subscribe
* connect with clean session true and subscribe to a topic1, set msg to topic1 and ensure it is received
* connect cs false, set msg to topic1 and nothing should come in, Sub to topic2 and check if msg is received
* connect cs false and send msg to topic2 and should be received
* cs true and everything should be clean again
*/
TEST_C(ConnectTests, cleanSessionInitSubscribers) {
IoT_Error_t rc = SUCCESS;
char expectedCallbackString[] = "msg topic";
IOT_DEBUG("-->Running Connect Tests - B:27 - Connect attempt, Clean session, Subscribe \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
//1. connect with clean session true and
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
connectParams.isCleanSession = true;
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
//1. subscribe to a topic1 and
testPubMsgParams.payload = expectedCallbackString;
testPubMsgParams.payloadLen = (uint16_t) strlen(expectedCallbackString);
setTLSRxBufferForSuback(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic1, (uint16_t) strlen(subTopic1), QOS0, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
//1. receive message
setTLSRxBufferWithMsgOnSubscribedTopic(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams,
expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean);
ResetTLSBuffer();
rc = aws_iot_mqtt_disconnect(&iotClient);
//2. connect cs false and
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
connectParams.isCleanSession = false;
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
//3. set msg to topic1 and should receive the topic1 message
snprintf(CallbackMsgStringclean, 100, NO_MSG_XXXX);
setTLSRxBufferWithMsgOnSubscribedTopic(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams,
expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean);
ResetTLSBuffer();
//4. ,sub to topic2
snprintf(CallbackMsgStringclean, 100, NO_MSG_XXXX);
setTLSRxBufferForSuback(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic2, (uint16_t) strlen(subTopic2), QOS0, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
//5. and check if topic 2 msg is received
setTLSRxBufferWithMsgOnSubscribedTopic(subTopic2, strlen(subTopic2), QOS0, testPubMsgParams,
expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean);
rc = aws_iot_mqtt_disconnect(&iotClient);
//6. connect cs false and
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
connectParams.isCleanSession = false;
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
//7. set msg to topic2 and
snprintf(CallbackMsgStringclean, 100, NO_MSG_XXXX);
setTLSRxBufferWithMsgOnSubscribedTopic(subTopic2, strlen(subTopic2), QOS0, testPubMsgParams,
expectedCallbackString);
//8. should be received
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean);
IOT_DEBUG("-->Success - B:27 - Connect attempt, Clean session, Subscribe \n");
}
/* B:28 - Connect attempt, power cycle with clean session false
* This test is to ensure we can initialize the subscribe table in mqtt even when connecting with CS = false
* currently the AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS is set to 5
*/
TEST_C(ConnectTests, PowerCycleWithCleanSessionFalse) {
IoT_Error_t rc = SUCCESS;
int itr = 0;
char subTestTopic[12];
uint16_t subTestTopicLen = 0;
IOT_DEBUG("-->Running Connect Tests - B:28 - Connect attempt, power cycle with clean session false \n");
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
//1. connect with clean session false and
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
connectParams.isCleanSession = true;
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
//2. subscribe to max number of topics
for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; itr++) {
snprintf(subTestTopic, 12, "sdk/topic%d", itr + 1);
subTestTopicLen = (uint16_t) strlen(subTestTopic);
setTLSRxBufferForSuback(subTestTopic, subTestTopicLen, QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTestTopic, subTestTopicLen, QOS0, iot_subscribe_callback_handler,
NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
}
//3. Subscribe to one more topic. Should return error
snprintf(subTestTopic, 12, "sdk/topic%d", itr + 1);
subTestTopicLen = (uint16_t) strlen(subTestTopic);
setTLSRxBufferForSuback(subTestTopic, subTestTopicLen, QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTestTopic, subTestTopicLen, QOS0, iot_subscribe_callback_handler,
NULL);
CHECK_EQUAL_C_INT(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR, rc);
IOT_DEBUG("-->Success - B:28 - Connect attempt, power cycle with clean session false \n");
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_disconnect.cpp
* @brief IoT Client Unit Testing - Disconnect API Tests
*/
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness_c.h>
TEST_GROUP_C(DisconnectTests){
TEST_GROUP_C_SETUP_WRAPPER(DisconnectTests)
TEST_GROUP_C_TEARDOWN_WRAPPER(DisconnectTests)
};
/* F:1 - Disconnect with Null/empty client instance */
TEST_GROUP_C_WRAPPER(DisconnectTests, NullClientDisconnect)
/* F:2 - Set Disconnect Handler with Null/empty Client */
TEST_GROUP_C_WRAPPER(DisconnectTests, NullClientSetDisconnectHandler)
/* F:3 - Call Set Disconnect handler with Null handler */
TEST_GROUP_C_WRAPPER(DisconnectTests, SetDisconnectHandlerNullHandler)
/* F:4 - Disconnect attempt, not connected */
TEST_GROUP_C_WRAPPER(DisconnectTests, disconnectNotConnected)
/* F:5 - Disconnect success */
TEST_GROUP_C_WRAPPER(DisconnectTests, disconnectNoAckSuccess)
/* F:6 - Disconnect, Handler invoked on disconnect */
TEST_GROUP_C_WRAPPER(DisconnectTests, HandlerInvokedOnDisconnect)
/* F:7 - Disconnect, with set handler and invoked on disconnect */
TEST_GROUP_C_WRAPPER(DisconnectTests, SetHandlerAndInvokedOnDisconnect)

View File

@@ -0,0 +1,244 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_disconnect_helper.c
* @brief IoT Client Unit Testing - Disconnect Tests helper
*/
#include <stdio.h>
#include <unistd.h>
#include <CppUTest/TestHarness_c.h>
#include "aws_iot_tests_unit_helper_functions.h"
#include "aws_iot_log.h"
static IoT_Client_Init_Params initParams;
static IoT_Client_Connect_Params connectParams;
static AWS_IoT_Client iotClient;
static bool handlerInvoked = false;
void disconnectTestHandler(AWS_IoT_Client *pClient, void *disconHandlerParam) {
IOT_UNUSED(pClient);
IOT_UNUSED(disconHandlerParam);
handlerInvoked = true;
}
TEST_GROUP_C_SETUP(DisconnectTests) {
IoT_Error_t rc;
ResetTLSBuffer();
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, true, disconnectTestHandler);
initParams.mqttCommandTimeout_ms = 2000;
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
connectParams.keepAliveIntervalInSec = 5;
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc);
ResetTLSBuffer();
}
TEST_GROUP_C_TEARDOWN(DisconnectTests) { }
/* F:1 - Disconnect with Null/empty client instance */
TEST_C(DisconnectTests, NullClientDisconnect) {
IoT_Error_t rc = aws_iot_mqtt_disconnect(NULL);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
/* F:2 - Set Disconnect Handler with Null/empty Client */
TEST_C(DisconnectTests, NullClientSetDisconnectHandler) {
IoT_Error_t rc = aws_iot_mqtt_set_disconnect_handler(NULL, disconnectTestHandler, NULL);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
/* F:3 - Call Set Disconnect handler with Null handler */
TEST_C(DisconnectTests, SetDisconnectHandlerNullHandler) {
IoT_Error_t rc = aws_iot_mqtt_set_disconnect_handler(&iotClient, NULL, NULL);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
/* F:4 - Disconnect attempt, not connected */
TEST_C(DisconnectTests, disconnectNotConnected) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Disconnect Tests - F:4 - Disconnect attempt, not connected \n");
/* First make sure client is disconnected */
rc = aws_iot_mqtt_disconnect(&iotClient);
/* Check client is disconnected */
CHECK_EQUAL_C_INT(false, aws_iot_mqtt_is_client_connected(&iotClient));
/* Now call disconnect again */
rc = aws_iot_mqtt_disconnect(&iotClient);
CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc);
IOT_DEBUG("-->Success - F:4 - Disconnect attempt, not connected \n");
}
/* F:5 - Disconnect success */
TEST_C(DisconnectTests, disconnectNoAckSuccess) {
IoT_Error_t rc = SUCCESS;
rc = aws_iot_mqtt_disconnect(&iotClient);
CHECK_EQUAL_C_INT(SUCCESS, rc);
}
/* F:6 - Disconnect, Handler invoked on disconnect */
TEST_C(DisconnectTests, HandlerInvokedOnDisconnect) {
bool connected = false;
bool currentAutoReconnectStatus = false;
int i;
int j;
int attempt = 3;
uint32_t dcCount = 0;
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Disconnect Tests - F:6 - Disconnect, Handler invoked on disconnect \n");
handlerInvoked = false;
IOT_DEBUG("Current Keep Alive Interval is set to %d sec.\n", connectParams.keepAliveIntervalInSec);
currentAutoReconnectStatus = aws_iot_is_autoreconnect_enabled(&iotClient);
connected = aws_iot_mqtt_is_client_connected(&iotClient);
CHECK_EQUAL_C_INT(1, connected);
aws_iot_mqtt_autoreconnect_set_status(&iotClient, false);
// 3 cycles of half keep alive time expiring
// verify a ping request is sent and give a ping response
for(i = 0; i < attempt; i++) {
/* Set TLS buffer for ping response */
ResetTLSBuffer();
setTLSRxBufferForPingresp();
for(j = 0; j <= connectParams.keepAliveIntervalInSec; j++) {
sleep(1);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
}
CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePingreq());
}
// keepalive() waits for 1/2 of keepalive time after sending ping request
// to receive a pingresponse before determining the connection is not alive
// wait for keepalive time and then yield()
sleep(connectParams.keepAliveIntervalInSec);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc);
CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect());
connected = aws_iot_mqtt_is_client_connected(&iotClient);
CHECK_EQUAL_C_INT(0, connected);
CHECK_EQUAL_C_INT(true, handlerInvoked);
dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient);
CHECK_C(1 == dcCount);
aws_iot_mqtt_reset_network_disconnected_count(&iotClient);
dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient);
CHECK_C(0 == dcCount);
ResetTLSBuffer();
aws_iot_mqtt_autoreconnect_set_status(&iotClient, currentAutoReconnectStatus);
IOT_DEBUG("-->Success - F:6 - Disconnect, Handler invoked on disconnect \n");
}
/* F:7 - Disconnect, with set handler and invoked on disconnect */
TEST_C(DisconnectTests, SetHandlerAndInvokedOnDisconnect) {
bool connected = false;
bool currentAutoReconnectStatus = false;
int i;
int j;
int attempt = 3;
uint32_t dcCount = 0;
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Disconnect Tests - F:7 - Disconnect, with set handler and invoked on disconnect \n");
handlerInvoked = false;
InitMQTTParamsSetup(&initParams, "localhost", 8883, false, NULL);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
connectParams.keepAliveIntervalInSec = 5;
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
aws_iot_mqtt_set_disconnect_handler(&iotClient, disconnectTestHandler, NULL);
aws_iot_mqtt_autoreconnect_set_status(&iotClient, true);
IOT_DEBUG("Current Keep Alive Interval is set to %d sec.\n", connectParams.keepAliveIntervalInSec);
currentAutoReconnectStatus = aws_iot_is_autoreconnect_enabled(&iotClient);
connected = aws_iot_mqtt_is_client_connected(&iotClient);
CHECK_EQUAL_C_INT(1, connected);
aws_iot_mqtt_autoreconnect_set_status(&iotClient, false);
// 3 cycles of keep alive time expiring
// verify a ping request is sent and give a ping response
for(i = 0; i < attempt; i++) {
/* Set TLS buffer for ping response */
ResetTLSBuffer();
setTLSRxBufferForPingresp();
for(j = 0; j <= connectParams.keepAliveIntervalInSec; j++) {
sleep(1);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
}
CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePingreq());
}
ResetTLSBuffer();
// keepalive() waits for 1/2 of keepalive time after sending ping request
// to receive a pingresponse before determining the connection is not alive
// wait for keepalive time and then yield()
sleep(connectParams.keepAliveIntervalInSec);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc);
CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect());
connected = aws_iot_mqtt_is_client_connected(&iotClient);
CHECK_EQUAL_C_INT(0, connected);
CHECK_EQUAL_C_INT(true, handlerInvoked);
dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient);
CHECK_C(1 == dcCount);
aws_iot_mqtt_reset_network_disconnected_count(&iotClient);
dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient);
CHECK_C(0 == dcCount);
ResetTLSBuffer();
aws_iot_mqtt_autoreconnect_set_status(&iotClient, currentAutoReconnectStatus);
IOT_DEBUG("-->Success - F:7 - Disconnect, with set handler and invoked on disconnect \n");
}

View File

@@ -0,0 +1,511 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_helper_functions.c
* @brief IoT Client Unit Testing - Helper Functions
*/
#include <stdio.h>
#include <string.h>
#include "aws_iot_mqtt_client.h"
#include "aws_iot_tests_unit_mock_tls_params.h"
#include "aws_iot_tests_unit_helper_functions.h"
#define CONNACK_SUBACK_PACKET_SIZE 9
#define PUBACK_PACKET_SIZE 4
#define SUBACK_PACKET_SIZE 5
#define UNSUBACK_PACKET_SIZE 4
#define PINGRESP_PACKET_SIZE 2
void ResetInvalidParameters(void) {
invalidEndpointFilter = NULL;
invalidRootCAPathFilter = NULL;
invalidCertPathFilter = NULL;
invalidPrivKeyPathFilter = NULL;
invalidPortFilter = 0;
}
void InitMQTTParamsSetup(IoT_Client_Init_Params *params, char *pHost, uint16_t port, bool enableAutoReconnect,
iot_disconnect_handler disconnectHandler) {
params->pHostURL = pHost;
params->port = port;
params->mqttCommandTimeout_ms = 5000;
params->tlsHandshakeTimeout_ms = 5000;
params->enableAutoReconnect = enableAutoReconnect;
params->disconnectHandler = disconnectHandler;
params->disconnectHandlerData = NULL;
params->isSSLHostnameVerify = true;
params->pDeviceCertLocation = AWS_IOT_ROOT_CA_FILENAME;
params->pDevicePrivateKeyLocation = AWS_IOT_CERTIFICATE_FILENAME;
params->pRootCALocation = AWS_IOT_PRIVATE_KEY_FILENAME;
}
void ConnectMQTTParamsSetup(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen) {
params->keepAliveIntervalInSec = 10;
params->isCleanSession = 1;
params->MQTTVersion = MQTT_3_1_1;
params->pClientID = pClientID;
params->clientIDLen = clientIDLen;
params->isWillMsgPresent = false;
params->pUsername = NULL;
params->usernameLen = 0;
params->pPassword = NULL;
params->passwordLen = 0;
}
void ConnectMQTTParamsSetup_Detailed(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen, QoS qos,
bool isCleanSession, bool isWillMsgPresent, char *pWillTopicName,
uint16_t willTopicNameLen, char *pWillMessage, uint16_t willMsgLen,
char *pUsername, uint16_t userNameLen, char *pPassword, uint16_t passwordLen) {
params->keepAliveIntervalInSec = 10;
params->isCleanSession = isCleanSession;
params->MQTTVersion = MQTT_3_1_1;
params->pClientID = pClientID;
params->clientIDLen = clientIDLen;
params->pUsername = pUsername;
params->usernameLen = userNameLen;
params->pPassword = pPassword;
params->passwordLen = passwordLen;
params->isWillMsgPresent = isWillMsgPresent;
params->will.pMessage = pWillMessage;
params->will.msgLen = willMsgLen;
params->will.pTopicName = pWillTopicName;
params->will.topicNameLen = willTopicNameLen;
params->will.qos = qos;
params->will.isRetained = false;
}
void printBuffer(unsigned char *buffer, size_t len) {
size_t i;
printf("\n--\n");
for(i = 0; i < len; i++) {
printf("%d: %c, %d\n", (uint32_t)i, buffer[i], buffer[i]);
}
printf("\n--\n");
}
#define CONNACK_PACKET_SIZE 4
void setTLSRxBufferForConnack(IoT_Client_Connect_Params *params, unsigned char sessionPresent,
unsigned char connackResponseCode) {
RxBuffer.NoMsgFlag = false;
if(params->isCleanSession) {
sessionPresent = 0;
}
RxBuffer.pBuffer[0] = (unsigned char) (0x20);
RxBuffer.pBuffer[1] = (unsigned char) (0x02);
RxBuffer.pBuffer[2] = sessionPresent;
RxBuffer.pBuffer[3] = connackResponseCode;
RxBuffer.len = CONNACK_PACKET_SIZE;
RxIndex = 0;
}
void setTLSRxBufferForConnackAndSuback(IoT_Client_Connect_Params *conParams, unsigned char sessionPresent,
char *topicName, size_t topicNameLen, QoS qos) {
IOT_UNUSED(topicName);
IOT_UNUSED(topicNameLen);
RxBuffer.NoMsgFlag = false;
if(conParams->isCleanSession) {
sessionPresent = 0;
}
RxBuffer.pBuffer[0] = (unsigned char) (0x20);
RxBuffer.pBuffer[1] = (unsigned char) (0x02);
RxBuffer.pBuffer[2] = sessionPresent;
RxBuffer.pBuffer[3] = (unsigned char) (0x0);
RxBuffer.pBuffer[4] = (unsigned char) (0x90);
RxBuffer.pBuffer[5] = (unsigned char) (0x2 + 1);
// Variable header - packet identifier
RxBuffer.pBuffer[6] = (unsigned char) (2);
RxBuffer.pBuffer[7] = (unsigned char) (0);
// payload
RxBuffer.pBuffer[8] = (unsigned char) (qos);
RxBuffer.len = CONNACK_SUBACK_PACKET_SIZE;
RxIndex = 0;
}
void setTLSRxBufferForPuback(void) {
size_t i;
RxBuffer.NoMsgFlag = true;
RxBuffer.len = PUBACK_PACKET_SIZE;
RxIndex = 0;
for(i = 0; i < RxBuffer.BufMaxSize; i++) {
RxBuffer.pBuffer[i] = 0;
}
RxBuffer.pBuffer[0] = (unsigned char) (0x40);
RxBuffer.pBuffer[1] = (unsigned char) (0x02);
RxBuffer.pBuffer[2] = (unsigned char) (0x02);
RxBuffer.pBuffer[3] = (unsigned char) (0x00);
RxBuffer.NoMsgFlag = false;
}
void setTLSRxBufferForSubFail(void) {
RxBuffer.NoMsgFlag = false;
RxBuffer.pBuffer[0] = (unsigned char) (0x90);
RxBuffer.pBuffer[1] = (unsigned char) (0x2 + 1);
// Variable header - packet identifier
RxBuffer.pBuffer[2] = (unsigned char) (2);
RxBuffer.pBuffer[3] = (unsigned char) (0);
// payload
RxBuffer.pBuffer[4] = (unsigned char) (128);
RxBuffer.len = SUBACK_PACKET_SIZE;
RxIndex = 0;
}
void setTLSRxBufferForDoubleSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params) {
IOT_UNUSED(topicName);
IOT_UNUSED(topicNameLen);
IOT_UNUSED(params);
RxBuffer.NoMsgFlag = false;
RxBuffer.pBuffer[0] = (unsigned char) (0x90);
RxBuffer.pBuffer[1] = (unsigned char) (0x2 + 1);
// Variable header - packet identifier
RxBuffer.pBuffer[2] = (unsigned char) (2);
RxBuffer.pBuffer[3] = (unsigned char) (0);
// payload
RxBuffer.pBuffer[4] = (unsigned char) (qos);
RxBuffer.pBuffer[5] = (unsigned char) (0x90);
RxBuffer.pBuffer[6] = (unsigned char) (0x2 + 1);
// Variable header - packet identifier
RxBuffer.pBuffer[7] = (unsigned char) (2);
RxBuffer.pBuffer[8] = (unsigned char) (0);
// payload
RxBuffer.pBuffer[9] = (unsigned char) (qos);
RxBuffer.len = SUBACK_PACKET_SIZE * 2;
RxIndex = 0;
}
void setTLSRxBufferForSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params) {
IOT_UNUSED(topicName);
IOT_UNUSED(topicNameLen);
IOT_UNUSED(params);
RxBuffer.NoMsgFlag = false;
RxBuffer.pBuffer[0] = (unsigned char) (0x90);
RxBuffer.pBuffer[1] = (unsigned char) (0x2 + 1);
// Variable header - packet identifier
RxBuffer.pBuffer[2] = (unsigned char) (2);
RxBuffer.pBuffer[3] = (unsigned char) (0);
// payload
RxBuffer.pBuffer[4] = (unsigned char) (qos);
RxBuffer.len = SUBACK_PACKET_SIZE;
RxIndex = 0;
}
void setTLSRxBufferForUnsuback(void) {
RxBuffer.NoMsgFlag = false;
RxBuffer.pBuffer[0] = (unsigned char) (0xB0);
RxBuffer.pBuffer[1] = (unsigned char) (0x02);
// Variable header - packet identifier
RxBuffer.pBuffer[2] = (unsigned char) (2);
RxBuffer.pBuffer[3] = (unsigned char) (0);
// No payload
RxBuffer.len = UNSUBACK_PACKET_SIZE;
RxIndex = 0;
}
void setTLSRxBufferForPingresp(void) {
RxBuffer.NoMsgFlag = false;
RxBuffer.pBuffer[0] = (unsigned char) (0xD0);
RxBuffer.pBuffer[1] = (unsigned char) (0x00);
RxBuffer.len = PINGRESP_PACKET_SIZE;
RxIndex = 0;
}
void ResetTLSBuffer(void) {
size_t i;
RxBuffer.len = 0;
RxBuffer.NoMsgFlag = true;
for(i = 0; i < RxBuffer.BufMaxSize; i++) {
RxBuffer.pBuffer[i] = 0;
}
RxIndex = 0;
RxBuffer.expiry_time.tv_sec = 0;
RxBuffer.expiry_time.tv_usec = 0;
TxBuffer.len = 0;
for(i = 0; i < TxBuffer.BufMaxSize; i++) {
TxBuffer.pBuffer[i] = 0;
}
}
void setTLSRxBufferDelay(int seconds, int microseconds) {
struct timeval now, duration, result;
duration.tv_sec = seconds;
duration.tv_usec = microseconds;
gettimeofday(&now, NULL);
timeradd(&now, &duration, &result);
RxBuffer.expiry_time.tv_sec = result.tv_sec;
RxBuffer.expiry_time.tv_usec = result.tv_usec;
}
void setTLSRxBufferWithMsgOnSubscribedTopic(char *topicName, size_t topicNameLen, QoS qos,
IoT_Publish_Message_Params params, char *pMsg) {
size_t VariableLen = topicNameLen + 2 + 2;
size_t i = 0, cursor = 0, packetIdStartLoc = 0, payloadStartLoc = 0, VarHeaderStartLoc = 0;
size_t PayloadLen = strlen(pMsg) + 1;
RxBuffer.NoMsgFlag = false;
RxBuffer.pBuffer[0] = (unsigned char) (0x30 | ((params.qos << 1) & 0xF));// QoS1
cursor++; // Move the cursor
// Remaining Length
// Translate the Remaining Length into packet bytes
encodeRemainingLength(RxBuffer.pBuffer, &cursor, VariableLen + PayloadLen);
VarHeaderStartLoc = cursor - 1;
// Variable header
RxBuffer.pBuffer[VarHeaderStartLoc + 1] = (unsigned char) ((topicNameLen & 0xFF00) >> 8);
RxBuffer.pBuffer[VarHeaderStartLoc + 2] = (unsigned char) (topicNameLen & 0xFF);
for(i = 0; i < topicNameLen; i++) {
RxBuffer.pBuffer[VarHeaderStartLoc + 3 + i] = (unsigned char) topicName[i];
}
packetIdStartLoc = VarHeaderStartLoc + topicNameLen + 2;
payloadStartLoc = (packetIdStartLoc + 1);
if(QOS0 != qos) {
// packet id only for QoS 1 or 2
RxBuffer.pBuffer[packetIdStartLoc + 1] = 2;
RxBuffer.pBuffer[packetIdStartLoc + 2] = 3;
payloadStartLoc = packetIdStartLoc + 3;
}
// payload
for(i = 0; i < PayloadLen; i++) {
RxBuffer.pBuffer[payloadStartLoc + i] = (unsigned char) pMsg[i];
}
RxBuffer.len = VariableLen + PayloadLen + 2; // 2 for fixed header
RxIndex = 0;
//printBuffer(RxBuffer.pBuffer, RxBuffer.len);
}
unsigned char isLastTLSTxMessagePuback() {
return (unsigned char) (TxBuffer.pBuffer[0] == 0x40 ? 1 : 0);
}
unsigned char isLastTLSTxMessagePingreq() {
return (unsigned char) (TxBuffer.pBuffer[0] == 0xC0 ? 1 : 0);
}
unsigned char isLastTLSTxMessageDisconnect() {
return (unsigned char) (TxBuffer.pBuffer[0] == 0xE0 ? 1 : 0);
}
unsigned char generateMultipleSubTopics(char *des, int boundary) {
int i;
int currLen = 0;
char *op1 = des;
unsigned char ret = (unsigned char) (des == NULL ? 0 : 1);
while(*op1 != '\0') {
currLen++;
op1++;
}
// Save 1 byte for terminator '\0'
for(i = 0; i < boundary - currLen - 1; i++) {
//printf("%d\n", i);
strcat(des, "a");
}
return ret;
}
void encodeRemainingLength(unsigned char *buf, size_t *st, size_t length) {
unsigned char c;
// watch out for the type of length, could be over flow. Limits = 256MB
// No boundary check for 256MB!!
do {
c = (unsigned char) (length % 128);
length /= 128;
if(length > 0) c |= (unsigned char) (0x80); // If there is still another byte following
buf[(*st)++] = c;
} while(length > 0);
// At this point, *st should be the next position for a new part of data in the packet
}
unsigned char *connectTxBufferHeaderParser(ConnectBufferProofread *params, unsigned char *buf) {
unsigned char *op = buf;
// Get packet type
unsigned char *ele1 = op;
unsigned int multiplier = 1;
int cnt = 0;
unsigned char *ele2;
unsigned int x;
unsigned char *op2;
params->PacketType = *ele1;
op++;
// Get remaining length (length bytes more than 4 bytes are ignored)
params->RemainingLength = 0;
do {
ele2 = op;
params->RemainingLength += ((unsigned int) (*ele2 & (0x7F)) * multiplier);
multiplier *= 128;
cnt++;
op++;
} while((*ele2 & (0x80)) != 0 && cnt < 4);
// At this point, op should be updated to the start address of the next chunk of information
// Get protocol length
params->ProtocolLength = 0;
params->ProtocolLength += (256 * (unsigned int) (*op++));
params->ProtocolLength += (unsigned int) (*op++);
// Get protocol name
for(x = 0; x < params->ProtocolLength; x++) {
params->ProtocolName[x] = *op;
op++;
}
// Get protocol level
params->ProtocolLevel = (unsigned int) (*op++);
// Get connect flags
params->ConnectFlag = (*op++);
// Get keepalive
op2 = op;
params->KeepAlive = 0;
params->KeepAlive += (256 * (unsigned int) (*op2++)); // get rid of the sign bit
op++;
params->KeepAlive += (unsigned int) (*op2++);
op++;
return op;
}
bool isConnectTxBufFlagCorrect(IoT_Client_Connect_Params *settings, ConnectBufferProofread *readRes) {
bool ret = true;
int i;
unsigned char myByte[8]; // Construct our own connect flag byte according to the settings
myByte[0] = (unsigned char) (settings->pUsername == NULL ? 0 : 1); // User Name Flag
myByte[1] = (unsigned char) (settings->pPassword == NULL ? 0 : 1); // Password Flag
myByte[2] = 0; // Will Retain
// QoS
if(QOS1 == settings->will.qos) {
myByte[3] = 0;
myByte[4] = 1;
} else { // default QoS is QOS0
myByte[3] = 0;
myByte[4] = 0;
}
//
myByte[5] = (unsigned char) settings->isWillMsgPresent; // Will Flag
myByte[6] = (unsigned char) settings->isCleanSession; // Clean Session
myByte[7] = 0; // Retained
//
for(i = 0; i < 8; i++) {
if(myByte[i] != (unsigned char) (((readRes->ConnectFlag) >> (7 - i)) & 0x01)) {
printf("ex %x ac %x\n", (unsigned char) (((readRes->ConnectFlag) >> (7 - i)) & 0x01) + '0', myByte[i]);
ret = false;
break;
}
}
return ret;
}
bool isConnectTxBufPayloadCorrect(IoT_Client_Connect_Params *settings, unsigned char *payloadBuf) {
// Construct our own payload according to the settings to see if the real one matches with it
unsigned int ClientIDLen = (unsigned int) strlen(settings->pClientID);
unsigned int WillTopicLen = (unsigned int) strlen(settings->will.pTopicName);
unsigned int WillMsgLen = (unsigned int) strlen(settings->will.pMessage);
unsigned int UsernameLen = (unsigned int) settings->usernameLen;
unsigned int PasswordLen = (unsigned int) settings->passwordLen;
unsigned int myPayloadLen = ClientIDLen + 2 + WillTopicLen + 2 + WillMsgLen + UsernameLen + 2 + PasswordLen;
char *myPayload = (char *) malloc(sizeof(char) * (myPayloadLen + 1)); // reserve 1 byte for '\0'
// Construction starts...
unsigned int i;
bool ret = false;
char *op = myPayload;
*op = (char) (ClientIDLen & 0x0FF00); // MSB There is a writeInt inside paho... MQTTString.lenstring.len != 0
op++;
*op = (char) (ClientIDLen & 0x00FF); // LSB
op++;
// ClientID
for(i = 0; i < ClientIDLen; i++) {
*op = settings->pClientID[i];
op++;
}
if(true == settings->isWillMsgPresent) {
// WillTopic
for(i = 0; i < WillTopicLen; i++) {
*op = settings->will.pTopicName[i];
op++;
}
// WillMsg Len
*op = (char) (WillMsgLen & 0x0FF00); // MSB
op++;
*op = (char) (WillMsgLen & 0x00FF); // LSB
op++;
// WillMsg
for(i = 0; i < WillMsgLen; i++) {
*op = settings->will.pMessage[i];
op++;
}
}
// Username
if(NULL != settings->pUsername) {
for(i = 0; i < UsernameLen; i++) {
*op = settings->pUsername[i];
op++;
}
}
// PasswordLen + Password
if(NULL != settings->pPassword) {
*op = (char) (PasswordLen & 0x0FF00); // MSB
op++;
*op = (char) (PasswordLen & 0x00FF); // LSB
op++;
//
for(i = 0; i < PasswordLen; i++) {
*op = settings->pPassword[i];
op++;
}
}
//
*op = '\0';
ret = strcmp(myPayload, (const char *)payloadBuf) == 0 ? true : false;
free(myPayload);
return ret;
}
void printPrfrdParams(ConnectBufferProofread *params) {
unsigned int i;
printf("\n----------------\n");
printf("PacketType: %x\n", params->PacketType);
printf("RemainingLength: %u\n", params->RemainingLength);
printf("ProtocolLength: %u\n", params->ProtocolLength);
printf("ProtocolName: ");
for(i = 0; i < params->ProtocolLength; i++) {
printf("%c", params->ProtocolName[i]);
}
printf("\n");
printf("ProtocolLevel: %u\n", params->ProtocolLevel);
printf("ConnectFlag: %x\n", params->ConnectFlag);
printf("KeepAliveInterval: %u\n", params->KeepAlive);
printf("----------------\n");
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_json_utils.cpp
* @brief IoT Client Unit Testing - JSON Utility Tests
*/
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness_c.h>
TEST_GROUP_C(JsonUtils) {
TEST_GROUP_C_SETUP_WRAPPER(JsonUtils)
TEST_GROUP_C_TEARDOWN_WRAPPER(JsonUtils)
};
TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringBasic)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringLongerStringIsValid)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringEmptyStringIsValid)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringErrorOnInteger)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringErrorOnBoolean)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanTrue)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanFalse)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanErrorOnString)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanErrorOnInvalidJson)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleBasic)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleNumberWithNoDecimal)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleSmallDouble)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleErrorOnString)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleErrorOnBoolean)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleErrorOnJsonObject)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleNegativeNumber)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatBasic)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatNumberWithNoDecimal)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatSmallFloat)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatErrorOnString)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatErrorOnBoolean)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatErrorOnJsonObject)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatNegativeNumber)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerBasic)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerLargeInteger)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerNegativeInteger)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerErrorOnBoolean)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerErrorOnString)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitBasic)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitLargeInteger)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitNegativeInteger)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitErrorOnBoolean)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitErrorOnString)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitBasic)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitLargeInteger)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitNegativeInteger)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitErrorOnBoolean)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitErrorOnString)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerBasic)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerLargeInteger)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerErrorOnNegativeInteger)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerErrorOnBoolean)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerErrorOnString)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitBasic)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitLargeInteger)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitErrorOnNegativeInteger)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitErrorOnBoolean)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitErrorOnString)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitBasic)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitLargeInteger)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitErrorOnNegativeInteger)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitErrorOnBoolean)
TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitErrorOnString)

View File

@@ -0,0 +1,810 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_json_utils_helper.c
* @brief IoT Client Unit Testing - JSON Utility Tests helper
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <CppUTest/TestHarness_c.h>
#include "aws_iot_json_utils.h"
#include "aws_iot_tests_unit_helper_functions.h"
#include "aws_iot_log.h"
static IoT_Error_t rc = SUCCESS;
static jsmn_parser test_parser;
static jsmntok_t t[128];
TEST_GROUP_C_SETUP(JsonUtils) {
jsmn_init(&test_parser);
}
TEST_GROUP_C_TEARDOWN(JsonUtils) {
}
TEST_C(JsonUtils, ParseStringBasic) {
int r;
const char *json = "{\"x\":\"test1\"}";
char parsedString[50];
IOT_DEBUG("\n-->Running Json Utils Tests - Basic String Parsing \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseStringValue(parsedString, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING("test1", parsedString);
}
TEST_C(JsonUtils, ParseStringLongerStringIsValid) {
int r;
const char *json = "{\"x\":\"this is a longer string for test 2\"}";
char parsedString[50];
IOT_DEBUG("\n-->Running Json Utils Tests - Parse long string \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseStringValue(parsedString, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING("this is a longer string for test 2", parsedString);
}
TEST_C(JsonUtils, ParseStringEmptyStringIsValid) { int r;
const char *json = "{\"x\":\"\"}";
char parsedString[50];
IOT_DEBUG("\n-->Running Json Utils Tests - Parse empty string \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseStringValue(parsedString, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING("", parsedString);
}
TEST_C(JsonUtils, ParseStringErrorOnInteger) {
int r;
const char *json = "{\"x\":3}";
char parsedString[50];
IOT_DEBUG("\n-->Running Json Utils Tests - parse integer as string returns error \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseStringValue(parsedString, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseStringErrorOnBoolean) {
int r;
const char *json = "{\"x\":true}";
char parsedString[50];
IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean as string returns error \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseStringValue(parsedString, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseBooleanTrue) {
int r;
const char *json = "{\"x\":true}";
bool parsedBool;
IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean with true value \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseBooleanValue(&parsedBool, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(1, (int) parsedBool);
}
TEST_C(JsonUtils, ParseBooleanFalse) {
int r;
const char *json = "{\"x\":false}";
bool parsedBool;
IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean with false value \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseBooleanValue(&parsedBool, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(0, (int) parsedBool);
}
TEST_C(JsonUtils, ParseBooleanErrorOnString) {
int r;
const char *json = "{\"x\":\"not a bool\"}";
bool parsedBool;
IOT_DEBUG("\n-->Running Json Utils Tests - parse string as boolean returns error \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseBooleanValue(&parsedBool, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseBooleanErrorOnInvalidJson) {
int r;
const char *json = "{\"x\":frue}"; // Invalid
bool parsedBool;
IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean returns error with invalid json \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseBooleanValue(&parsedBool, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseDoubleBasic) {
int r;
const char *json = "{\"x\":20.5}";
double parsedDouble;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse double test \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseDoubleValue(&parsedDouble, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_REAL(20.5, parsedDouble, 0.0);
}
TEST_C(JsonUtils, ParseDoubleNumberWithNoDecimal) {
int r;
const char *json = "{\"x\":100}";
double parsedDouble;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse double number with no decimal \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseDoubleValue(&parsedDouble, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_REAL(100, parsedDouble, 0.0);
}
TEST_C(JsonUtils, ParseDoubleSmallDouble) {
int r;
const char *json = "{\"x\":0.000004}";
double parsedDouble;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse small double value \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseDoubleValue(&parsedDouble, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_REAL(0.000004, parsedDouble, 0.0);
}
TEST_C(JsonUtils, ParseDoubleErrorOnString) {
int r;
const char *json = "{\"x\":\"20.5\"}";
double parsedDouble;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse string as double returns error \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseDoubleValue(&parsedDouble, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseDoubleErrorOnBoolean) {
int r;
const char *json = "{\"x\":true}";
double parsedDouble;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse boolean as double returns error \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseDoubleValue(&parsedDouble, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseDoubleErrorOnJsonObject) {
int r;
const char *json = "{\"x\":{}}";
double parsedDouble;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse json object as double returns error \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseDoubleValue(&parsedDouble, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseDoubleNegativeNumber) {
int r;
const char *json = "{\"x\":-56.78}";
double parsedDouble;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative double value \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseDoubleValue(&parsedDouble, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_REAL(-56.78, parsedDouble, 0.0);
}
TEST_C(JsonUtils, ParseFloatBasic) {
int r;
const char *json = "{\"x\":20.5}";
float parsedFloat;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse float test \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseFloatValue(&parsedFloat, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_REAL(20.5, parsedFloat, 0.0);
}
TEST_C(JsonUtils, ParseFloatNumberWithNoDecimal) {
int r;
const char *json = "{\"x\":100}";
float parsedFloat;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse float number with no decimal \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseFloatValue(&parsedFloat, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_REAL(100, parsedFloat, 0.0);
}
TEST_C(JsonUtils, ParseFloatSmallFloat) {
int r;
const char *json = "{\"x\":0.0004}";
float parsedFloat;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse small float value \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseFloatValue(&parsedFloat, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_C(0.0004f == parsedFloat);
}
TEST_C(JsonUtils, ParseFloatErrorOnString) {
int r;
const char *json = "{\"x\":\"20.5\"}";
float parsedFloat;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse string as float returns error \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseFloatValue(&parsedFloat, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseFloatErrorOnBoolean) {
int r;
const char *json = "{\"x\":true}";
float parsedFloat;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse boolean as float returns error \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseFloatValue(&parsedFloat, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseFloatErrorOnJsonObject) {
int r;
const char *json = "{\"x\":{}}";
float parsedDouble;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse json object as float returns error \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseFloatValue(&parsedDouble, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseFloatNegativeNumber) {
int r;
const char *json = "{\"x\":-56.78}";
float parsedFloat;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative float value \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseFloatValue(&parsedFloat, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_C(-56.78f == parsedFloat);
}
TEST_C(JsonUtils, ParseIntegerBasic) {
int r;
const char *json = "{\"x\":1}";
int32_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse 32 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger32Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(1, parsedInteger);
}
TEST_C(JsonUtils, ParseIntegerLargeInteger) {
int r;
const char *json = "{\"x\":2147483647}";
int32_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse large 32 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger32Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(2147483647, parsedInteger);
}
TEST_C(JsonUtils, ParseIntegerNegativeInteger) {
int r;
const char *json = "{\"x\":-308}";
int32_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative 32 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger32Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(-308, parsedInteger);
}
TEST_C(JsonUtils, ParseIntegerErrorOnBoolean) {
int r;
const char *json = "{\"x\":true}";
int32_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse 32 bit integer returns error with boolean \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger32Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseIntegerErrorOnString) {
int r;
const char *json = "{\"x\":\"45\"}";
int32_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse 32 bit integer returns error on string \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger32Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseInteger16bitBasic) {
int r;
const char *json = "{\"x\":1}";
int16_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse 16 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger16Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(1, parsedInteger);
}
TEST_C(JsonUtils, ParseInteger16bitLargeInteger) {
int r;
const char *json = "{\"x\":32767}";
int16_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse large 16 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger16Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(32767, parsedInteger);
}
TEST_C(JsonUtils, ParseInteger16bitNegativeInteger) {
int r;
const char *json = "{\"x\":-308}";
int16_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative 16 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger16Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(-308, parsedInteger);
}
TEST_C(JsonUtils, ParseInteger16bitErrorOnBoolean) {
int r;
const char *json = "{\"x\":true}";
int16_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse 16 bit integer returns error with boolean \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger16Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseInteger16bitErrorOnString) {
int r;
const char *json = "{\"x\":\"45\"}";
int16_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse 16 bit integer returns error on string \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger16Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseInteger8bitBasic) {
int r;
const char *json = "{\"x\":1}";
int8_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse 8 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger8Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(1, parsedInteger);
}
TEST_C(JsonUtils, ParseInteger8bitLargeInteger) {
int r;
const char *json = "{\"x\":127}";
int8_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse large 8 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger8Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(127, parsedInteger);
}
TEST_C(JsonUtils, ParseInteger8bitNegativeInteger) {
int r;
const char *json = "{\"x\":-30}";
int8_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative 8 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger8Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(-30, parsedInteger);
}
TEST_C(JsonUtils, ParseInteger8bitErrorOnBoolean) {
int r;
const char *json = "{\"x\":true}";
int8_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse 8 bit integer returns error with boolean \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger8Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseInteger8bitErrorOnString) {
int r;
const char *json = "{\"x\":\"45\"}";
int8_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse 8 bit integer returns error on string \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseInteger8Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseUnsignedIntegerBasic) {
int r;
const char *json = "{\"x\":1}";
uint32_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_C(1 == parsedInteger);
}
TEST_C(JsonUtils, ParseUnsignedIntegerLargeInteger) {
int r;
const char *json = "{\"x\":2147483647}";
uint32_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse large unsigned 32 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_C(2147483647 == parsedInteger);
}
TEST_C(JsonUtils, ParseUnsignedIntegerErrorOnNegativeInteger) {
int r;
const char *json = "{\"x\":-308}";
uint32_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer returns error with negative value \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseUnsignedIntegerErrorOnBoolean) {
int r;
const char *json = "{\"x\":true}";
uint32_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer returns error with boolean \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseUnsignedIntegerErrorOnString) {
int r;
const char *json = "{\"x\":\"45\"}";
uint32_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer returns error on string \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseUnsignedInteger16bitBasic) {
int r;
const char *json = "{\"x\":1}";
uint16_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(1, parsedInteger);
}
TEST_C(JsonUtils, ParseUnsignedInteger16bitLargeInteger) {
int r;
const char *json = "{\"x\":65535}";
uint16_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse large unsigned 16 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(65535, parsedInteger);
}
TEST_C(JsonUtils, ParseUnsignedInteger16bitErrorOnNegativeInteger) {
int r;
const char *json = "{\"x\":-308}";
uint16_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer returns error on negative value \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseUnsignedInteger16bitErrorOnBoolean) {
int r;
const char *json = "{\"x\":true}";
uint16_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer returns error with boolean \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseUnsignedInteger16bitErrorOnString) {
int r;
const char *json = "{\"x\":\"45\"}";
uint16_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer returns error on string \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseUnsignedInteger8bitBasic) {
int r;
const char *json = "{\"x\":1}";
uint8_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(1, parsedInteger);
}
TEST_C(JsonUtils, ParseUnsignedInteger8bitLargeInteger) {
int r;
const char *json = "{\"x\":255}";
uint8_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse large unsigned 8 bit integer \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(255, parsedInteger);
}
TEST_C(JsonUtils, ParseUnsignedInteger8bitErrorOnNegativeInteger) {
int r;
const char *json = "{\"x\":-30}";
uint8_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer returns error on negative value \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseUnsignedInteger8bitErrorOnBoolean) {
int r;
const char *json = "{\"x\":true}";
uint8_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer returns error with boolean \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}
TEST_C(JsonUtils, ParseUnsignedInteger8bitErrorOnString) {
int r;
const char *json = "{\"x\":\"45\"}";
uint8_t parsedInteger;
IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer returns error on string \n");
r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0]));
rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2);
CHECK_EQUAL_C_INT(3, r);
CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc);
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_publish.cpp
* @brief IoT Client Unit Testing - Publish API Tests
*/
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness_c.h>
TEST_GROUP_C(PublishTests) {
TEST_GROUP_C_SETUP_WRAPPER(PublishTests)
TEST_GROUP_C_TEARDOWN_WRAPPER(PublishTests)
};
/* E:1 - Publish with Null/empty client instance */
TEST_GROUP_C_WRAPPER(PublishTests, PublishNullClient)
/* E:2 - Publish with Null/empty Topic Name */
TEST_GROUP_C_WRAPPER(PublishTests, PublishNullTopic)
/* E:3 - Publish with Null/empty payload */
TEST_GROUP_C_WRAPPER(PublishTests, PublishNullParams)
/* E:4 - Publish with network disconnected */
TEST_GROUP_C_WRAPPER(PublishTests, PublishNetworkDisconnected)
/* E:5 - Publish with QoS2 */
/* Not required here, enum value doesn't exist for QoS2 */
/* E:6 - Publish with QoS1 send success, Puback not received */
TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1FailureToReceivePuback)
/* E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout */
TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1FailureDelayedPuback)
/* E:8 - Publish with send success, Delayed Puback received before command timeout */
TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1Success10msDelayedPuback)
/* E:9 - Publish QoS0 success */
TEST_GROUP_C_WRAPPER(PublishTests, publishQoS0NoPubackSuccess)
/* E:10 - Publish with QoS1 send success, Puback received */
TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1Success)

View File

@@ -0,0 +1,205 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_publish_helper.c
* @brief IoT Client Unit Testing - Publish API Tests Helper
*/
#include <stdio.h>
#include <string.h>
#include <CppUTest/TestHarness_c.h>
#include "aws_iot_mqtt_client_interface.h"
#include "aws_iot_tests_unit_helper_functions.h"
#include "aws_iot_log.h"
static IoT_Client_Init_Params initParams;
static IoT_Client_Connect_Params connectParams;
static IoT_Publish_Message_Params testPubMsgParams;
static char subTopic[10] = "sdk/Test";
static uint16_t subTopicLen = 8;
static AWS_IoT_Client iotClient;
char cPayload[100];
TEST_GROUP_C_SETUP(PublishTests) {
IoT_Error_t rc = SUCCESS;
ResetTLSBuffer();
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
initParams.mqttCommandTimeout_ms = 2000;
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc);
testPubMsgParams.qos = QOS1;
testPubMsgParams.isRetained = 0;
sprintf(cPayload, "%s : %d ", "hello from SDK", 0);
testPubMsgParams.payload = (void *) cPayload;
testPubMsgParams.payloadLen = strlen(cPayload);
ResetTLSBuffer();
}
TEST_GROUP_C_TEARDOWN(PublishTests) { }
/* E:1 - Publish with Null/empty client instance */
TEST_C(PublishTests, PublishNullClient) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Publish Tests - E:1 - Publish with Null/empty client instance \n");
testPubMsgParams.qos = QOS1;
testPubMsgParams.isRetained = 0;
testPubMsgParams.payload = "Message";
testPubMsgParams.payloadLen = 7;
rc = aws_iot_mqtt_publish(NULL, "sdkTest/Sub", 11, &testPubMsgParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
IOT_DEBUG("-->Success - E:1 - Publish with Null/empty client instance \n");
}
/* E:2 - Publish with Null/empty Topic Name */
TEST_C(PublishTests, PublishNullTopic) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Publish Tests - E:2 - Publish with Null/empty Topic Name \n");
testPubMsgParams.qos = QOS1;
testPubMsgParams.isRetained = 0;
testPubMsgParams.payload = "Message";
testPubMsgParams.payloadLen = 7;
rc = aws_iot_mqtt_publish(&iotClient, NULL, 11, &testPubMsgParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 0, &testPubMsgParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
IOT_DEBUG("-->Success - E:2 - Publish with Null/empty Topic Name \n");
}
/* E:3 - Publish with Null/empty payload */
TEST_C(PublishTests, PublishNullParams) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Publish Tests - E:3 - Publish with Null/empty payload \n");
rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 11, NULL);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
testPubMsgParams.qos = QOS1;
testPubMsgParams.isRetained = 0;
testPubMsgParams.payload = NULL;
testPubMsgParams.payloadLen = 0;
rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 11, &testPubMsgParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
IOT_DEBUG("-->Success - E:3 - Publish with Null/empty payload \n");
}
/* E:4 - Publish with network disconnected */
TEST_C(PublishTests, PublishNetworkDisconnected) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Publish Tests - E:4 - Publish with network disconnected \n");
/* Ensure network is disconnected */
rc = aws_iot_mqtt_disconnect(&iotClient);
testPubMsgParams.qos = QOS1;
testPubMsgParams.isRetained = 0;
testPubMsgParams.payload = NULL;
testPubMsgParams.payloadLen = 0;
rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 11, &testPubMsgParams);
CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc);
IOT_DEBUG("-->Success - E:4 - Publish with network disconnected \n");
}
/* E:6 - Publish with QoS1 send success, Puback not received */
TEST_C(PublishTests, publishQoS1FailureToReceivePuback) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Publish Tests - E:6 - Publish with QoS1 send success, Puback not received \n");
rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams);
CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc);
IOT_DEBUG("-->Success - E:6 - Publish with QoS1 send success, Puback not received \n");
}
/* E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout */
TEST_C(PublishTests, publishQoS1FailureDelayedPuback) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Publish Tests - E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout \n");
setTLSRxBufferDelay(10, 0);
setTLSRxBufferForPuback();
rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams);
CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc);
IOT_DEBUG("-->Success - E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout \n");
}
/* E:8 - Publish with send success, Delayed Puback received before command timeout */
TEST_C(PublishTests, publishQoS1Success10msDelayedPuback) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Publish Tests - E:8 - Publish with send success, Delayed Puback received before command timeout \n");
ResetTLSBuffer();
setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2);
setTLSRxBufferForPuback();
rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("-->Success - E:8 - Publish with send success, Delayed Puback received before command timeout \n");
}
/* E:9 - Publish QoS0 success */
TEST_C(PublishTests, publishQoS0NoPubackSuccess) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Publish Tests - E:9 - Publish QoS0 success \n");
testPubMsgParams.qos = QOS0; // switch to a Qos0 PUB
rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("-->Success - E:9 - Publish QoS0 success \n");
}
/* E:10 - Publish with QoS1 send success, Puback received */
TEST_C(PublishTests, publishQoS1Success) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Publish Tests - E:10 - Publish with QoS1 send success, Puback received \n");
setTLSRxBufferForPuback();
rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("-->Success - E:10 - Publish with QoS1 send success, Puback received \n");
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_runner.cpp
* @brief IoT Client Unit Testing - Runner
*/
#include <CppUTest/CommandLineTestRunner.h>
int main(int ac, char **argv) {
return CommandLineTestRunner::RunAllTests(ac, argv);
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_shadow_action.cpp
* @brief IoT Client Unit Testing - Shadow Action Tests
*/
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness_c.h>
TEST_GROUP_C(ShadowActionTests) {
TEST_GROUP_C_SETUP_WRAPPER(ShadowActionTests)
TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowActionTests)
};
TEST_GROUP_C_WRAPPER(ShadowActionTests, GetTheFullJSONDocument)
TEST_GROUP_C_WRAPPER(ShadowActionTests, DeleteTheJSONDocument)
TEST_GROUP_C_WRAPPER(ShadowActionTests, UpdateTheJSONDocument)
TEST_GROUP_C_WRAPPER(ShadowActionTests, GetTheFullJSONDocumentTimeout)
TEST_GROUP_C_WRAPPER(ShadowActionTests, SubscribeToAcceptedRejectedOnGet)
TEST_GROUP_C_WRAPPER(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetResponse)
TEST_GROUP_C_WRAPPER(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeout)
TEST_GROUP_C_WRAPPER(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeoutWithSticky)
TEST_GROUP_C_WRAPPER(ShadowActionTests, WrongTokenInGetResponse)
TEST_GROUP_C_WRAPPER(ShadowActionTests, NoTokenInGetResponse)
TEST_GROUP_C_WRAPPER(ShadowActionTests, InvalidInboundJSONInGetResponse)
TEST_GROUP_C_WRAPPER(ShadowActionTests, AcceptedSubFailsGetRequest)
TEST_GROUP_C_WRAPPER(ShadowActionTests, RejectedSubFailsGetRequest)
TEST_GROUP_C_WRAPPER(ShadowActionTests, PublishFailsGetRequest)
TEST_GROUP_C_WRAPPER(ShadowActionTests, GetVersionFromAckStatus)
TEST_GROUP_C_WRAPPER(ShadowActionTests, StickyNonStickyNeverConflict)
TEST_GROUP_C_WRAPPER(ShadowActionTests, ACKWaitingMoreThanAllowed)
TEST_GROUP_C_WRAPPER(ShadowActionTests, InboundDataTooBigForBuffer)
TEST_GROUP_C_WRAPPER(ShadowActionTests, NoClientTokenForShadowAction)
TEST_GROUP_C_WRAPPER(ShadowActionTests, NoCallbackForShadowAction)

View File

@@ -0,0 +1,870 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_shadow_action_helper.c
* @brief IoT Client Unit Testing - Shadow Action API Tests Helper
*/
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <CppUTest/TestHarness_c.h>
#include <aws_iot_tests_unit_mock_tls_params.h>
#include "aws_iot_tests_unit_mock_tls_params.h"
#include "aws_iot_tests_unit_helper_functions.h"
#include "aws_iot_tests_unit_shadow_helper.h"
#include "aws_iot_shadow_interface.h"
#include "aws_iot_shadow_actions.h"
#include "aws_iot_shadow_json.h"
#include "aws_iot_log.h"
#define SIZE_OF_UPDATE_DOCUMENT 200
#define TEST_JSON_RESPONSE_FULL_DOCUMENT "{\"state\":{\"reported\":{\"sensor1\":98}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}"
#define TEST_JSON_RESPONSE_DELETE_DOCUMENT "{\"version\":2,\"timestamp\":1443473857,\"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}"
#define TEST_JSON_RESPONSE_UPDATE_DOCUMENT "{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}"
static AWS_IoT_Client client;
static IoT_Client_Connect_Params connectParams;
static IoT_Publish_Message_Params testPubMsgParams;
static ShadowInitParameters_t shadowInitParams;
static ShadowConnectParameters_t shadowConnectParams;
static Shadow_Ack_Status_t ackStatusRx;
static char jsonFullDocument[200];
static ShadowActions_t actionRx;
static void topicNameFromThingAndAction(char *pTopic, const char *pThingName, ShadowActions_t action) {
char actionBuf[10];
if(SHADOW_GET == action) {
strcpy(actionBuf, "get");
} else if(SHADOW_UPDATE == action) {
strcpy(actionBuf, "update");
} else if(SHADOW_DELETE == action) {
strcpy(actionBuf, "delete");
}
snprintf(pTopic, 100, "$aws/things/%s/shadow/%s", pThingName, actionBuf);
}
TEST_GROUP_C_SETUP(ShadowActionTests) {
IoT_Error_t ret_val = SUCCESS;
char cPayload[100];
char topic[120];
shadowInitParams.pHost = AWS_IOT_MQTT_HOST;
shadowInitParams.port = AWS_IOT_MQTT_PORT;
shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME;
shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME;
shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME;
shadowInitParams.disconnectHandler = NULL;
shadowInitParams.enableAutoReconnect = false;
ret_val = aws_iot_shadow_init(&client, &shadowInitParams);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME;
shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID;
shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
ret_val = aws_iot_shadow_connect(&client, &shadowConnectParams);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
setTLSRxBufferForPuback();
testPubMsgParams.qos = QOS1;
testPubMsgParams.isRetained = 0;
snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0);
testPubMsgParams.payload = (void *) cPayload;
testPubMsgParams.payloadLen = strlen(cPayload) + 1;
topicNameFromThingAndAction(topic, AWS_IOT_MY_THING_NAME, SHADOW_GET);
setTLSRxBufferForDoubleSuback(topic, strlen(topic), QOS1, testPubMsgParams);
}
TEST_GROUP_C_TEARDOWN(ShadowActionTests) {
/* Clean up. Not checking return code here because this is common to all tests.
* A test might have already caused a disconnect by this point.
*/
IoT_Error_t rc = aws_iot_shadow_disconnect(&client);
IOT_UNUSED(rc);
}
static void actionCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status,
const char *pReceivedJsonDocument, void *pContextData) {
IOT_UNUSED(pThingName);
IOT_UNUSED(pContextData);
IOT_DEBUG("%s", pReceivedJsonDocument);
actionRx = action;
ackStatusRx = status;
if(SHADOW_ACK_TIMEOUT != status) {
strcpy(jsonFullDocument, pReceivedJsonDocument);
}
}
// Happy path for Get, Update, Delete
TEST_C(ShadowActionTests, GetTheFullJSONDocument) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - Get full json document \n");
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
ResetTLSBuffer();
params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT);
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument);
CHECK_EQUAL_C_INT(SHADOW_GET, actionRx);
CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx);
IOT_DEBUG("-->Success - Get full json document \n");
}
TEST_C(ShadowActionTests, DeleteTheJSONDocument) {
IoT_Error_t ret_val = SUCCESS;
IoT_Publish_Message_Params params;
char deleteRequestJson[120];
IOT_DEBUG("-->Running Shadow Action Tests - Delete json document \n");
aws_iot_shadow_internal_delete_request_json(deleteRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_DELETE, deleteRequestJson, actionCallback,
NULL, 4, false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
params.payloadLen = strlen(TEST_JSON_RESPONSE_DELETE_DOCUMENT);
params.payload = TEST_JSON_RESPONSE_DELETE_DOCUMENT;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(DELETE_ACCEPTED_TOPIC, strlen(DELETE_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_DELETE_DOCUMENT, jsonFullDocument);
CHECK_EQUAL_C_INT(SHADOW_DELETE, actionRx);
CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx);
IOT_DEBUG("-->Success - Delete json document \n");
}
TEST_C(ShadowActionTests, UpdateTheJSONDocument) {
IoT_Error_t ret_val = SUCCESS;
char updateRequestJson[SIZE_OF_UPDATE_DOCUMENT];
char expectedUpdateRequestJson[SIZE_OF_UPDATE_DOCUMENT];
double doubleData = 4.0908f;
float floatData = 3.445f;
bool boolData = true;
jsonStruct_t dataFloatHandler;
jsonStruct_t dataDoubleHandler;
jsonStruct_t dataBoolHandler;
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - Update json document \n");
dataFloatHandler.cb = NULL;
dataFloatHandler.pData = &floatData;
dataFloatHandler.pKey = "floatData";
dataFloatHandler.type = SHADOW_JSON_FLOAT;
dataDoubleHandler.cb = NULL;
dataDoubleHandler.pData = &doubleData;
dataDoubleHandler.pKey = "doubleData";
dataDoubleHandler.type = SHADOW_JSON_DOUBLE;
dataBoolHandler.cb = NULL;
dataBoolHandler.pData = &boolData;
dataBoolHandler.pKey = "boolData";
dataBoolHandler.type = SHADOW_JSON_BOOL;
ret_val = aws_iot_shadow_init_json_document(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
ret_val = aws_iot_shadow_add_reported(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT, 2, &dataDoubleHandler,
&dataFloatHandler);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
ret_val = aws_iot_shadow_add_desired(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT, 1, &dataBoolHandler);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
ret_val = aws_iot_finalize_json_document(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
snprintf(expectedUpdateRequestJson, SIZE_OF_UPDATE_DOCUMENT,
"{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000},\"desired\":{\"boolData\":true}}, \"clientToken\":\"%s-0\"}",
AWS_IOT_MQTT_CLIENT_ID);
CHECK_EQUAL_C_STRING(expectedUpdateRequestJson, updateRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_UPDATE, updateRequestJson, actionCallback,
NULL, 4, false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
ResetTLSBuffer();
snprintf(jsonFullDocument, 200, "%s", "");
params.payloadLen = strlen(TEST_JSON_RESPONSE_UPDATE_DOCUMENT);
params.payload = TEST_JSON_RESPONSE_UPDATE_DOCUMENT;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(UPDATE_ACCEPTED_TOPIC, strlen(UPDATE_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_UPDATE_DOCUMENT, jsonFullDocument);
CHECK_EQUAL_C_INT(SHADOW_UPDATE, actionRx);
CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx);
IOT_DEBUG("-->Success - Update json document \n");
}
TEST_C(ShadowActionTests, GetTheFullJSONDocumentTimeout) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - Get full json document timeout \n");
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
sleep(4 + 1);
params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT);
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument);
CHECK_EQUAL_C_INT(SHADOW_GET, actionRx);
CHECK_EQUAL_C_INT(SHADOW_ACK_TIMEOUT, ackStatusRx);
IOT_DEBUG("-->Success - Get full json document timeout \n");
}
// Subscribe and UnSubscribe on reception of thing names. Will perform the test with Get operation
TEST_C(ShadowActionTests, SubscribeToAcceptedRejectedOnGet) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
uint8_t firstByte, secondByte;
uint16_t topicNameLen;
char topicName[128] = "test";
IOT_DEBUG("-->Running Shadow Action Tests - Subscribe to get/accepted and get/rejected \n");
lastSubscribeMsgLen = 11;
snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message");
secondLastSubscribeMsgLen = 11;
snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message");
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage);
CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage);
firstByte = (uint8_t)(TxBuffer.pBuffer[2]);
secondByte = (uint8_t)(TxBuffer.pBuffer[3]);
topicNameLen = (uint16_t) (secondByte + (256 * firstByte));
snprintf(topicName, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[4])); // Added one for null character
// Verify publish happens
CHECK_EQUAL_C_STRING(GET_PUB_TOPIC, topicName);
IOT_DEBUG("-->Success - Subscribe to get/accepted and get/rejected \n");
}
TEST_C(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetResponse) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - unsubscribe to get/accepted and get/rejected on response \n");
lastSubscribeMsgLen = 11;
snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message");
secondLastSubscribeMsgLen = 11;
snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message");
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT);
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage);
CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage);
IOT_DEBUG("-->Success - unsubscribe to get/accepted and get/rejected on response \n");
}
TEST_C(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeout) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - Unsubscribe to get/accepted and get/rejected on get timeout \n");
snprintf(jsonFullDocument, 200, "aa");
lastSubscribeMsgLen = 11;
snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message");
secondLastSubscribeMsgLen = 11;
snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message");
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
sleep(4 + 1);
params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT);
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING("aa", jsonFullDocument);
CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage);
CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage);
IOT_DEBUG("-->Success - Unsubscribe to get/accepted and get/rejected on get timeout \n");
}
TEST_C(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeoutWithSticky) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - No unsubscribe to get/accepted and get/rejected on get timeout with a sticky subscription \n");
snprintf(jsonFullDocument, 200, "timeout");
lastSubscribeMsgLen = 11;
snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message");
secondLastSubscribeMsgLen = 11;
snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message");
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
true);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
sleep(4 + 1);
ResetTLSBuffer();
params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT);
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING("timeout", jsonFullDocument);
CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage);
CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage);
IOT_DEBUG("-->Success - No unsubscribe to get/accepted and get/rejected on get timeout with a sticky subscription \n");
}
#define TEST_JSON_RESPONSE_FULL_DOCUMENT_WITH_VERSION(num) "{\"state\":{\"reported\":{\"sensor1\":98}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\",\"version\":" #num "}"
TEST_C(ShadowActionTests, GetVersionFromAckStatus) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IoT_Publish_Message_Params params2;
IOT_DEBUG("-->Running Shadow Action Tests - Get version from Ack status \n");
snprintf(jsonFullDocument, 200, "timeout");
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
true);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
ResetTLSBuffer();
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_WITH_VERSION(1);
params.payloadLen = strlen(params.payload);
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_C(1u == aws_iot_shadow_get_last_received_version());
ResetTLSBuffer();
params2.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_WITH_VERSION(132387);
params2.payloadLen = strlen(params2.payload);
params2.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params2,
params2.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_C(132387u == aws_iot_shadow_get_last_received_version());
IOT_DEBUG("-->Success - Get version from Ack status \n");
}
#define TEST_JSON_RESPONSE_FULL_DOCUMENT_ALWAYS_WRONG_TOKEN "{\"state\":{\"reported\":{\"sensor1\":98}}, \"clientToken\":\"TroubleToken1234\"}"
TEST_C(ShadowActionTests, WrongTokenInGetResponse) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - Wrong token in get response \n");
snprintf(jsonFullDocument, 200, "timeout");
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
sleep(4 + 1);
params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT_ALWAYS_WRONG_TOKEN);
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_ALWAYS_WRONG_TOKEN;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING("timeout", jsonFullDocument);
CHECK_EQUAL_C_INT(SHADOW_GET, actionRx);
CHECK_EQUAL_C_INT(SHADOW_ACK_TIMEOUT, ackStatusRx);
IOT_DEBUG("-->Success - Wrong token in get response \n");
}
#define TEST_JSON_RESPONSE_FULL_DOCUMENT_NO_TOKEN "{\"state\":{\"reported\":{\"sensor1\":98}}}"
TEST_C(ShadowActionTests, NoTokenInGetResponse) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - No token in get response \n");
snprintf(jsonFullDocument, 200, "timeout");
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
sleep(4 + 1);
params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT_NO_TOKEN);
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_NO_TOKEN;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING("timeout", jsonFullDocument);
CHECK_EQUAL_C_INT(SHADOW_GET, actionRx);
CHECK_EQUAL_C_INT(SHADOW_ACK_TIMEOUT, ackStatusRx);
IOT_DEBUG("-->Success - No token in get response \n");
}
TEST_C(ShadowActionTests, InvalidInboundJSONInGetResponse) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - Invalid inbound json in get response \n");
snprintf(jsonFullDocument, 200, "NOT_VISITED");
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
params.payloadLen = strlen("{\"state\":{{");
params.payload = "{\"state\":{{";
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument);
IOT_DEBUG("-->Success - Invalid inbound json in get response \n");
}
TEST_C(ShadowActionTests, AcceptedSubFailsGetRequest) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - Accepted sub fails get request \n");
snprintf(jsonFullDocument, 200, "NOT_SENT");
ResetTLSBuffer();
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, ret_val); // Should never subscribe and publish
ResetTLSBuffer();
params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT);
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING("NOT_SENT", jsonFullDocument); // Never called callback
IOT_DEBUG("-->Success - Accepted sub fails get request \n");
}
TEST_C(ShadowActionTests, RejectedSubFailsGetRequest) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - Rejected sub fails get request \n");
snprintf(jsonFullDocument, 200, "NOT_SENT");
params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT);
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT;
params.qos = QOS0;
ResetTLSBuffer();
setTLSRxBufferForSuback(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params);
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, ret_val); // Should never subscribe and publish
ResetTLSBuffer();
setTLSRxBufferWithMsgOnSubscribedTopic(GET_REJECTED_TOPIC, strlen(GET_REJECTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING("NOT_SENT", jsonFullDocument); // Never called callback
IOT_DEBUG("-->Success - Rejected sub fails get request \n");
}
TEST_C(ShadowActionTests, PublishFailsGetRequest) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - publish fails on get request \n");
snprintf(jsonFullDocument, 200, "NOT_SENT");
ResetTLSBuffer();
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, ret_val); // Should never subscribe and publish
ResetTLSBuffer();
params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT);
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING("NOT_SENT", jsonFullDocument); // Never called callback
IOT_DEBUG("-->Success - publish fails on get request \n");
}
TEST_C(ShadowActionTests, StickyNonStickyNeverConflict) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - Sticky and non-sticky subscriptions do not conflict \n");
lastSubscribeMsgLen = 11;
snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message");
secondLastSubscribeMsgLen = 11;
snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message");
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
true);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT);
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument);
CHECK_EQUAL_C_INT(SHADOW_GET, actionRx);
CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx);
lastSubscribeMsgLen = 11;
snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message");
secondLastSubscribeMsgLen = 11;
snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message");
// Non-sticky shadow get, same thing name. Should never unsub since they are sticky
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
ResetTLSBuffer();
params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT);
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument);
CHECK_EQUAL_C_INT(SHADOW_GET, actionRx);
CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx);
CHECK_EQUAL_C_STRING("No Message", LastSubscribeMessage);
CHECK_EQUAL_C_STRING("No Message", SecondLastSubscribeMessage);
IOT_DEBUG("-->Success - Sticky and non-sticky subscriptions do not conflict \n");
}
TEST_C(ShadowActionTests, ACKWaitingMoreThanAllowed) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IOT_DEBUG("-->Running Shadow Action Tests - Ack waiting more than allowed wait time \n");
// 1st
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL,
100, false); // 100 sec to timeout
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
// 2nd
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL,
100, false); // 100 sec to timeout
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
// 3rd
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL,
100, false); // 100 sec to timeout
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
// 4th
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL,
100, false); // 100 sec to timeout
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
// 5th
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL,
100, false); // 100 sec to timeout
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
// 6th
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL,
100, false); // 100 sec to timeout
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
// 7th
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL,
100, false); // 100 sec to timeout
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
// 8th
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL,
100, false); // 100 sec to timeout
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
// 9th
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL,
100, false); // 100 sec to timeout
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
// 10th
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL,
100, false); // 100 sec to timeout
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
// 11th
// Should return some error code, since we are running out of ACK space
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL,
100, false); // 100 sec to timeout
CHECK_EQUAL_C_INT(FAILURE, ret_val);
IOT_DEBUG("-->Success - Ack waiting more than allowed wait time \n");
}
#define JSON_SIZE_OVERFLOW "{\"state\":{\"reported\":{\"file\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}"
TEST_C(ShadowActionTests, InboundDataTooBigForBuffer) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
IOT_DEBUG("-->Running Shadow Action Tests - Inbound data too big for buffer \n");
snprintf(jsonFullDocument, 200, "NOT_VISITED");
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
params.payloadLen = strlen(JSON_SIZE_OVERFLOW);
params.payload = JSON_SIZE_OVERFLOW;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(MQTT_RX_BUFFER_TOO_SHORT_ERROR, ret_val);
CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument);
IOT_DEBUG("-->Success - Inbound data too big for buffer \n");
}
#define TEST_JSON_RESPONSE_NO_TOKEN "{\"state\":{\"reported\":{\"sensor1\":98}}}"
TEST_C(ShadowActionTests, NoClientTokenForShadowAction) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
uint8_t firstByte, secondByte;
uint16_t topicNameLen;
char topicName[128] = "test";
IOT_DEBUG("-->Running Shadow Action Tests - No client token for shadow action \n");
snprintf(getRequestJson, 120, "{}");
snprintf(jsonFullDocument, 200, "NOT_VISITED");
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, actionCallback, NULL, 4,
false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
params.payloadLen = strlen(TEST_JSON_RESPONSE_NO_TOKEN);
params.payload = TEST_JSON_RESPONSE_NO_TOKEN;
params.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
// Should never subscribe to accepted/rejected topics since we have no token to track the response
CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument);
firstByte = (uint8_t)(TxBuffer.pBuffer[2]);
secondByte = (uint8_t)(TxBuffer.pBuffer[3]);
topicNameLen = (uint16_t) (secondByte + (256 * firstByte));
snprintf(topicName, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[4])); // Added one for null character
// Verify publish happens
CHECK_EQUAL_C_STRING(GET_PUB_TOPIC, topicName);
IOT_DEBUG("-->Success - No client token for shadow action \n");
}
TEST_C(ShadowActionTests, NoCallbackForShadowAction) {
IoT_Error_t ret_val = SUCCESS;
char getRequestJson[120];
IoT_Publish_Message_Params params;
uint8_t firstByte, secondByte;
uint16_t topicNameLen;
char topicName[128] = "test";
IOT_DEBUG("-->Running Shadow Action Tests - No callback for shadow action \n");
snprintf(jsonFullDocument, 200, "NOT_VISITED");
aws_iot_shadow_internal_get_request_json(getRequestJson);
ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, NULL, NULL, 4, false);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT);
params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT;
setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params,
params.payload);
ret_val = aws_iot_shadow_yield(&client, 200);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
// Should never subscribe to accepted/rejected topics since we have no callback to track the response
CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument);
firstByte = (uint8_t)(TxBuffer.pBuffer[2]);
secondByte = (uint8_t)(TxBuffer.pBuffer[3]);
topicNameLen = (uint16_t) (secondByte + (256 * firstByte));
snprintf(topicName, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[4])); // Added one for null character
// Verify publish happens
CHECK_EQUAL_C_STRING(GET_PUB_TOPIC, topicName);
IOT_DEBUG("-->Success - No callback for shadow action");
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_shadow_delta.cpp
* @brief IoT Client Unit Testing - Shadow Delta Tests
*/
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness_c.h>
TEST_GROUP_C(ShadowDeltaTest){
TEST_GROUP_C_SETUP_WRAPPER(ShadowDeltaTest)
TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowDeltaTest)
};
TEST_GROUP_C_WRAPPER(ShadowDeltaTest, registerDeltaSuccess)
TEST_GROUP_C_WRAPPER(ShadowDeltaTest, registerDeltaInt)
TEST_GROUP_C_WRAPPER(ShadowDeltaTest, registerDeltaIntNoCallback)
TEST_GROUP_C_WRAPPER(ShadowDeltaTest, DeltaNestedObject)
TEST_GROUP_C_WRAPPER(ShadowDeltaTest, DeltaVersionIgnoreOldVersion)

View File

@@ -0,0 +1,319 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_shadow_delta_helper.c
* @brief IoT Client Unit Testing - Shadow Delta Tests Helper
*/
#include <string.h>
#include <stdio.h>
#include <CppUTest/TestHarness_c.h>
#include "aws_iot_shadow_interface.h"
#include "aws_iot_tests_unit_helper_functions.h"
#include "aws_iot_log.h"
static AWS_IoT_Client client;
static IoT_Client_Connect_Params connectParams;
static ShadowInitParameters_t shadowInitParams;
static ShadowConnectParameters_t shadowConnectParams;
static char receivedNestedObject[100] = "";
static char sentNestedObjectData[100] = "{\"sensor1\":23}";
static char shadowDeltaTopic[MAX_SHADOW_TOPIC_LENGTH_BYTES];
#define SHADOW_DELTA_UPDATE "$aws/things/%s/shadow/update/delta"
#undef AWS_IOT_MY_THING_NAME
#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK"
void genericCallback(const char *pJsonStringData, uint32_t JsonStringDataLen, jsonStruct_t *pContext) {
printf("\nkey[%s]==Data[%.*s]\n", pContext->pKey, JsonStringDataLen, pJsonStringData);
}
void nestedObjectCallback(const char *pJsonStringData, uint32_t JsonStringDataLen, jsonStruct_t *pContext) {
printf("\nkey[%s]==Data[%.*s]\n", pContext->pKey, JsonStringDataLen, pJsonStringData);
snprintf(receivedNestedObject, 100, "%.*s", JsonStringDataLen, pJsonStringData);
}
TEST_GROUP_C_SETUP(ShadowDeltaTest) {
IoT_Error_t ret_val = SUCCESS;
shadowInitParams.pHost = AWS_IOT_MQTT_HOST;
shadowInitParams.port = AWS_IOT_MQTT_PORT;
shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME;
shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME;
shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME;
shadowInitParams.disconnectHandler = NULL;
shadowInitParams.enableAutoReconnect = false;
ret_val = aws_iot_shadow_init(&client, &shadowInitParams);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME;
shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID;
shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
ret_val = aws_iot_shadow_connect(&client, &shadowConnectParams);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
snprintf(shadowDeltaTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, SHADOW_DELTA_UPDATE, AWS_IOT_MY_THING_NAME);
}
TEST_GROUP_C_TEARDOWN(ShadowDeltaTest) {
}
TEST_C(ShadowDeltaTest, registerDeltaSuccess) {
jsonStruct_t windowHandler;
char deltaJSONString[] = "{\"state\":{\"delta\":{\"window\":true}},\"version\":1}";
bool windowOpenData = false;
IoT_Publish_Message_Params params;
IoT_Error_t ret_val = SUCCESS;
IOT_DEBUG("\n-->Running Shadow Delta Tests - Register delta success \n");
windowHandler.cb = genericCallback;
windowHandler.pKey = "window";
windowHandler.type = SHADOW_JSON_BOOL;
windowHandler.pData = &windowOpenData;
params.payloadLen = strlen(deltaJSONString);
params.payload = deltaJSONString;
params.qos = QOS0;
ResetTLSBuffer();
setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params);
ret_val = aws_iot_shadow_register_delta(&client, &windowHandler);
ResetTLSBuffer();
setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload);
ret_val = aws_iot_shadow_yield(&client, 3000);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_INT(true, windowOpenData);
}
TEST_C(ShadowDeltaTest, registerDeltaInt) {
IoT_Error_t ret_val = SUCCESS;
jsonStruct_t intHandler;
int intData = 0;
char deltaJSONString[] = "{\"state\":{\"delta\":{\"length\":23}},\"version\":1}";
IoT_Publish_Message_Params params;
IOT_DEBUG("\n-->Running Shadow Delta Tests - Register delta integer \n");
intHandler.cb = genericCallback;
intHandler.pKey = "length";
intHandler.type = SHADOW_JSON_INT32;
intHandler.pData = &intData;
params.payloadLen = strlen(deltaJSONString);
params.payload = deltaJSONString;
params.qos = QOS0;
ResetTLSBuffer();
setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params);
ret_val = aws_iot_shadow_register_delta(&client, &intHandler);
ResetTLSBuffer();
setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload);
aws_iot_shadow_yield(&client, 3000);
CHECK_EQUAL_C_INT(23, intData);
}
TEST_C(ShadowDeltaTest, registerDeltaIntNoCallback) {
IoT_Error_t ret_val = SUCCESS;
jsonStruct_t intHandler;
int intData = 0;
char deltaJSONString[] = "{\"state\":{\"delta\":{\"length_nocb\":23}},\"version\":1}";
IoT_Publish_Message_Params params;
IOT_DEBUG("\n-->Running Shadow Delta Tests - Register delta integer with no callback \n");
intHandler.cb = NULL;
intHandler.pKey = "length_nocb";
intHandler.type = SHADOW_JSON_INT32;
intHandler.pData = &intData;
params.payloadLen = strlen(deltaJSONString);
params.payload = deltaJSONString;
params.qos = QOS0;
ResetTLSBuffer();
setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params);
ret_val = aws_iot_shadow_register_delta(&client, &intHandler);
ResetTLSBuffer();
setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload);
aws_iot_shadow_yield(&client, 3000);
CHECK_EQUAL_C_INT(23, intData);
}
TEST_C(ShadowDeltaTest, DeltaNestedObject) {
IoT_Error_t ret_val = SUCCESS;
IoT_Publish_Message_Params params;
jsonStruct_t nestedObjectHandler;
char nestedObject[100];
char deltaJSONString[100];
printf("\n-->Running Shadow Delta Tests - Delta received with nested object \n");
nestedObjectHandler.cb = nestedObjectCallback;
nestedObjectHandler.pKey = "sensors";
nestedObjectHandler.type = SHADOW_JSON_OBJECT;
nestedObjectHandler.pData = &nestedObject;
snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":1}", nestedObjectHandler.pKey,
sentNestedObjectData);
params.payloadLen = strlen(deltaJSONString);
params.payload = deltaJSONString;
params.qos = QOS0;
ResetTLSBuffer();
setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params);
ret_val = aws_iot_shadow_register_delta(&client, &nestedObjectHandler);
ResetTLSBuffer();
setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload);
aws_iot_shadow_yield(&client, 3000);
CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject);
}
// Send back to back version and ensure a wrong version is ignored with old message enabled
TEST_C(ShadowDeltaTest, DeltaVersionIgnoreOldVersion) {
IoT_Error_t ret_val = SUCCESS;
char deltaJSONString[100];
jsonStruct_t nestedObjectHandler;
char nestedObject[100];
IoT_Publish_Message_Params params;
printf("\n-->Running Shadow Delta Tests - delta received, old version ignored \n");
nestedObjectHandler.cb = nestedObjectCallback;
nestedObjectHandler.pKey = "sensors";
nestedObjectHandler.type = SHADOW_JSON_OBJECT;
nestedObjectHandler.pData = &nestedObject;
snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":1}", nestedObjectHandler.pKey,
sentNestedObjectData);
params.payloadLen = strlen(deltaJSONString);
params.payload = deltaJSONString;
params.qos = QOS0;
ResetTLSBuffer();
setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params);
ret_val = aws_iot_shadow_register_delta(&client, &nestedObjectHandler);
ResetTLSBuffer();
setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload);
aws_iot_shadow_yield(&client, 100);
CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject);
snprintf(receivedNestedObject, 100, " ");
snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":2}", nestedObjectHandler.pKey,
sentNestedObjectData);
params.payloadLen = strlen(deltaJSONString);
params.payload = deltaJSONString;
params.qos = QOS0;
ResetTLSBuffer();
setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload);
aws_iot_shadow_yield(&client, 100);
CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject);
snprintf(receivedNestedObject, 100, " ");
snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":2}", nestedObjectHandler.pKey,
sentNestedObjectData);
params.payloadLen = strlen(deltaJSONString);
params.payload = deltaJSONString;
params.qos = QOS0;
ResetTLSBuffer();
setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload);
aws_iot_shadow_yield(&client, 100);
CHECK_EQUAL_C_STRING(" ", receivedNestedObject);
snprintf(receivedNestedObject, 100, " ");
snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey,
sentNestedObjectData);
params.payloadLen = strlen(deltaJSONString);
params.payload = deltaJSONString;
params.qos = QOS0;
ResetTLSBuffer();
setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload);
aws_iot_shadow_yield(&client, 100);
CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject);
aws_iot_shadow_reset_last_received_version();
snprintf(receivedNestedObject, 100, " ");
snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey,
sentNestedObjectData);
params.payloadLen = strlen(deltaJSONString);
params.payload = deltaJSONString;
params.qos = QOS0;
ResetTLSBuffer();
setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload);
aws_iot_shadow_yield(&client, 100);
CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject);
snprintf(receivedNestedObject, 100, " ");
snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey,
sentNestedObjectData);
params.payloadLen = strlen(deltaJSONString);
params.payload = deltaJSONString;
params.qos = QOS0;
ResetTLSBuffer();
setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload);
aws_iot_shadow_yield(&client, 100);
CHECK_EQUAL_C_STRING(" ", receivedNestedObject);
aws_iot_shadow_disable_discard_old_delta_msgs();
snprintf(receivedNestedObject, 100, " ");
snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey,
sentNestedObjectData);
params.payloadLen = strlen(deltaJSONString);
params.payload = deltaJSONString;
params.qos = QOS0;
ResetTLSBuffer();
setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload);
aws_iot_shadow_yield(&client, 100);
CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject);
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_shadow_json_builder.cpp
* @brief IoT Client Unit Testing - Shadow JSON Builder Tests
*/
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness_c.h>
TEST_GROUP_C(ShadowJsonBuilderTests){
TEST_GROUP_C_SETUP_WRAPPER(ShadowJsonBuilderTests)
TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowJsonBuilderTests)
};
TEST_GROUP_C_WRAPPER(ShadowJsonBuilderTests, UpdateTheJSONDocumentBuilder)
TEST_GROUP_C_WRAPPER(ShadowJsonBuilderTests, PassingNullValue)
TEST_GROUP_C_WRAPPER(ShadowJsonBuilderTests, SmallBuffer)

View File

@@ -0,0 +1,129 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_shadow_json_builder_helper.c
* @brief IoT Client Unit Testing - Shadow JSON Builder Tests Helper
*/
#include <string.h>
#include <CppUTest/TestHarness_c.h>
#include <aws_iot_shadow_interface.h>
#include "aws_iot_shadow_actions.h"
#include "aws_iot_log.h"
#include "aws_iot_tests_unit_helper_functions.h"
static jsonStruct_t dataFloatHandler;
static jsonStruct_t dataDoubleHandler;
static double doubleData = 4.0908f;
static float floatData = 3.445f;
static AWS_IoT_Client iotClient;
static IoT_Client_Connect_Params connectParams;
static ShadowInitParameters_t shadowInitParams;
static ShadowConnectParameters_t shadowConnectParams;
TEST_GROUP_C_SETUP(ShadowJsonBuilderTests) {
IoT_Error_t ret_val;
shadowInitParams.pHost = AWS_IOT_MQTT_HOST;
shadowInitParams.port = AWS_IOT_MQTT_PORT;
shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME;
shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME;
shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME;
shadowInitParams.disconnectHandler = NULL;
shadowInitParams.enableAutoReconnect = false;
ret_val = aws_iot_shadow_init(&iotClient, &shadowInitParams);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME;
shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID;
shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
ret_val = aws_iot_shadow_connect(&iotClient, &shadowConnectParams);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
dataFloatHandler.cb = NULL;
dataFloatHandler.pData = &floatData;
dataFloatHandler.pKey = "floatData";
dataFloatHandler.type = SHADOW_JSON_FLOAT;
dataDoubleHandler.cb = NULL;
dataDoubleHandler.pData = &doubleData;
dataDoubleHandler.pKey = "doubleData";
dataDoubleHandler.type = SHADOW_JSON_DOUBLE;
}
TEST_GROUP_C_TEARDOWN(ShadowJsonBuilderTests) {
/* Clean up. Not checking return code here because this is common to all tests.
* A test might have already caused a disconnect by this point.
*/
IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient);
IOT_UNUSED(rc);
}
#define TEST_JSON_RESPONSE_UPDATE_DOCUMENT "{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}"
#define SIZE_OF_UPFATE_BUF 200
TEST_C(ShadowJsonBuilderTests, UpdateTheJSONDocumentBuilder) {
IoT_Error_t ret_val;
char updateRequestJson[SIZE_OF_UPFATE_BUF];
size_t jsonBufSize = sizeof(updateRequestJson) / sizeof(updateRequestJson[0]);
IOT_DEBUG("\n-->Running Shadow Json Builder Tests - Update the Json document builder \n");
ret_val = aws_iot_shadow_init_json_document(updateRequestJson, jsonBufSize);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
ret_val = aws_iot_shadow_add_reported(updateRequestJson, jsonBufSize, 2, &dataDoubleHandler, &dataFloatHandler);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
ret_val = aws_iot_finalize_json_document(updateRequestJson, jsonBufSize);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_UPDATE_DOCUMENT, updateRequestJson);
}
TEST_C(ShadowJsonBuilderTests, PassingNullValue) {
IoT_Error_t ret_val;
IOT_DEBUG("\n-->Running Shadow Json Builder Tests - Passing Null value to Shadow json builder \n");
ret_val = aws_iot_shadow_init_json_document(NULL, SIZE_OF_UPFATE_BUF);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val);
ret_val = aws_iot_shadow_add_reported(NULL, SIZE_OF_UPFATE_BUF, 2, &dataDoubleHandler, &dataFloatHandler);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val);
ret_val = aws_iot_shadow_add_desired(NULL, SIZE_OF_UPFATE_BUF, 2, &dataDoubleHandler, &dataFloatHandler);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val);
ret_val = aws_iot_finalize_json_document(NULL, SIZE_OF_UPFATE_BUF);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val);
}
TEST_C(ShadowJsonBuilderTests, SmallBuffer) {
IoT_Error_t ret_val;
char updateRequestJson[14];
size_t jsonBufSize = sizeof(updateRequestJson) / sizeof(updateRequestJson[0]);
IOT_DEBUG("\n-->Running Shadow Json Builder Tests - Json Buffer is too small \n");
ret_val = aws_iot_shadow_init_json_document(updateRequestJson, jsonBufSize);
CHECK_EQUAL_C_INT(SUCCESS, ret_val);
ret_val = aws_iot_shadow_add_reported(updateRequestJson, jsonBufSize, 2, &dataDoubleHandler, &dataFloatHandler);
CHECK_EQUAL_C_INT(SHADOW_JSON_BUFFER_TRUNCATED, ret_val);
ret_val = aws_iot_shadow_add_desired(updateRequestJson, jsonBufSize, 2, &dataDoubleHandler, &dataFloatHandler);
CHECK_EQUAL_C_INT(SHADOW_JSON_ERROR, ret_val);
ret_val = aws_iot_finalize_json_document(updateRequestJson, jsonBufSize);
CHECK_EQUAL_C_INT(SHADOW_JSON_ERROR, ret_val);
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_shadow_null_fields.cpp
* @brief IoT Client Unit Testing - Shadow APIs NULL field Tests
*/
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness_c.h>
TEST_GROUP_C(ShadowNullFields){
TEST_GROUP_C_SETUP_WRAPPER(ShadowNullFields)
TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowNullFields)
};
TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientInit)
TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientConnect)
TEST_GROUP_C_WRAPPER(ShadowNullFields, NullHost)
TEST_GROUP_C_WRAPPER(ShadowNullFields, NullPort)
TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientID)
TEST_GROUP_C_WRAPPER(ShadowNullFields, NullUpdateDocument)
TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientYield)
TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientDisconnect)
TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientShadowGet)
TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientShadowUpdate)
TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientShadowDelete)
TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientSetAutoreconnect)

View File

@@ -0,0 +1,148 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_shadow_null_fields_helper.c
* @brief IoT Client Unit Testing - Shadow APIs NULL field Tests helper
*/
#include <stdio.h>
#include <string.h>
#include <CppUTest/TestHarness_c.h>
#include <aws_iot_shadow_interface.h>
#include "aws_iot_tests_unit_helper_functions.h"
#include "aws_iot_shadow_interface.h"
#include "aws_iot_shadow_actions.h"
#include "aws_iot_log.h"
static AWS_IoT_Client client;
static ShadowInitParameters_t shadowInitParams;
static ShadowConnectParameters_t shadowConnectParams;
static Shadow_Ack_Status_t ackStatusRx;
static ShadowActions_t actionRx;
static char jsonFullDocument[200];
void actionCallbackNullTest(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status,
const char *pReceivedJsonDocument, void *pContextData) {
IOT_UNUSED(pThingName);
IOT_UNUSED(pContextData);
IOT_DEBUG("%s", pReceivedJsonDocument);
actionRx = action;
ackStatusRx = status;
if(status != SHADOW_ACK_TIMEOUT) {
strcpy(jsonFullDocument, pReceivedJsonDocument);
}
}
TEST_GROUP_C_SETUP(ShadowNullFields) {
ResetTLSBuffer();
}
TEST_GROUP_C_TEARDOWN(ShadowNullFields) { }
TEST_C(ShadowNullFields, NullHost) {
shadowInitParams.pHost = NULL;
shadowInitParams.port = AWS_IOT_MQTT_PORT;
IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
TEST_C(ShadowNullFields, NullPort) {
shadowInitParams.pHost = AWS_IOT_MQTT_HOST;
shadowInitParams.port = 0;
IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
TEST_C(ShadowNullFields, NullClientID) {
shadowInitParams.pHost = AWS_IOT_MQTT_HOST;
shadowInitParams.port = AWS_IOT_MQTT_PORT;
shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME;
shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME;
shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME;
shadowInitParams.disconnectHandler = NULL;
shadowInitParams.enableAutoReconnect = false;
IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME;
shadowConnectParams.pMqttClientId = NULL;
rc = aws_iot_shadow_connect(&client, &shadowConnectParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
TEST_C(ShadowNullFields, NullClientInit) {
shadowInitParams.pHost = AWS_IOT_MQTT_HOST;
shadowInitParams.port = AWS_IOT_MQTT_PORT;
IoT_Error_t rc = aws_iot_shadow_init(NULL, &shadowInitParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
TEST_C(ShadowNullFields, NullClientConnect) {
shadowInitParams.pHost = AWS_IOT_MQTT_HOST;
shadowInitParams.port = AWS_IOT_MQTT_PORT;
shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME;
shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME;
shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME;
shadowInitParams.disconnectHandler = NULL;
shadowInitParams.enableAutoReconnect = false;
IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME;
shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID;
shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID);
rc = aws_iot_shadow_connect(NULL, &shadowConnectParams);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
TEST_C(ShadowNullFields, NullUpdateDocument) {
IoT_Error_t rc = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_UPDATE, NULL, actionCallbackNullTest,
NULL, 4, false);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
TEST_C(ShadowNullFields, NullClientYield) {
IoT_Error_t rc = aws_iot_shadow_yield(NULL, 1000);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
TEST_C(ShadowNullFields, NullClientDisconnect) {
IoT_Error_t rc = aws_iot_shadow_disconnect(NULL);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
TEST_C(ShadowNullFields, NullClientShadowGet) {
IoT_Error_t rc = aws_iot_shadow_get(NULL, AWS_IOT_MY_THING_NAME, actionCallbackNullTest, NULL, 100, true);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
TEST_C(ShadowNullFields, NullClientShadowUpdate) {
IoT_Error_t rc = aws_iot_shadow_update(NULL, AWS_IOT_MY_THING_NAME, jsonFullDocument,
actionCallbackNullTest, NULL, 100, true);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
TEST_C(ShadowNullFields, NullClientShadowDelete) {
IoT_Error_t rc = aws_iot_shadow_delete(NULL, AWS_IOT_MY_THING_NAME, actionCallbackNullTest, NULL, 100, true);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
TEST_C(ShadowNullFields, NullClientSetAutoreconnect) {
IoT_Error_t rc = aws_iot_shadow_set_autoreconnect_status(NULL, true);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_subscribe.cpp
* @brief IoT Client Unit Testing - Subscribe API Tests
*/
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness_c.h>
TEST_GROUP_C(SubscribeTests){
TEST_GROUP_C_SETUP_WRAPPER(SubscribeTests)
TEST_GROUP_C_TEARDOWN_WRAPPER(SubscribeTests)
};
/* C:1 - Subscribe with Null/empty Client Instance */
TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullClient)
/* C:2 - Subscribe with Null/empty Topic Name */
TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullTopic)
/* C:3 - Subscribe with Null client callback */
TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullSubscribeHandler)
/* C:4 - Subscribe with Null client callback data */
TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullSubscribeHandlerData)
/* C:5 - Subscribe with no connection */
TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNoConnection)
/* C:6 - Subscribe QoS2, error */
/* Not required, QoS enum doesn't have value for QoS2 */
/* C:7 - Subscribe attempt, QoS0, no response timeout */
TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0FailureOnNoSuback)
/* C:8 - Subscribe attempt, QoS1, no response timeout */
TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1FailureOnNoSuback)
/* C:9 - Subscribe QoS0 success, suback received */
TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0Success)
/* C:10 - Subscribe QoS1 success, suback received */
TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1Success)
/* C:11 - Subscribe, QoS0, delayed suback, success */
TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0WithDelayedSubackSuccess)
/* C:12 - Subscribe, QoS1, delayed suback, success */
TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1WithDelayedSubackSuccess)
/* C:13 - Subscribe QoS0 success, no puback sent on message */
TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0MsgReceivedAndNoPubackSent)
/* C:14 - Subscribe QoS1 success, puback sent on message */
TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1MsgReceivedAndSendPuback)
/* C:15 - Subscribe, malformed response */
TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeMalformedResponse)
/* C:16 - Subscribe, multiple topics, messages on each topic */
TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeToMultipleTopicsSuccess)
/* C:17 - Subscribe, max topics, messages on each topic */
TEST_GROUP_C_WRAPPER(SubscribeTests, SubcribeToMaxAllowedTopicsSuccess)
/* C:18 - Subscribe, max topics, another subscribe */
TEST_GROUP_C_WRAPPER(SubscribeTests, SubcribeToMaxPlusOneAllowedTopicsFailure)
/* C:19 - Subscribe, '#' not last character in topic name, Failure */
TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicWithHashkeyAllSubTopicSuccess)
/* C:20 - Subscribe with '#', subscribed to all subtopics */
TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicHashkeyMustBeTheLastFail)
/* C:21 - Subscribe with '+' as wildcard success */
TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicWithPluskeySuccess)
/* C:22 - Subscribe with '+' as last character in topic name, Success */
TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicPluskeyComesLastSuccess)

View File

@@ -0,0 +1,606 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_subscribe_helper.c
* @brief IoT Client Unit Testing - Subscribe API Tests Helper
*/
#include <stdio.h>
#include <string.h>
#include <CppUTest/TestHarness_c.h>
#include "aws_iot_tests_unit_helper_functions.h"
#include "aws_iot_log.h"
static IoT_Client_Init_Params initParams;
static IoT_Client_Connect_Params connectParams;
static IoT_Publish_Message_Params testPubMsgParams;
static char subTopic[10] = "sdk/Test";
static uint16_t subTopicLen = 8;
static AWS_IoT_Client iotClient;
static char CallbackMsgString[100];
char cPayload[100];
static char CallbackMsgString1[100] = {"XXXX"};
static char CallbackMsgString2[100] = {"XXXX"};
static char CallbackMsgString3[100] = {"XXXX"};
static char CallbackMsgString4[100] = {"XXXX"};
static char CallbackMsgString5[100] = {"XXXX"};
static char CallbackMsgString6[100] = {"XXXX"};
static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName,
uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) {
if(NULL == pClient || NULL == topicName || 0 == topicNameLen) {
return;
}
IOT_UNUSED(pData);
char *tmp = params->payload;
unsigned int i;
for(i = 0; i < (params->payloadLen); i++) {
CallbackMsgString[i] = tmp[i];
}
}
static void iot_subscribe_callback_handler1(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
if(NULL == pClient || NULL == topicName || 0 == topicNameLen) {
return;
}
IOT_UNUSED(pData);
char *tmp = params->payload;
unsigned int i;
printf("callback topic %s\n", topicName);
for(i = 0; i < (params->payloadLen); i++) {
CallbackMsgString1[i] = tmp[i];
}
}
static void iot_subscribe_callback_handler2(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
if(NULL == pClient || NULL == topicName || 0 == topicNameLen) {
return;
}
IOT_UNUSED(pData);
char *tmp = params->payload;
unsigned int i;
for(i = 0; i < (params->payloadLen); i++) {
CallbackMsgString2[i] = tmp[i];
}
}
static void iot_subscribe_callback_handler3(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
if(NULL == pClient || NULL == topicName || 0 == topicNameLen) {
return;
}
IOT_UNUSED(pData);
char *tmp = params->payload;
unsigned int i;
for(i = 0; i < (params->payloadLen); i++) {
CallbackMsgString3[i] = tmp[i];
}
}
static void iot_subscribe_callback_handler4(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
if(NULL == pClient || NULL == topicName || 0 == topicNameLen) {
return;
}
IOT_UNUSED(pData);
char *tmp = params->payload;
unsigned int i;
for(i = 0; i < (params->payloadLen); i++) {
CallbackMsgString4[i] = tmp[i];
}
}
static void iot_subscribe_callback_handler5(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
if(NULL == pClient || NULL == topicName || 0 == topicNameLen) {
return;
}
IOT_UNUSED(pData);
char *tmp = params->payload;
unsigned int i;
for(i = 0; i < (params->payloadLen); i++) {
CallbackMsgString5[i] = tmp[i];
}
}
static void iot_subscribe_callback_handler6(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
if(NULL == pClient || NULL == topicName || 0 == topicNameLen) {
return;
}
IOT_UNUSED(pData);
char *tmp = params->payload;
unsigned int i;
for(i = 0; i < (params->payloadLen); i++) {
CallbackMsgString6[i] = tmp[i];
}
}
TEST_GROUP_C_SETUP(SubscribeTests) {
IoT_Error_t rc;
ResetTLSBuffer();
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
initParams.mqttCommandTimeout_ms = 2000;
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc);
testPubMsgParams.qos = QOS1;
testPubMsgParams.isRetained = 0;
snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0);
testPubMsgParams.payload = (void *) cPayload;
testPubMsgParams.payloadLen = strlen(cPayload);
ResetTLSBuffer();
}
TEST_GROUP_C_TEARDOWN(SubscribeTests) { }
/* C:1 - Subscribe with Null/empty Client Instance */
TEST_C(SubscribeTests, SubscribeNullClient) {
IoT_Error_t rc = aws_iot_mqtt_subscribe(NULL, "sdkTest/Sub", 11, QOS1, iot_subscribe_callback_handler, &iotClient);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
/* C:2 - Subscribe with Null/empty Topic Name */
TEST_C(SubscribeTests, SubscribeNullTopic) {
IoT_Error_t rc = aws_iot_mqtt_subscribe(&iotClient, NULL, 11, QOS1, iot_subscribe_callback_handler, &iotClient);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
/* C:3 - Subscribe with Null client callback */
TEST_C(SubscribeTests, SubscribeNullSubscribeHandler) {
IoT_Error_t rc = aws_iot_mqtt_subscribe(&iotClient, "sdkTest/Sub", 11, QOS1, NULL, &iotClient);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
/* C:4 - Subscribe with Null client callback data */
TEST_C(SubscribeTests, SubscribeNullSubscribeHandlerData) {
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams);
IoT_Error_t rc = aws_iot_mqtt_subscribe(&iotClient, "sdkTest/Sub", 11, QOS1, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
}
/* C:5 - Subscribe with no connection */
TEST_C(SubscribeTests, SubscribeNoConnection) {
/* Disconnect first */
IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdkTest/Sub", 11, QOS1, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc);
}
/* C:6 - Subscribe QoS2, error */
/* Not required, QoS enum doesn't have value for QoS2 */
/* C:7 - Subscribe attempt, QoS0, no response timeout */
TEST_C(SubscribeTests, subscribeQoS0FailureOnNoSuback) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Subscribe Tests - C:7 - Subscribe attempt, QoS0, no response timeout \n");
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc);
IOT_DEBUG("-->Success - C:7 - Subscribe attempt, QoS0, no response timeout \n");
}
/* C:8 - Subscribe attempt, QoS1, no response timeout */
TEST_C(SubscribeTests, subscribeQoS1FailureOnNoSuback) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Subscribe Tests - C:8 - Subscribe attempt, QoS1, no response timeout \n");
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc);
IOT_DEBUG("-->Success - C:8 - Subscribe attempt, QoS1, no response timeout \n");
}
/* C:9 - Subscribe QoS0 success, suback received */
TEST_C(SubscribeTests, subscribeQoS0Success) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Subscribe Tests - C:9 - Subscribe QoS0 success, suback received \n");
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("-->Success - C:9 - Subscribe QoS0 success, suback received \n");
}
/* C:10 - Subscribe QoS1 success, suback received */
TEST_C(SubscribeTests, subscribeQoS1Success) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Subscribe Tests - C:10 - Subscribe QoS1 success, suback received \n");
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("-->Success - C:10 - Subscribe QoS1 success, suback received \n");
}
/* C:11 - Subscribe, QoS0, delayed suback, success */
TEST_C(SubscribeTests, subscribeQoS0WithDelayedSubackSuccess) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Subscribe Tests - C:11 - Subscribe, QoS0, delayed suback, success \n");
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams);
setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("-->Success - C:11 - Subscribe, QoS0, delayed suback, success \n");
}
/* C:12 - Subscribe, QoS1, delayed suback, success */
TEST_C(SubscribeTests, subscribeQoS1WithDelayedSubackSuccess) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Subscribe Tests - C:12 - Subscribe, QoS1, delayed suback, success \n");
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams);
setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("-->Success - C:12 - Subscribe, QoS1, delayed suback, success \n");
}
/* C:13 - Subscribe QoS0 success, no puback sent on message */
TEST_C(SubscribeTests, subscribeQoS0MsgReceivedAndNoPubackSent) {
IoT_Error_t rc = SUCCESS;
char expectedCallbackString[100] = "Test msg - unit test";
IOT_DEBUG("-->Running Subscribe Tests - C:13 - Subscribe QoS0 success, no puback sent on message \n");
ResetTLSBuffer();
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL);
if(SUCCESS == rc) {
testPubMsgParams.qos = QOS0;
setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS0, testPubMsgParams, expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
if(SUCCESS == rc) {
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
}
}
CHECK_EQUAL_C_INT(0, isLastTLSTxMessagePuback());
IOT_DEBUG("-->Success - C:13 - Subscribe QoS0 success, no puback sent on message \n");
}
/* C:14 - Subscribe QoS1 success, puback sent on message */
TEST_C(SubscribeTests, subscribeQoS1MsgReceivedAndSendPuback) {
IoT_Error_t rc = SUCCESS;
char expectedCallbackString[] = "0xA5A5A3";
IOT_DEBUG("-->Running Subscribe Tests - C:14 - Subscribe QoS1 success, puback sent on message \n");
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL);
if(SUCCESS == rc) {
setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
if(SUCCESS == rc) {
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
}
CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback());
}
IOT_DEBUG("-->Success - C:14 - Subscribe QoS1 success, puback sent on message \n");
}
/* C:15 - Subscribe, malformed response */
TEST_C(SubscribeTests, subscribeMalformedResponse) {}
/* C:16 - Subscribe, multiple topics, messages on each topic */
TEST_C(SubscribeTests, SubscribeToMultipleTopicsSuccess) {
IoT_Error_t rc = SUCCESS;
char expectedCallbackString[] = "0xA5A5A3";
IOT_DEBUG("-->Running Subscribe Tests - C:16 - Subscribe, multiple topics, messages on each topic \n");
setTLSRxBufferForSuback("sdk/Test1", 9, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test1", 9, QOS1, iot_subscribe_callback_handler1, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferForSuback("sdk/Test2", 9, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test2", 9, QOS1, iot_subscribe_callback_handler2, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test1", 9, QOS1, testPubMsgParams, expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString1);
IOT_DEBUG("-->Success - C:16 - Subscribe, multiple topics, messages on each topic \n");
}
/* C:17 - Subscribe, max topics, messages on each topic */
TEST_C(SubscribeTests, SubcribeToMaxAllowedTopicsSuccess) {
IoT_Error_t rc = SUCCESS;
char expectedCallbackString[] = "topics sdk/Test1";
char expectedCallbackString2[] = "topics sdk/Test2";
char expectedCallbackString3[] = "topics sdk/Test3";
char expectedCallbackString4[] = "topics sdk/Test4";
char expectedCallbackString5[] = "topics sdk/Test5";
IOT_DEBUG("-->Running Subscribe Tests - C:17 - Subscribe, max topics, messages on each topic \n");
setTLSRxBufferForSuback("sdk/Test1", 9, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test1", 9, QOS1, iot_subscribe_callback_handler1, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferForSuback("sdk/Test2", 9, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test2", 9, QOS1, iot_subscribe_callback_handler2, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferForSuback("sdk/Test3", 9, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test3", 9, QOS1, iot_subscribe_callback_handler3, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferForSuback("sdk/Test4", 9, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test4", 9, QOS1, iot_subscribe_callback_handler4, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferForSuback("sdk/Test5", 9, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test5", 9, QOS1, iot_subscribe_callback_handler5, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test1", 9, QOS1, testPubMsgParams, expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test2", 9, QOS1, testPubMsgParams, expectedCallbackString2);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test3", 9, QOS1, testPubMsgParams, expectedCallbackString3);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test4", 9, QOS1, testPubMsgParams, expectedCallbackString4);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test5", 9, QOS1, testPubMsgParams, expectedCallbackString5);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString1);
CHECK_EQUAL_C_STRING(expectedCallbackString2, CallbackMsgString2);
CHECK_EQUAL_C_STRING(expectedCallbackString3, CallbackMsgString3);
CHECK_EQUAL_C_STRING(expectedCallbackString4, CallbackMsgString4);
CHECK_EQUAL_C_STRING(expectedCallbackString5, CallbackMsgString5);
IOT_DEBUG("-->Success - C:17 - Subscribe, max topics, messages on each topic \n");
}
/* C:18 - Subscribe, max topics, another subscribe */
TEST_C(SubscribeTests, SubcribeToMaxPlusOneAllowedTopicsFailure) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Subscribe Tests - C:18 - Subscribe, max topics, another subscribe \n");
setTLSRxBufferForSuback("sdk/Test1", 9, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test1", 9, QOS1, iot_subscribe_callback_handler1, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferForSuback("sdk/Test2", 9, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test2", 9, QOS1, iot_subscribe_callback_handler2, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferForSuback("sdk/Test3", 9, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test3", 9, QOS1, iot_subscribe_callback_handler3, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferForSuback("sdk/Test4", 9, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test4", 9, QOS1, iot_subscribe_callback_handler4, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferForSuback("sdk/Test5", 9, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test5", 9, QOS1, iot_subscribe_callback_handler5, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
setTLSRxBufferForSuback("sdk/Test6", 9, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test6", 9, QOS1, iot_subscribe_callback_handler6, NULL);
CHECK_EQUAL_C_INT(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR, rc);
IOT_DEBUG("-->Success - C:18 - Subscribe, max topics, another subscribe \n");
}
/* C:19 - Subscribe, '#' not last character in topic name, Failure */
TEST_C(SubscribeTests, subscribeTopicWithHashkeyAllSubTopicSuccess) {
IoT_Error_t rc = SUCCESS;
char expectedCallbackString[100] = "New message: sub/sub, Hashkey";
IOT_DEBUG("-->Running Subscribe Tests - C:19 - Subscribe, '#' not last character in topic name, Failure \n");
// Set up the subscribed topic, including '#'
setTLSRxBufferForSuback("sdk/Test/#", strlen("sdk/Test/#"), QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test/#", strlen("sdk/Test/#"), QOS1,
iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
// Now provide a published message from a sub topic
IOT_DEBUG("[Matching '#'] Checking first sub topic message, with '#' be the last..\n");
setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/sub/sub", strlen("sdk/Test/sub/sub"), QOS1, testPubMsgParams,
expectedCallbackString);
snprintf(CallbackMsgString, 100, "NOT_VISITED");
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback());
// Re-initialize Rx Tx Buffer
ResetTLSBuffer();
// Now provide another message from a different sub topic
IOT_DEBUG("[Matching '#'] Checking second sub topic message, with '#' be the last...\n");
snprintf(expectedCallbackString, 100, "New message: sub2, Hashkey");
setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/sub2", strlen("sdk/Test/sub2"), QOS1, testPubMsgParams,
expectedCallbackString);
snprintf(CallbackMsgString, 100, "NOT_VISITED");
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback());
IOT_DEBUG("-->Success - C:19 - Subscribe, '#' not last character in topic name, Failure \n");
}
/* C:20 - Subscribe with '#', subscribed to all subtopics */
TEST_C(SubscribeTests, subscribeTopicHashkeyMustBeTheLastFail) {
IoT_Error_t rc = SUCCESS;
char expectedCallbackString[100] = "New message: foo1/sub, Hashkey";
IOT_DEBUG("-->Running Subscribe Tests - C:20 - Subscribe with '#', subscribed to all subtopics \n");
// Set up the subscribed topic, with '#' in the middle
// Topic directory not permitted, should fail
setTLSRxBufferForSuback("sdk/#/sub", strlen("sdk/#/sub"), QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/#/sub", strlen("sdk/#/sub"), QOS1,
iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
// Now provide a published message from a sub directoy with this sub topic
IOT_DEBUG("[Matching '#'] Checking sub topic message, with '#' in the middle...\n");
setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/foo1/sub", strlen("sdk/Test/foo1/sub"), QOS1, testPubMsgParams,
expectedCallbackString);
snprintf(CallbackMsgString, 100, "NOT_VISITED");
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING("NOT_VISITED", CallbackMsgString);
IOT_DEBUG("-->Success - C:20 - Subscribe with '#', subscribed to all subtopics \n");
}
/* C:21 - Subscribe with '+' as wildcard success */
TEST_C(SubscribeTests, subscribeTopicWithPluskeySuccess) {
IoT_Error_t rc = SUCCESS;
char expectedCallbackString[100] = "New message: 1/sub, Pluskey";
IOT_DEBUG("-->Running Subscribe Tests - C:21 - Subscribe with '+' as wildcard success \n");
// Set up the subscribed topic, including '+'
setTLSRxBufferForSuback("sdk/Test/+/sub", strlen("sdk/Test/+/sub"), QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test/+/sub", strlen("sdk/Test/+/sub"), QOS1,
iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
// Now provide a published message from a sub topic
IOT_DEBUG("[Matching '+'] Checking first sub topic message, with '+' in the middle...\n");
setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/1/sub", strlen("sdk/Test/1/sub"), QOS1, testPubMsgParams,
expectedCallbackString);
snprintf(CallbackMsgString, 100, "NOT_VISITED");
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback());
// Re-initialize Rx Tx Buffer
ResetTLSBuffer();
// Now provide another message from a different sub topic
IOT_DEBUG("[Matching '+'] Checking second sub topic message, with '+' in the middle...\n");
snprintf(expectedCallbackString, 100, "New message: 2/sub, Pluskey");
setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/2/sub", strlen("sdk/Test/2/sub"), QOS1, testPubMsgParams,
expectedCallbackString);
snprintf(CallbackMsgString, 100, "NOT_VISITED");
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback());
IOT_DEBUG("-->Success - C:21 - Subscribe with '+' as wildcard success \n");
}
/* C:22 - Subscribe with '+' as last character in topic name, Success */
TEST_C(SubscribeTests, subscribeTopicPluskeyComesLastSuccess) {
IoT_Error_t rc = SUCCESS;
char expectedCallbackString[100] = "New message: foo1, Pluskey";
IOT_DEBUG("-->Running Subscribe Tests - C:22 - Subscribe with '+' as last character in topic name, Success \n");
// Set up the subscribed topic, with '+' comes the last
setTLSRxBufferForSuback("sdk/Test/+", strlen("sdk/Test/+"), QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test/+", strlen("sdk/Test/+"), QOS1,
iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
// Now provide a published message from a single layer of sub directroy
IOT_DEBUG("[Matching '+'] Checking first sub topic message, with '+' be the last...\n");
setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/foo1", strlen("sdk/Test/foo1"), QOS1, testPubMsgParams,
expectedCallbackString);
snprintf(CallbackMsgString, 100, "NOT_VISITED");
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback());
// Re-initialize Rx Tx Buffer
ResetTLSBuffer();
// Now provide a published message from another single layer of sub directroy
IOT_DEBUG("[Matching '+'] Checking second sub topic message, with '+' be the last...\n");
snprintf(expectedCallbackString, 100, "New message: foo2, Pluskey");
setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/foo2", strlen("sdk/Test/foo2"), QOS1, testPubMsgParams,
expectedCallbackString);
snprintf(CallbackMsgString, 100, "NOT_VISITED");
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback());
IOT_DEBUG("-->Success - C:22 - Subscribe with '+' as last character in topic name, Success \n");
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_unsubscribe.cpp
* @brief IoT Client Unit Testing - Unsubscribe API Tests
*/
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness_c.h>
TEST_GROUP_C(UnsubscribeTests){
TEST_GROUP_C_SETUP_WRAPPER(UnsubscribeTests)
TEST_GROUP_C_TEARDOWN_WRAPPER(UnsubscribeTests)
};
/* D:1 - Unsubscribe with Null/empty client instance */
TEST_GROUP_C_WRAPPER(UnsubscribeTests, UnsubscribeNullClient)
/* D:2 - Unsubscribe with Null/empty topic name */
TEST_GROUP_C_WRAPPER(UnsubscribeTests, UnsubscribeNullTopic)
/* D:3 - Unsubscribe, Not subscribed to topic */
TEST_GROUP_C_WRAPPER(UnsubscribeTests, UnsubscribeNotSubscribed)
/* D:4 - Unsubscribe, QoS0, No response, timeout */
TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS0FailureOnNoUnsuback)
/* D:5 - Unsubscribe, QoS1, No response, timeout */
TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS1FailureOnNoUnsuback)
/* D:6 - Unsubscribe, QoS0, success */
TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS0WithUnsubackSuccess)
/* D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success */
TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS0WithDelayedUnsubackSuccess)
/* D:8 - Unsubscribe, QoS1, success */
TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS1WithUnsubackSuccess)
/* D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success */
TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS1WithDelayedUnsubackSuccess)
/* D:10 - Unsubscribe, success, message on topic ignored */
TEST_GROUP_C_WRAPPER(UnsubscribeTests, MsgAfterUnsubscribe)
/* D:11 - Unsubscribe after max topics reached */
TEST_GROUP_C_WRAPPER(UnsubscribeTests, MaxTopicsSubscription)
/* D:12 - Repeated Subscribe and Unsubscribe */
TEST_GROUP_C_WRAPPER(UnsubscribeTests, RepeatedSubUnSub)

View File

@@ -0,0 +1,343 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_unsubscribe_helper.c
* @brief IoT Client Unit Testing - Unsubscribe API Tests Helper
*/
#include <stdio.h>
#include <string.h>
#include <CppUTest/TestHarness_c.h>
#include "aws_iot_mqtt_client_interface.h"
#include "aws_iot_tests_unit_helper_functions.h"
#include "aws_iot_log.h"
static IoT_Client_Init_Params initParams;
static IoT_Client_Connect_Params connectParams;
static IoT_Publish_Message_Params testPubMsgParams;
static char subTopic[10] = "sdk/Test";
static uint16_t subTopicLen = 8;
static AWS_IoT_Client iotClient;
static char CallbackMsgString[100];
char cPayload[100];
static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
if(NULL == pClient || NULL == topicName || 0 == topicNameLen) {
return;
}
IOT_UNUSED(pData);
char *tmp = params->payload;
unsigned int i;
for(i = 0; i < (params->payloadLen); i++) {
CallbackMsgString[i] = tmp[i];
}
}
TEST_GROUP_C_SETUP(UnsubscribeTests) {
IoT_Error_t rc = SUCCESS;
ResetTLSBuffer();
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL);
initParams.mqttCommandTimeout_ms = 2000;
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID));
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc);
testPubMsgParams.qos = QOS1;
testPubMsgParams.isRetained = 0;
snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0);
testPubMsgParams.payload = (void *) cPayload;
testPubMsgParams.payloadLen = strlen(cPayload);
ResetTLSBuffer();
}
TEST_GROUP_C_TEARDOWN(UnsubscribeTests) { }
/* D:1 - Unsubscribe with Null/empty client instance */
TEST_C(UnsubscribeTests, UnsubscribeNullClient) {
IoT_Error_t rc = aws_iot_mqtt_unsubscribe(NULL, "sdkTest/Sub", 11);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
/* D:2 - Unsubscribe with Null/empty topic name */
TEST_C(UnsubscribeTests, UnsubscribeNullTopic) {
IoT_Error_t rc = aws_iot_mqtt_unsubscribe(&iotClient, NULL, 11);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
/* D:3 - Unsubscribe, Not subscribed to topic */
TEST_C(UnsubscribeTests, UnsubscribeNotSubscribed) {
IoT_Error_t rc = aws_iot_mqtt_unsubscribe(&iotClient, "sdkTest/Sub", 11);
CHECK_EQUAL_C_INT(FAILURE, rc);
}
/* D:4 - Unsubscribe, QoS0, No response, timeout */
TEST_C(UnsubscribeTests, unsubscribeQoS0FailureOnNoUnsuback) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Unsubscribe Tests - D:4 - Unsubscribe, QoS0, No response, timeout \n");
// First, subscribe to a topic
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler,
NULL);
if(SUCCESS == rc) {
// Then, unsubscribe
rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic));
CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc);
}
IOT_DEBUG("-->Success - D:4 - Unsubscribe, QoS0, No response, timeout \n");
}
/* D:5 - Unsubscribe, QoS1, No response, timeout */
TEST_C(UnsubscribeTests, unsubscribeQoS1FailureOnNoUnsuback) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Unsubscribe Tests - D:5 - Unsubscribe, QoS1, No response, timeout \n");
// First, subscribe to a topic
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler,
NULL);
if(SUCCESS == rc) {
// Then, unsubscribe
rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic));
CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc);
}
IOT_DEBUG("-->Success - D:5 - Unsubscribe, QoS1, No response, timeout \n");
}
/* D:6 - Unsubscribe, QoS0, success */
TEST_C(UnsubscribeTests, unsubscribeQoS0WithUnsubackSuccess) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Unsubscribe Tests - D:6 - Unsubscribe, QoS0, success \n");
// First, subscribe to a topic
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler,
NULL);
if(SUCCESS == rc) {
// Then, unsubscribe
setTLSRxBufferForUnsuback();
rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic));
CHECK_EQUAL_C_INT(SUCCESS, rc);
}
IOT_DEBUG("-->Success - D:6 - Unsubscribe, QoS0, success \n");
}
/* D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success */
TEST_C(UnsubscribeTests, unsubscribeQoS0WithDelayedUnsubackSuccess) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Unsubscribe Tests - D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success \n");
// First, subscribe to a topic
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler,
NULL);
if(SUCCESS == rc) {
// Then, unsubscribe
setTLSRxBufferForUnsuback();
setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2);
rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic));
CHECK_EQUAL_C_INT(SUCCESS, rc);
}
IOT_DEBUG("-->Success - D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success \n");
}
/* D:8 - Unsubscribe, QoS1, success */
TEST_C(UnsubscribeTests, unsubscribeQoS1WithUnsubackSuccess) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Unsubscribe Tests - D:8 - Unsubscribe, QoS1, success \n");
// First, subscribe to a topic
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler,
NULL);
if(SUCCESS == rc) {
// Then, unsubscribe
setTLSRxBufferForUnsuback();
rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic));
CHECK_EQUAL_C_INT(SUCCESS, rc);
}
IOT_DEBUG("-->Success - D:8 - Unsubscribe, QoS1, success \n");
}
/* D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success */
TEST_C(UnsubscribeTests, unsubscribeQoS1WithDelayedUnsubackSuccess) {
IoT_Error_t rc = SUCCESS;
IOT_DEBUG("-->Running Unsubscribe Tests - D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success \n");
// First, subscribe to a topic
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler,
NULL);
if(SUCCESS == rc) {
// Then, unsubscribe
setTLSRxBufferForUnsuback();
setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2);
rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic));
CHECK_EQUAL_C_INT(SUCCESS, rc);
}
IOT_DEBUG("-->Success - D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success \n");
}
/* D:10 - Unsubscribe, success, message on topic ignored
* 1. Subscribe to topic 1
* 2. Send message and receive it
* 3. Unsubscribe to topic 1
* 4. Should not receive message
*/
TEST_C(UnsubscribeTests, MsgAfterUnsubscribe) {
IoT_Error_t rc = SUCCESS;
char expectedCallbackString[100];
IOT_DEBUG("-->Running Unsubscribe Tests - D:10 - Unsubscribe, success, message on topic ignored \n");
// 1.
setTLSRxBufferForSuback("topic1", 6, QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, "topic1", 6, QOS0, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
// 2.
snprintf(expectedCallbackString, 100, "Message for topic1");
setTLSRxBufferWithMsgOnSubscribedTopic("topic1", 6, QOS1, testPubMsgParams, expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
//3.
setTLSRxBufferForUnsuback();
rc = aws_iot_mqtt_unsubscribe(&iotClient, "topic1", 6);
CHECK_EQUAL_C_INT(SUCCESS, rc);
//reset the string
snprintf(CallbackMsgString, 100, " ");
// 4.
// Have a new message published to that topic coming in
snprintf(expectedCallbackString, 100, "Message after unsubscribe");
setTLSRxBufferWithMsgOnSubscribedTopic("topic1", 6, QOS0, testPubMsgParams, expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
// No new msg was received
CHECK_EQUAL_C_STRING(" ", CallbackMsgString);
IOT_DEBUG("-->Success - D:10 - Unsubscribe, success, message on topic ignored \n");
}
/* D:11 - Unsubscribe after max topics reached
* 1. Subscribe to max topics + 1 fail for last subscription
* 2. Unsubscribe from one topic
* 3. Subscribe again and should have no error
* 4. Receive msg test - last subscribed topic
*/
TEST_C(UnsubscribeTests, MaxTopicsSubscription) {
IoT_Error_t rc = SUCCESS;
int i = 0;
char topics[AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS + 1][10];
char expectedCallbackString[] = "Message after subscribe - topic[i]";
IOT_DEBUG("-->Running Unsubscribe Tests - D:11 - Unsubscribe after max topics reached \n");
// 1.
for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; i++) {
snprintf(topics[i], 10, "topic-%d", i);
setTLSRxBufferForSuback(topics[i], strlen(topics[i]), QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i]), QOS0, iot_subscribe_callback_handler,
NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
}
snprintf(topics[i], 10, "topic-%d", i);
setTLSRxBufferForSuback(topics[i], strlen(topics[i]), QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i]), QOS0, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR, rc);
// 2.
setTLSRxBufferForUnsuback();
rc = aws_iot_mqtt_unsubscribe(&iotClient, topics[i - 1], (uint16_t) strlen(topics[i - 1]));
CHECK_EQUAL_C_INT(SUCCESS, rc);
//3.
setTLSRxBufferForSuback(topics[i], strlen(topics[i]), QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i]), QOS0, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
//4.
setTLSRxBufferWithMsgOnSubscribedTopic(topics[i], strlen(topics[i]), QOS1, testPubMsgParams,
expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
IOT_DEBUG("-->Success - D:11 - Unsubscribe after max topics reached \n");
}
/* D:12 - Repeated Subscribe and Unsubscribe
* 1. subscribe and unsubscribe for more than the max subscribed topic
* 2. ensure every time the subscribed topic msg is received
*/
TEST_C(UnsubscribeTests, RepeatedSubUnSub) {
IoT_Error_t rc = SUCCESS;
int i = 0;
char expectedCallbackString[100];
char topics[3 * AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS][10];
IOT_DEBUG("-->Running Unsubscribe Tests - D:12 - Repeated Subscribe and Unsubscribe \n");
for(i = 0; i < 3 * AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; i++) {
//1.
snprintf(topics[i], 10, "topic-%d", i);
setTLSRxBufferForSuback(topics[i], 10, QOS0, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], 10, QOS0, iot_subscribe_callback_handler, NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
snprintf(expectedCallbackString, 10, "message##%d", i);
testPubMsgParams.payload = (void *) expectedCallbackString;
testPubMsgParams.payloadLen = strlen(expectedCallbackString);
setTLSRxBufferWithMsgOnSubscribedTopic(topics[i], strlen(topics[i]), QOS1, testPubMsgParams,
expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
//2.
setTLSRxBufferForUnsuback();
rc = aws_iot_mqtt_unsubscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i]));
CHECK_EQUAL_C_INT(SUCCESS, rc);
}
IOT_DEBUG("-->Success - D:12 - Repeated Subscribe and Unsubscribe \n");
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_yield.cpp
* @brief IoT Client Unit Testing - Yield API Tests
*/
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness_c.h>
TEST_GROUP_C(YieldTests){
TEST_GROUP_C_SETUP_WRAPPER(YieldTests)
TEST_GROUP_C_TEARDOWN_WRAPPER(YieldTests)
};
/* G:1 - Yield with Null/empty Client Instance */
TEST_GROUP_C_WRAPPER(YieldTests, NullClientYield)
/* G:2 - Yield with zero yield timeout */
TEST_GROUP_C_WRAPPER(YieldTests, ZeroTimeoutYield)
/* G:3 - Yield, network disconnected, never connected */
TEST_GROUP_C_WRAPPER(YieldTests, YieldNetworkDisconnectedNeverConnected)
/* G:4 - Yield, network disconnected, disconnected manually */
TEST_GROUP_C_WRAPPER(YieldTests, YieldNetworkDisconnectedDisconnectedManually)
/* G:5 - Yield, network connected, yield called while in subscribe application callback */
TEST_GROUP_C_WRAPPER(YieldTests, YieldInSubscribeCallback)
/* G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled */
TEST_GROUP_C_WRAPPER(YieldTests, disconnectNoAutoReconnect)
/* G:7 - Yield, network connected, no incoming messages */
TEST_GROUP_C_WRAPPER(YieldTests, YieldSuccessNoMessages)
/* G:8 - Yield, network connected, ping request/response */
TEST_GROUP_C_WRAPPER(YieldTests, PingRequestPingResponse)
/* G:9 - Yield, disconnected, Auto-reconnect timed-out */
TEST_GROUP_C_WRAPPER(YieldTests, disconnectAutoReconnectTimeout)
/* G:10 - Yield, disconnected, Auto-reconnect successful */
TEST_GROUP_C_WRAPPER(YieldTests, disconnectAutoReconnectSuccess)
/* G:11 - Yield, disconnected, Manual reconnect */
TEST_GROUP_C_WRAPPER(YieldTests, disconnectManualAutoReconnect)
/* G:12 - Yield, resubscribe to all topics on reconnect */
TEST_GROUP_C_WRAPPER(YieldTests, resubscribeSuccessfulReconnect)

View File

@@ -0,0 +1,452 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_yield_helper.c
* @brief IoT Client Unit Testing - Yield API Tests Helper
*/
#include <stdio.h>
#include <unistd.h>
#include <CppUTest/TestHarness_c.h>
#include "aws_iot_tests_unit_helper_functions.h"
#include "aws_iot_tests_unit_mock_tls_params.h"
#include "aws_iot_log.h"
static IoT_Client_Init_Params initParams;
static IoT_Client_Connect_Params connectParams;
static AWS_IoT_Client iotClient;
static IoT_Publish_Message_Params testPubMsgParams;
static ConnectBufferProofread prfrdParams;
static char CallbackMsgString[100];
static char subTopic[10] = "sdk/Test";
static uint16_t subTopicLen = 8;
static bool dcHandlerInvoked = false;
static void iot_tests_unit_acr_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName,
uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
char *tmp = params->payload;
unsigned int i;
IOT_UNUSED(pClient);
IOT_UNUSED(topicName);
IOT_UNUSED(topicNameLen);
IOT_UNUSED(pData);
for(i = 0; i < params->payloadLen; i++) {
CallbackMsgString[i] = tmp[i];
}
}
static void iot_tests_unit_yield_test_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName,
uint16_t topicNameLen,
IoT_Publish_Message_Params *params, void *pData) {
char *tmp = params->payload;
unsigned int i;
IoT_Error_t rc = SUCCESS;
IOT_UNUSED(pClient);
IOT_UNUSED(topicName);
IOT_UNUSED(topicNameLen);
IOT_UNUSED(pData);
rc = aws_iot_mqtt_yield(pClient, 1000);
CHECK_EQUAL_C_INT(MQTT_CLIENT_NOT_IDLE_ERROR, rc);
for(i = 0; i < params->payloadLen; i++) {
CallbackMsgString[i] = tmp[i];
}
}
void iot_tests_unit_disconnect_handler(AWS_IoT_Client *pClient, void *disconParam) {
IOT_UNUSED(pClient);
IOT_UNUSED(disconParam);
dcHandlerInvoked = true;
}
TEST_GROUP_C_SETUP(YieldTests) {
IoT_Error_t rc = SUCCESS;
dcHandlerInvoked = false;
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, iot_tests_unit_disconnect_handler);
rc = aws_iot_mqtt_init(&iotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ConnectMQTTParamsSetup_Detailed(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID),
QOS1, false, true, "willTopicName", (uint16_t) strlen("willTopicName"), "willMsg",
(uint16_t) strlen("willMsg"), NULL, 0, NULL, 0);
connectParams.keepAliveIntervalInSec = 5;
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_connect(&iotClient, &connectParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, false);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
}
TEST_GROUP_C_TEARDOWN(YieldTests) {
/* Clean up. Not checking return code here because this is common to all tests.
* A test might have already caused a disconnect by this point.
*/
IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient);
IOT_UNUSED(rc);
}
/* G:1 - Yield with Null/empty Client Instance */
TEST_C(YieldTests, NullClientYield) {
IoT_Error_t rc = aws_iot_mqtt_yield(NULL, 1000);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
/* G:2 - Yield with zero yield timeout */
TEST_C(YieldTests, ZeroTimeoutYield) {
IoT_Error_t rc = aws_iot_mqtt_yield(&iotClient, 0);
CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc);
}
/* G:3 - Yield, network disconnected, never connected */
TEST_C(YieldTests, YieldNetworkDisconnectedNeverConnected) {
AWS_IoT_Client tempIotClient;
IoT_Error_t rc;
InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, iot_tests_unit_disconnect_handler);
rc = aws_iot_mqtt_init(&tempIotClient, &initParams);
CHECK_EQUAL_C_INT(SUCCESS, rc);
rc = aws_iot_mqtt_yield(&tempIotClient, 1000);
CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc);
}
/* G:4 - Yield, network disconnected, disconnected manually */
TEST_C(YieldTests, YieldNetworkDisconnectedDisconnectedManually) {
IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient);
CHECK_EQUAL_C_INT(SUCCESS, rc);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
CHECK_EQUAL_C_INT(NETWORK_MANUALLY_DISCONNECTED, rc);
}
/* G:5 - Yield, network connected, yield called while in subscribe application callback */
TEST_C(YieldTests, YieldInSubscribeCallback) {
IoT_Error_t rc = SUCCESS;
char expectedCallbackString[] = "0xA5A5A3";
IOT_DEBUG("-->Running Yield Tests - G:5 - Yield, network connected, yield called while in subscribe application callback \n");
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1,
iot_tests_unit_yield_test_subscribe_callback_handler, NULL);
if(SUCCESS == rc) {
setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 1000);
if(SUCCESS == rc) {
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
}
CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback());
}
IOT_DEBUG("-->Success - G:5 - Yield, network connected, yield called while in subscribe application callback \n");
}
/* G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled */
TEST_C(YieldTests, disconnectNoAutoReconnect) {
IoT_Error_t rc = FAILURE;
IOT_DEBUG("-->Running Yield Tests - G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled \n");
rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient));
CHECK_EQUAL_C_INT(true, aws_iot_is_autoreconnect_enabled(&iotClient));
/* Disable Autoreconnect, then let ping request time out and call yield */
aws_iot_mqtt_autoreconnect_set_status(&iotClient, false);
sleep((uint16_t)(iotClient.clientData.keepAliveInterval / 2));
ResetTLSBuffer();
/* Sleep for half keep alive interval to allow the first ping to be sent out */
sleep(iotClient.clientData.keepAliveInterval / (uint32_t)2);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq());
/* Let ping request time out and call yield */
sleep(iotClient.clientData.keepAliveInterval / (uint32_t)2 + 1);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc);
CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect());
CHECK_EQUAL_C_INT(0, aws_iot_mqtt_is_client_connected(&iotClient));
CHECK_EQUAL_C_INT(true, dcHandlerInvoked);
IOT_DEBUG("-->Success - G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled \n");
}
/* G:7 - Yield, network connected, no incoming messages */
TEST_C(YieldTests, YieldSuccessNoMessages) {
IoT_Error_t rc;
int i;
IOT_DEBUG("-->Running Yield Tests - G:7 - Yield, network connected, no incoming messages \n");
for(i = 0; i < 100; i++) {
CallbackMsgString[i] = 'x';
}
rc = aws_iot_mqtt_yield(&iotClient, 1000);
if(SUCCESS == rc) {
/* Check no messages were received */
for(i = 0; i < 100; i++) {
if('x' != CallbackMsgString[i]) {
rc = FAILURE;
}
}
}
CHECK_EQUAL_C_INT(SUCCESS, rc);
IOT_DEBUG("-->Success - G:7 - Yield, network connected, no incoming messages \n");
}
/* G:8 - Yield, network connected, ping request/response */
TEST_C(YieldTests, PingRequestPingResponse) {
IoT_Error_t rc = SUCCESS;
int i = 0;
int j = 0;
int attempt = 3;
IOT_DEBUG("-->Running Yield Tests - G:8 - Yield, network connected, ping request/response \n");
IOT_DEBUG("Current Keep Alive Interval is set to %d sec.\n", iotClient.clientData.keepAliveInterval);
for(i = 0; i < attempt; i++) {
IOT_DEBUG("[Round_%d/Total_%d] Waiting for %d sec...\n", i + 1, attempt, iotClient.clientData.keepAliveInterval);
/* Set TLS buffer for ping response */
ResetTLSBuffer();
setTLSRxBufferForPingresp();
for(j = 0; j <= iotClient.clientData.keepAliveInterval; j++) {
sleep(1);
IOT_DEBUG("[Waited %d secs]", j + 1);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
}
/* Check whether ping was processed correctly and new Ping request was generated */
CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePingreq());
}
IOT_DEBUG("-->Success - G:8 - Yield, network connected, ping request/response \n");
}
/* G:9 - Yield, disconnected, Auto-reconnect timed-out */
TEST_C(YieldTests, disconnectAutoReconnectTimeout) {
IoT_Error_t rc = FAILURE;
IOT_DEBUG("-->Running Yield Tests - G:9 - Yield, disconnected, Auto-reconnect timed-out \n");
rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient));
CHECK_EQUAL_C_INT(true, aws_iot_is_autoreconnect_enabled(&iotClient));
ResetTLSBuffer();
/* Sleep for half keep alive interval to allow the first ping to be sent out */
sleep(iotClient.clientData.keepAliveInterval / (uint32_t)2);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq());
/* Let ping request time out and call yield */
sleep(iotClient.clientData.keepAliveInterval / (uint32_t)2 + 1);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc);
CHECK_EQUAL_C_INT(0, aws_iot_mqtt_is_client_connected(&iotClient));
CHECK_EQUAL_C_INT(true, dcHandlerInvoked);
IOT_DEBUG("-->Success - G:9 - Yield, disconnected, Auto-reconnect timed-out \n");
}
/* G:10 - Yield, disconnected, Auto-reconnect successful */
TEST_C(YieldTests, disconnectAutoReconnectSuccess) {
IoT_Error_t rc = FAILURE;
unsigned char *currPayload = NULL;
IOT_DEBUG("-->Running Yield Tests - G:10 - Yield, disconnected, Auto-reconnect successful \n");
rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient));
CHECK_EQUAL_C_INT(true, aws_iot_is_autoreconnect_enabled(&iotClient));
/* Sleep for half keep alive interval to allow the first ping to be sent out */
sleep(iotClient.clientData.keepAliveInterval / (uint32_t)2);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq());
/* Let ping request time out and call yield */
sleep(iotClient.clientData.keepAliveInterval / (uint32_t)2 + 1);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc);
sleep(2); /* Default min reconnect delay is 1 sec */
printf("\nWakeup");
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
currPayload = connectTxBufferHeaderParser(&prfrdParams, TxBuffer.pBuffer);
CHECK_C(true == isConnectTxBufFlagCorrect(&connectParams, &prfrdParams));
CHECK_C(true == isConnectTxBufPayloadCorrect(&connectParams, currPayload));
CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient));
CHECK_EQUAL_C_INT(true, dcHandlerInvoked);
IOT_DEBUG("-->Success - G:10 - Yield, disconnected, Auto-reconnect successful \n");
}
/* G:11 - Yield, disconnected, Manual reconnect */
TEST_C(YieldTests, disconnectManualAutoReconnect) {
IoT_Error_t rc = FAILURE;
unsigned char *currPayload = NULL;
IOT_DEBUG("-->Running Yield Tests - G:11 - Yield, disconnected, Manual reconnect \n");
CHECK_C(aws_iot_mqtt_is_client_connected(&iotClient));
/* Disable Autoreconnect, then let ping request time out and call yield */
aws_iot_mqtt_autoreconnect_set_status(&iotClient, false);
CHECK_C(!aws_iot_is_autoreconnect_enabled(&iotClient));
/* Sleep for half keep alive interval to allow the first ping to be sent out */
sleep(iotClient.clientData.keepAliveInterval / (uint32_t)2);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq());
/* Let ping request time out and call yield */
sleep(iotClient.clientData.keepAliveInterval / (uint32_t)2 + 1);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc);
CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect());
CHECK_C(!aws_iot_mqtt_is_client_connected(&iotClient));
CHECK_EQUAL_C_INT(true, dcHandlerInvoked);
dcHandlerInvoked = false;
setTLSRxBufferForConnack(&connectParams, 0, 0);
rc = aws_iot_mqtt_attempt_reconnect(&iotClient);
CHECK_EQUAL_C_INT(NETWORK_RECONNECTED, rc);
currPayload = connectTxBufferHeaderParser(&prfrdParams, TxBuffer.pBuffer);
CHECK_C(true == isConnectTxBufFlagCorrect(&connectParams, &prfrdParams));
CHECK_C(true == isConnectTxBufPayloadCorrect(&connectParams, currPayload));
CHECK_C(aws_iot_mqtt_is_client_connected(&iotClient));
CHECK_EQUAL_C_INT(false, dcHandlerInvoked);
IOT_DEBUG("-->Success - G:11 - Yield, disconnected, Manual reconnect \n");
}
/* G:12 - Yield, resubscribe to all topics on reconnect */
TEST_C(YieldTests, resubscribeSuccessfulReconnect) {
IoT_Error_t rc = FAILURE;
char cPayload[100];
bool connected = false;
bool autoReconnectEnabled = false;
char expectedCallbackString[100];
IOT_DEBUG("-->Running Yield Tests - G:12 - Yield, resubscribe to all topics on reconnect \n");
rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true);
CHECK_EQUAL_C_INT(SUCCESS, rc);
snprintf(CallbackMsgString, 100, "NOT_VISITED");
testPubMsgParams.qos = QOS1;
testPubMsgParams.isRetained = 0;
snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0);
testPubMsgParams.payload = (void *) cPayload;
testPubMsgParams.payloadLen = strlen(cPayload);
connected = aws_iot_mqtt_is_client_connected(&iotClient);
CHECK_EQUAL_C_INT(1, connected);
ResetTLSBuffer();
/* Subscribe to a topic */
setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams);
rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_tests_unit_acr_subscribe_callback_handler,
NULL);
CHECK_EQUAL_C_INT(SUCCESS, rc);
ResetTLSBuffer();
/* Check subscribe */
snprintf(expectedCallbackString, 100, "Message for %s", subTopic);
setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
ResetTLSBuffer();
autoReconnectEnabled = aws_iot_is_autoreconnect_enabled(&iotClient);
CHECK_EQUAL_C_INT(1, autoReconnectEnabled);
/* Sleep for half keep alive interval to allow the first ping to be sent out */
sleep(iotClient.clientData.keepAliveInterval / (uint32_t)2);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq());
/* Let ping request time out and call yield */
sleep(iotClient.clientData.keepAliveInterval / (uint32_t)2 + 1);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc);
sleep(2); /* Default min reconnect delay is 1 sec */
ResetTLSBuffer();
setTLSRxBufferForConnackAndSuback(&connectParams, 0, subTopic, subTopicLen, QOS1);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
/* Test if reconnect worked */
connected = aws_iot_mqtt_is_client_connected(&iotClient);
CHECK_EQUAL_C_INT(true, connected);
ResetTLSBuffer();
/* Check subscribe */
snprintf(expectedCallbackString, 100, "Message for %s after resub", subTopic);
setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString);
rc = aws_iot_mqtt_yield(&iotClient, 100);
CHECK_EQUAL_C_INT(SUCCESS, rc);
CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString);
CHECK_EQUAL_C_INT(true, dcHandlerInvoked);
IOT_DEBUG("-->Success - G:12 - Yield, resubscribe to all topics on reconnect \n");
}

View File

@@ -0,0 +1,149 @@
#include <string.h>
#include <stdio.h>
#include <network_interface.h>
#include "network_interface.h"
#include "aws_iot_tests_unit_mock_tls_params.h"
void _iot_tls_set_connect_params(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation,
char *pDevicePrivateKeyLocation, char *pDestinationURL,
uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) {
pNetwork->tlsConnectParams.DestinationPort = destinationPort;
pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL;
pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation;
pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation;
pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation;
pNetwork->tlsConnectParams.timeout_ms = timeout_ms;
pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag;
}
IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation,
char *pDevicePrivateKeyLocation, char *pDestinationURL,
uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) {
_iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation,
pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag);
pNetwork->connect = iot_tls_connect;
pNetwork->read = iot_tls_read;
pNetwork->write = iot_tls_write;
pNetwork->disconnect = iot_tls_disconnect;
pNetwork->isConnected = iot_tls_is_connected;
pNetwork->destroy = iot_tls_destroy;
return SUCCESS;
}
IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) {
IOT_UNUSED(pNetwork);
if(NULL != params) {
_iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation,
params->pDevicePrivateKeyLocation, params->pDestinationURL, params->DestinationPort,
params->timeout_ms, params->ServerVerificationFlag);
}
if(NULL != invalidEndpointFilter && 0 == strcmp(invalidEndpointFilter, pNetwork->tlsConnectParams.pDestinationURL)) {
return NETWORK_ERR_NET_UNKNOWN_HOST;
}
if(invalidPortFilter == pNetwork->tlsConnectParams.DestinationPort) {
return NETWORK_ERR_NET_CONNECT_FAILED;
}
if(NULL != invalidRootCAPathFilter && 0 == strcmp(invalidRootCAPathFilter, pNetwork->tlsConnectParams.pRootCALocation)) {
return NETWORK_ERR_NET_CONNECT_FAILED;
}
if(NULL != invalidCertPathFilter && 0 == strcmp(invalidCertPathFilter, pNetwork->tlsConnectParams.pDeviceCertLocation)) {
return NETWORK_ERR_NET_CONNECT_FAILED;
}
if(NULL != invalidPrivKeyPathFilter && 0 == strcmp(invalidPrivKeyPathFilter, pNetwork->tlsConnectParams.pDevicePrivateKeyLocation)) {
return NETWORK_ERR_NET_CONNECT_FAILED;
}
return SUCCESS;
}
IoT_Error_t iot_tls_is_connected(Network *pNetwork) {
IOT_UNUSED(pNetwork);
/* Use this to add implementation which can check for physical layer disconnect */
return NETWORK_PHYSICAL_LAYER_CONNECTED;
}
IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *written_len) {
size_t i = 0;
uint8_t firstByte, secondByte;
uint16_t topicNameLen;
IOT_UNUSED(pNetwork);
IOT_UNUSED(timer);
for(i = 0; (i < len) && left_ms(timer) > 0; i++) {
TxBuffer.pBuffer[i] = pMsg[i];
}
TxBuffer.len = len;
*written_len = len;
/* Save last two subscribed topics */
if((TxBuffer.pBuffer[0] == 0x82 ? true : false)) {
snprintf(SecondLastSubscribeMessage, lastSubscribeMsgLen, "%s", LastSubscribeMessage);
secondLastSubscribeMsgLen = lastSubscribeMsgLen;
firstByte = (uint8_t)(TxBuffer.pBuffer[4]);
secondByte = (uint8_t)(TxBuffer.pBuffer[5]);
topicNameLen = (uint16_t) (secondByte + (256 * firstByte));
snprintf(LastSubscribeMessage, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[6])); // Added one for null character
lastSubscribeMsgLen = topicNameLen + 1u;
}
return SUCCESS;
}
static unsigned char isTimerExpired(struct timeval target_time) {
unsigned char ret_val = 0;
struct timeval now, result;
if(target_time.tv_sec != 0 || target_time.tv_usec != 0) {
gettimeofday(&now, NULL);
timersub(&(target_time), &now, &result);
if(result.tv_sec < 0 || (result.tv_sec == 0 && result.tv_usec <= 0)) {
ret_val = 1;
}
} else {
ret_val = 1;
}
return ret_val;
}
IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *pTimer, size_t *read_len) {
IOT_UNUSED(pNetwork);
IOT_UNUSED(pTimer);
if(RxIndex > TLSMaxBufferSize - 1) {
RxIndex = TLSMaxBufferSize - 1;
}
if(RxBuffer.len <= RxIndex || !isTimerExpired(RxBuffer.expiry_time)) {
return NETWORK_SSL_NOTHING_TO_READ;
}
if((false == RxBuffer.NoMsgFlag) && (RxIndex < RxBuffer.len)) {
memcpy(pMsg, &(RxBuffer.pBuffer[RxIndex]), len);
RxIndex += len;
*read_len = len;
}
return SUCCESS;
}
IoT_Error_t iot_tls_disconnect(Network *pNetwork) {
IOT_UNUSED(pNetwork);
return SUCCESS;
}
IoT_Error_t iot_tls_destroy(Network *pNetwork) {
IOT_UNUSED(pNetwork);
return SUCCESS;
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_mock_tls_params.c
* @brief IoT Client Unit Testing Mock TLS Params
*/
#include "aws_iot_tests_unit_mock_tls_params.h"
unsigned char RxBuf[TLSMaxBufferSize];
unsigned char TxBuf[TLSMaxBufferSize];
char LastSubscribeMessage[TLSMaxBufferSize];
size_t lastSubscribeMsgLen;
char SecondLastSubscribeMessage[TLSMaxBufferSize];
size_t secondLastSubscribeMsgLen;
TlsBuffer RxBuffer = {.pBuffer = RxBuf,.len = 512, .NoMsgFlag=1, .expiry_time = {0, 0}, .BufMaxSize = TLSMaxBufferSize};
TlsBuffer TxBuffer = {.pBuffer = TxBuf,.len = 512, .NoMsgFlag=1, .expiry_time = {0, 0}, .BufMaxSize = TLSMaxBufferSize};
size_t RxIndex = 0;
char *invalidEndpointFilter;
char *invalidRootCAPathFilter;
char *invalidCertPathFilter;
char *invalidPrivKeyPathFilter;
uint16_t invalidPortFilter;

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_tests_unit_mock_tls_params.h
* @brief IoT Client Unit Testing Mock TLS Params
*/
#ifndef UNITTESTS_MOCKS_TLS_PARAMS_H_
#define UNITTESTS_MOCKS_TLS_PARAMS_H_
#include <sys/time.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#define TLSMaxBufferSize 1024
#define NO_MSG_LENGTH_MENTIONED -1
typedef struct {
unsigned char *pBuffer;
size_t len;
bool NoMsgFlag;
struct timeval expiry_time;
size_t BufMaxSize;
} TlsBuffer;
extern TlsBuffer RxBuffer;
extern TlsBuffer TxBuffer;
extern size_t RxIndex;
extern unsigned char RxBuf[TLSMaxBufferSize];
extern unsigned char TxBuf[TLSMaxBufferSize];
extern char LastSubscribeMessage[TLSMaxBufferSize];
extern size_t lastSubscribeMsgLen;
extern char SecondLastSubscribeMessage[TLSMaxBufferSize];
extern size_t secondLastSubscribeMsgLen;
extern char hostAddress[512];
extern uint16_t port;
extern uint32_t handshakeTimeout_ms;
extern char *invalidEndpointFilter;
extern char *invalidRootCAPathFilter;
extern char *invalidCertPathFilter;
extern char *invalidPrivKeyPathFilter;
extern uint16_t invalidPortFilter;
#endif /* UNITTESTS_MOCKS_TLS_PARAMS_H_ */

View File

@@ -0,0 +1,19 @@
//
// Created by chaurah on 3/22/16.
//
#ifndef IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H
/**
* @brief TLS Connection Parameters
*
* Defines a type containing TLS specific parameters to be passed down to the
* TLS networking layer to create a TLS secured socket.
*/
typedef struct _TLSDataParams {
uint32_t flags;
}TLSDataParams;
#define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H
#endif //IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H