summaryrefslogtreecommitdiff
path: root/src/ccapi/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/ccapi/test')
-rw-r--r--src/ccapi/test/Makefile.in225
-rw-r--r--src/ccapi/test/Makefile.w3275
-rw-r--r--src/ccapi/test/Pingtest.sln20
-rw-r--r--src/ccapi/test/deps0
-rw-r--r--src/ccapi/test/main.c90
-rw-r--r--src/ccapi/test/pingtest.c116
-rwxr-xr-xsrc/ccapi/test/setlib.pl10
-rw-r--r--src/ccapi/test/simple_lock_test.c91
-rw-r--r--src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_compare.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_destroy.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_get_change_time.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_get_credentials_version.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_get_last_default_time.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_get_name.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_get_principal.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_iterator_next.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_move.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_new_credentials_iterator.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_release.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_remove_credentials.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_set_default.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_set_principal.c15
-rw-r--r--src/ccapi/test/test_cc_ccache_store_credentials.c15
-rw-r--r--src/ccapi/test/test_cc_close.c14
-rw-r--r--src/ccapi/test/test_cc_context_compare.c15
-rw-r--r--src/ccapi/test/test_cc_context_create_ccache.c15
-rw-r--r--src/ccapi/test/test_cc_context_create_default_ccache.c15
-rw-r--r--src/ccapi/test/test_cc_context_create_new_ccache.c15
-rw-r--r--src/ccapi/test/test_cc_context_get_change_time.c15
-rw-r--r--src/ccapi/test/test_cc_context_get_default_ccache_name.c15
-rw-r--r--src/ccapi/test/test_cc_context_new_ccache_iterator.c15
-rw-r--r--src/ccapi/test/test_cc_context_open_ccache.c15
-rw-r--r--src/ccapi/test/test_cc_context_open_default_ccache.c15
-rw-r--r--src/ccapi/test/test_cc_context_release.c15
-rw-r--r--src/ccapi/test/test_cc_create.c14
-rw-r--r--src/ccapi/test/test_cc_credentials_iterator_next.c16
-rw-r--r--src/ccapi/test/test_cc_destroy.c14
-rw-r--r--src/ccapi/test/test_cc_get_NC_info.c14
-rw-r--r--src/ccapi/test/test_cc_get_change_time.c14
-rw-r--r--src/ccapi/test/test_cc_get_cred_version.c14
-rw-r--r--src/ccapi/test/test_cc_get_name.c14
-rw-r--r--src/ccapi/test/test_cc_get_principal.c14
-rw-r--r--src/ccapi/test/test_cc_initialize.c15
-rw-r--r--src/ccapi/test/test_cc_open.c14
-rw-r--r--src/ccapi/test/test_cc_remove_cred.c14
-rw-r--r--src/ccapi/test/test_cc_seq_fetch_NCs_begin.c14
-rw-r--r--src/ccapi/test/test_cc_seq_fetch_NCs_next.c14
-rw-r--r--src/ccapi/test/test_cc_seq_fetch_creds_begin.c14
-rw-r--r--src/ccapi/test/test_cc_seq_fetch_creds_next.c14
-rw-r--r--src/ccapi/test/test_cc_set_principal.c14
-rw-r--r--src/ccapi/test/test_cc_shutdown.c14
-rw-r--r--src/ccapi/test/test_cc_store.c14
-rw-r--r--src/ccapi/test/test_ccapi.bat43
-rwxr-xr-xsrc/ccapi/test/test_ccapi.sh76
-rw-r--r--src/ccapi/test/test_ccapi_ccache.c2034
-rw-r--r--src/ccapi/test/test_ccapi_ccache.h49
-rw-r--r--src/ccapi/test/test_ccapi_check.c37
-rw-r--r--src/ccapi/test/test_ccapi_check.h43
-rw-r--r--src/ccapi/test/test_ccapi_constants.c66
-rw-r--r--src/ccapi/test/test_ccapi_constants.h6
-rw-r--r--src/ccapi/test/test_ccapi_context.c990
-rw-r--r--src/ccapi/test/test_ccapi_context.h32
-rw-r--r--src/ccapi/test/test_ccapi_globals.c87
-rw-r--r--src/ccapi/test/test_ccapi_globals.h57
-rw-r--r--src/ccapi/test/test_ccapi_iterators.c246
-rw-r--r--src/ccapi/test/test_ccapi_iterators.h12
-rw-r--r--src/ccapi/test/test_ccapi_log.c45
-rw-r--r--src/ccapi/test/test_ccapi_log.h20
-rw-r--r--src/ccapi/test/test_ccapi_util.c142
-rw-r--r--src/ccapi/test/test_ccapi_util.h13
-rw-r--r--src/ccapi/test/test_ccapi_v2.c1839
-rw-r--r--src/ccapi/test/test_ccapi_v2.h73
-rw-r--r--src/ccapi/test/test_constants.c15
76 files changed, 7241 insertions, 0 deletions
diff --git a/src/ccapi/test/Makefile.in b/src/ccapi/test/Makefile.in
new file mode 100644
index 0000000000000..85fe172354f14
--- /dev/null
+++ b/src/ccapi/test/Makefile.in
@@ -0,0 +1,225 @@
+mydir=ccapi$(S)test
+BUILDTOP=..$(S)..
+CCAPI=$(BUILDTOP)$(S)CCAPI
+
+!if defined(KRB5_KFW_COMPILE)
+KFWINC= /I$(BUILDTOP)\..\..\krbcc\include
+!endif
+
+# Because all the sources are in .,
+# the only includes we need are to directories outside of ccapi.
+LOCALINCLUDES = /I$(BUILDTOP) /I$(BUILDTOP)$(S)include /I$(BUILDTOP)$(S)include$(S)krb5 $(KFWINC) \
+ -I$(BUILDTOP)$(S)util$(S)et /I. -I$(CCAPI)$(S)COMMON -I$(CCAPI)$(S)LIB
+
+# run with "make all" to create CCAPI tests in "/tmp/ccapi_test"
+# run resulting tests with "sh test_ccapi.sh"
+
+##DOS##CPPFLAGS = $(CPPFLAGS) /EHsc -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 \
+##DOS## -D_WIN32_WINNT=0x0501 -D_CRT_SECURE_NO_WARNINGS
+
+##DOS##WINH = cci_debugging.h \
+##DOS## ccs_reply.h \
+##DOS## ccs_request.h \
+##DOS## ccs_request_c.c \
+##DOS## cci_types.h \
+##DOS## win-utils.h
+
+##DOS##LIBSRC=ccapi_ccache.c \
+##DOS## ccapi_ccache_iterator.c \
+##DOS## ccapi_context.c \
+##DOS## ccapi_context_change_time.c \
+##DOS## ccapi_err.c \
+##DOS## ccapi_ipc.c \
+##DOS## ccapi_credentials.c \
+##DOS## ccapi_credentials_iterator.c \
+##DOS## ccapi_string.c \
+##DOS## ccapi_v2.c
+
+##DOS##COMSRC=cci_cred_union.c \
+##DOS## cci_identifier.c \
+##DOS## cci_message.c
+
+##DOS##COWSRC=cci_os_identifier.c
+
+SRCDIR = .
+DSTROOT = $(SRCDIR)
+OBJDIR = $(DSTROOT)$(S)ccapi_intermediates
+DSTDIR = $(DSTROOT)$(S)ccapi_test
+TESTDIR = $(DSTDIR)$(S)tests
+SRCTMP = $(SRCDIR)\srctmp
+
+SCRIPT_NAME = test_ccapi.sh
+
+OBJECTS = $(OUTPRE)test_ccapi_ccache.$(OBJEXT) \
+ $(OUTPRE)test_ccapi_check.$(OBJEXT) \
+ $(OUTPRE)test_ccapi_constants.$(OBJEXT) \
+ $(OUTPRE)test_ccapi_context.$(OBJEXT) \
+ $(OUTPRE)test_ccapi_v2.$(OBJEXT) \
+ $(OUTPRE)test_ccapi_globals.$(OBJEXT) \
+ $(OUTPRE)test_ccapi_iterators.$(OBJEXT) \
+ $(OUTPRE)test_ccapi_log.$(OBJEXT) \
+ $(OUTPRE)test_ccapi_util.$(OBJEXT)
+
+PINGOBJS = $(OUTPRE)ccapi_ccache.$(OBJEXT) \
+ $(OUTPRE)ccapi_ccache_iterator.$(OBJEXT) \
+ $(OUTPRE)ccapi_context.$(OBJEXT) \
+ $(OUTPRE)ccapi_context_change_time.$(OBJEXT) \
+ $(OUTPRE)ccapi_err.$(OBJEXT) \
+ $(OUTPRE)ccapi_ipc.$(OBJEXT) \
+ $(OUTPRE)ccapi_credentials.$(OBJEXT) \
+ $(OUTPRE)ccapi_credentials_iterator.$(OBJEXT) \
+ $(OUTPRE)ccapi_string.$(OBJEXT) \
+ $(OUTPRE)ccapi_v2.$(OBJEXT) \
+ $(OUTPRE)cci_cred_union.$(OBJEXT) \
+ $(OUTPRE)cci_identifier.$(OBJEXT) \
+ $(OUTPRE)cci_os_identifier.$(OBJEXT) \
+ $(OUTPRE)cci_message.$(OBJEXT) \
+ $(OUTPRE)ccs_request_c.$(OBJEXT) \
+ $(OUTPRE)pingtest.$(OBJEXT) \
+ $(OBJECTS)
+
+TESTALLOBJS=$(OUTPRE)main.$(OBJEXT) \
+ $(OBJECTS)
+
+TEST_NAMES = test_cc_ccache_iterator_next \
+ test_constants \
+ test_cc_initialize \
+ test_cc_credentials_iterator_next
+
+MORE_TESTS = test_cc_context_release \
+ test_cc_context_get_change_time \
+ test_cc_context_get_default_ccache_name \
+ test_cc_context_open_ccache \
+ test_cc_context_open_default_ccache \
+ test_cc_context_create_ccache \
+ test_cc_context_create_default_ccache \
+ test_cc_context_create_new_ccache \
+ test_cc_context_new_ccache_iterator \
+ test_cc_context_compare \
+ test_cc_ccache_release \
+ test_cc_ccache_destroy \
+ test_cc_ccache_set_default \
+ test_cc_ccache_get_credentials_version \
+ test_cc_ccache_get_name \
+ test_cc_ccache_get_principal \
+ test_cc_ccache_set_principal \
+ test_cc_ccache_store_credentials \
+ test_cc_ccache_remove_credentials \
+ test_cc_ccache_new_credentials_iterator \
+ test_cc_ccache_get_change_time \
+ test_cc_ccache_get_last_default_time \
+ test_cc_ccache_move \
+ test_cc_ccache_compare \
+ test_cc_ccache_get_kdc_time_offset \
+ test_cc_ccache_set_kdc_time_offset \
+ test_cc_ccache_clear_kdc_time_offset \
+ test_cc_shutdown \
+ test_cc_get_change_time \
+ test_cc_open \
+ test_cc_create \
+ test_cc_close \
+ test_cc_destroy \
+ test_cc_get_cred_version \
+ test_cc_get_name \
+ test_cc_get_principal \
+ test_cc_set_principal \
+ test_cc_store \
+ test_cc_remove_cred \
+ test_cc_seq_fetch_NCs_begin \
+ test_cc_seq_fetch_NCs_next \
+ test_cc_seq_fetch_creds_begin \
+ test_cc_seq_fetch_creds_next \
+ test_cc_get_NC_info
+
+
+##### Linker
+LINK = link
+LIBS = -lkrb5
+##DOS##LIBS = $(CLIB) $(SLIB) advapi32.lib rpcrt4.lib user32.lib ws2_32.lib $(CCLIB).lib
+LFLAGS = /nologo $(LOPTS)
+
+all-mac: setup-test-dir pingtest simple_lock_test build-base build-tests link-tests copy-script success-message
+all-windows: setup-windows build-base $(OUTPRE)pingtest.exe build-tests build-testall copy-script success-message
+
+# compile base files used by all tests
+build-base: $(PINGOBJS)
+
+##++ These two rules build each element of the list:
+# compile each test
+build-tests: $(TEST_NAMES)
+ @echo build-tests complete.
+
+$(TEST_NAMES):
+ @echo DBG: $@
+ $(CC) $(ALL_CFLAGS) -Fe$(TESTDIR)$(S)$@.exe -Fd$(OBJDIR)$(S)$@.obj $@.c $(OBJECTS) $(LIBS)
+# Clean .obj from .:
+ $(RM) $@.$(OBJEXT)
+##-- These two rules build each element of the list.
+
+# Make a build directory
+setup-test-dir:
+ @echo "Removing old destination directory... $(DSTDIR)"
+ if [ -d "$(DSTDIR)" ]; then chmod -R u+w "$(DSTDIR)" && rm -rf "$(DSTDIR)"; fi
+ mkdir -p "$(TESTDIR)"
+ if [ -d "$(OBJDIR)" ]; then chmod -R u+w "$(OBJDIR)" && rm -rf "$(OBJDIR)"; fi
+ mkdir -p "$(OBJDIR)"
+
+## The same trick as used in TEST_NAMES to run an action on each element ofthe list WINH:
+setup-windows: $(WINH) $(LIBSRC) $(COMSRC) $(COWSRC)
+ if NOT exist $(TESTDIR) mkdir $(TESTDIR)
+ if NOT exist $(OBJDIR) mkdir $(OBJDIR)
+ set LINK = link
+
+# This rule assumes that nmake in ..\lib\win has already run.
+# That is how ..\Makefile.in is set up.
+$(WINH):
+ copy ..\lib\win\srctmp\$@ .
+
+$(LIBSRC):
+ copy ..\lib\$@ .
+
+$(COMSRC):
+ copy ..\common\$@ .
+
+$(COWSRC):
+ copy ..\common\win\$@ .
+
+# This rule assumes that nmake in ..\lib\win\ has already run.
+$(OUTPRE)pingtest.exe: $(OBJECTS) $(PINGOBJS)
+# There doesn't appear to be any way to examine a variable and return a value
+# indicating whether a string is present in it. We use a perl script to
+# check the LIB variable. If the path to $(CCLIB).lib isn't present, the script
+# deletes a.tmp and the following nmake actions correct LIB.
+ echo %%PATH%% > a.tmp
+ perl setlib.pl
+ if not exist a.tmp (
+ @echo Adding ..\lib\win\srctmp to LIB
+ set LIB=%%LIB%%;..\lib\win\srctmp
+ )
+ $(LINK) $(linkdebug) /map:$(@B)1.map -out:$(*B)1.exe $(conflags) $(PINGOBJS) $(LIBS)
+ $(LINK) $(LFLAGS) /map:$(@B)2.map /out:$(*B)2.exe $(conflags) $(PINGOBJS) $(LIBS) $(conlibsdll)
+
+link-tests: $(TEST_NAMES)
+
+build-testall: $(TEST_NAMES) $(OBJECTS) $(TESTALLOBJS) testall.exe
+
+testall.exe:
+ $(LINK) $(linkdebug) /map:$(@B)1.map -out:$(*B)1.exe $(conflags) $(TESTALLOBJS) $(LIBS) $(conslibdll)
+
+
+simple_lock_test:
+ $(CC) -o $(TESTDIR)/simple_lock_test simple_lock_test.c $(LIBS)
+
+copy-script:
+ $(CP) $(SCRIPT_NAME) $(DSTDIR)$(S)$(SCRIPT_NAME)
+
+success-message:
+ @echo
+ @echo "CCAPI tests created in $(DSTDIR)"
+
+.PHONY: clean
+
+clean:
+ -rm -rf "$(OBJDIR)"
+ -rm -rf $(LIBSRC)
+ -rm -rf $(WINH)
diff --git a/src/ccapi/test/Makefile.w32 b/src/ccapi/test/Makefile.w32
new file mode 100644
index 0000000000000..8c3da95153465
--- /dev/null
+++ b/src/ccapi/test/Makefile.w32
@@ -0,0 +1,75 @@
+# . is ccapi/test.
+CO = ..\common
+COWIN = $(CO)\win
+LIBDIR = ..\lib
+LIBWIN = $(LIBDIR)\win
+SRV = ..\server
+SRVWIN = ..\server\win
+
+!include <Win32.Mak>
+
+INC = -I..\..\include -I..\..\util\et -I$(CO) -I$(COWIN) -I$(LIBDIR) -I$(LIBWIN)
+
+!if "$(CPU)" == "i386"
+cflags = $(cflags) /EHsc /MTd -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 \
+$(INC)
+!else
+cflags = $(cflags) /W3 -D_CRTAPI1= -D_CRTAPI2= $(INC)
+!endif
+LIBS = $(LIBWIN)\ccapi.lib
+
+DSTROOT = .
+SRC = $(DSTROOT)
+#OBJDIR = $(DSTROOT)\obj
+OBJDIR = .
+OBJEXT = obj
+TESTDIR = $(DSTROOT)\tests
+TESTEXT = exe
+DSTDIR = $(DSTROOT)\ccapi_tests
+
+PINGOBJS = pingtest.obj
+SIMPLEOBJS = simple_lock_test.obj
+
+comobjs = cci_debugging.obj cci_stream.obj
+cowobjs = cci_os_debugging.obj
+libobjs = ccs_request_c.obj
+
+#all: build-base simple_lock_test pingtest
+all: build-base pingtest
+
+# compile base files used by all tests
+build-base: $(comobjs) $(libobjs) $(srvobjs)
+ @echo "Base objects built."
+
+# rule to compile src files
+.c.obj:
+ $(cc) $(cdebug) $(cflags) /Fo$(OBJDIR)\$(*B).$(OBJEXT) $(SRC)\$(*B).c
+
+$(comobjs) : $(CO)\$(*B).c
+ $(cc) $(cdebug) $(cflags) $(CO)\$(*B).c
+
+$(cowobjs) : $(COWIN)\$(*B).c
+ $(cc) $(cdebug) $(cflags) $(COWIN)\$(*B).c
+
+$(libobjs) : $(LIBWIN)\$(*B).c
+ $(cc) $(cdebug) $(cflags) $(LIBWIN)\$(*B).c
+
+#$(srvobjs) : $(SRVWIN)\$*.c
+# $(cc) $(cdebug) $(cflags) $(SRVWIN)\$*.c
+
+simple_lock_test: simple_lock_test.obj $(OBJS)
+ @echo R3+ Build $(*B) in $(TESTDIR)
+ $(cc) $(cdebug) $(cflags) $(*B).c
+ $(link) $(linkdebug) $(conflags) -out:$(TESTDIR)\$(*B).exe $(*B).obj \
+ $(LIBS) rpcrt4.lib
+ @echo R3- Built $(*B) in $(TESTDIR)
+
+pingtest: pingtest.obj
+ @echo R4+ Build $(*B) in $(TESTDIR)
+ $(cc) $(cdebug) $(cflags) $(*B).c
+ $(link) $(linkdebug) $(conflags) -out:$(*B).exe $(PINGOBJS) $(libobjs) $(srvobjs) \
+ $(LIBS) rpcrt4.lib
+ @echo R4- Built $(*B) in $(TESTDIR)
+
+clean:
+ DEL *.$(OBJEXT) \ No newline at end of file
diff --git a/src/ccapi/test/Pingtest.sln b/src/ccapi/test/Pingtest.sln
new file mode 100644
index 0000000000000..cf43a1e4f6722
--- /dev/null
+++ b/src/ccapi/test/Pingtest.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Pingtest", "Pingtest.vcproj", "{04017001-3222-43C4-A03C-8423B5349276}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {04017001-3222-43C4-A03C-8423B5349276}.Debug|Win32.ActiveCfg = Debug|Win32
+ {04017001-3222-43C4-A03C-8423B5349276}.Debug|Win32.Build.0 = Debug|Win32
+ {04017001-3222-43C4-A03C-8423B5349276}.Release|Win32.ActiveCfg = Release|Win32
+ {04017001-3222-43C4-A03C-8423B5349276}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/ccapi/test/deps b/src/ccapi/test/deps
new file mode 100644
index 0000000000000..e69de29bb2d1d
--- /dev/null
+++ b/src/ccapi/test/deps
diff --git a/src/ccapi/test/main.c b/src/ccapi/test/main.c
new file mode 100644
index 0000000000000..2ace967837aa1
--- /dev/null
+++ b/src/ccapi/test/main.c
@@ -0,0 +1,90 @@
+#include <stdio.h>
+#include <limits.h>
+
+// #include <Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+#include "test_ccapi_iterators.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+// cc_ccache_iterator_t cache_iterator = NULL;
+// cc_credentials_iterator_t cred_iterator = NULL;
+
+ fprintf(stdout, "Testing CCAPI against CCAPI v3 rev 8 documentation...\n");
+ fprintf(stdout, "Warning: this test suite is woefully incomplete and unpolished.\n");
+
+ T_CCAPI_INIT;
+
+ // *** ccapi v2 compat ***
+ err = check_cc_shutdown();
+ err = check_cc_get_change_time();
+ err = check_cc_open();
+ err = check_cc_create();
+ err = check_cc_close();
+ err = check_cc_destroy();
+ err = check_cc_get_cred_version();
+ err = check_cc_get_name();
+ err = check_cc_get_principal();
+ err = check_cc_set_principal();
+ err = check_cc_store();
+ err = check_cc_remove_cred();
+ err = check_cc_seq_fetch_NCs_begin();
+ err = check_cc_seq_fetch_NCs_next();
+ err = check_cc_seq_fetch_creds_begin();
+ err = check_cc_seq_fetch_creds_next();
+ err = check_cc_get_NC_info();
+
+ err = check_constants();
+
+ // *** cc_context ***
+ err = check_cc_initialize();
+ err = check_cc_context_release();
+ err = check_cc_context_get_change_time();
+ err = check_cc_context_get_default_ccache_name();
+ err = check_cc_context_open_ccache();
+ err = check_cc_context_open_default_ccache();
+ err = check_cc_context_create_ccache();
+ err = check_cc_context_create_default_ccache();
+ err = check_cc_context_create_new_ccache();
+ err = check_cc_context_new_ccache_iterator();
+ // err = check_cc_context_lock();
+ // err = check_cc_context_unlock();
+ err = check_cc_context_compare();
+
+ // *** cc_ccache ***
+ err = check_cc_ccache_release();
+ err = check_cc_ccache_destroy();
+ err = check_cc_ccache_set_default();
+ err = check_cc_ccache_get_credentials_version();
+ err = check_cc_ccache_get_name();
+ err = check_cc_ccache_get_principal();
+ err = check_cc_ccache_set_principal();
+ err = check_cc_ccache_store_credentials();
+ err = check_cc_ccache_remove_credentials();
+ err = check_cc_ccache_new_credentials_iterator();
+ // err = check_cc_ccache_lock();
+ // err = check_cc_ccache_unlock();
+ err = check_cc_ccache_get_change_time();
+ err = check_cc_ccache_get_last_default_time();
+ err = check_cc_ccache_move();
+ err = check_cc_ccache_compare();
+ err = check_cc_ccache_get_kdc_time_offset();
+ err = check_cc_ccache_set_kdc_time_offset();
+ err = check_cc_ccache_clear_kdc_time_offset();
+
+ // *** cc_ccache_iterator ***
+ err = check_cc_ccache_iterator_next();
+
+ // *** cc_credentials_iterator ***
+ err = check_cc_credentials_iterator_next();
+
+ fprintf(stdout, "\nFinished testing CCAPI. %d failure%s in total.\n", total_failure_count, (total_failure_count == 1) ? "" : "s");
+
+ return err;
+}
diff --git a/src/ccapi/test/pingtest.c b/src/ccapi/test/pingtest.c
new file mode 100644
index 0000000000000..d44839f71aca4
--- /dev/null
+++ b/src/ccapi/test/pingtest.c
@@ -0,0 +1,116 @@
+// pingtest.c
+//
+// Test RPC to server, with PING message, which exists for no other purpose than this test.
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+#include "cci_debugging.h"
+#include "CredentialsCache.h"
+#include "win-utils.h"
+
+#include "ccs_request.h"
+#define CLIENT_REQUEST_RPC_HANDLE ccs_request_IfHandle
+
+
+extern cc_int32 cci_os_ipc_thread_init (void);
+extern cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server,
+ k5_ipc_stream in_request_stream,
+ cc_int32 in_msg,
+ k5_ipc_stream* out_reply_stream);
+
+static DWORD dwTlsIndex;
+
+DWORD GetTlsIndex() {return dwTlsIndex;}
+
+RPC_STATUS send_test(char* endpoint) {
+ unsigned char* pszNetworkAddress = NULL;
+ unsigned char* pszOptions = NULL;
+ unsigned char* pszStringBinding = NULL;
+ unsigned char* pszUuid = NULL;
+ RPC_STATUS status;
+
+ status = RpcStringBindingCompose(pszUuid,
+ (RPC_CSTR)"ncalrpc",
+ pszNetworkAddress,
+ (unsigned char*)endpoint,
+ pszOptions,
+ &pszStringBinding);
+ cci_debug_printf("%s pszStringBinding = %s", __FUNCTION__, pszStringBinding);
+ if (status) {return cci_check_error(status);}
+
+ /* Set the binding handle that will be used to bind to the RPC server [the 'client']. */
+ status = RpcBindingFromStringBinding(pszStringBinding, &CLIENT_REQUEST_RPC_HANDLE);
+ if (status) {return cci_check_error(status);}
+
+ status = RpcStringFree(&pszStringBinding); // Temp var no longer needed.
+
+ if (!status) {
+ RpcTryExcept {
+ cci_debug_printf("%s calling remote procedure 'ccs_authenticate'", __FUNCTION__);
+ status = ccs_authenticate((CC_CHAR*)"DLLMAIN TEST!");
+ cci_debug_printf(" ccs_authenticate returned %d", status);
+ }
+ RpcExcept(1) {
+ status = cci_check_error(RpcExceptionCode());
+ }
+ RpcEndExcept
+ }
+
+ cci_check_error(RpcBindingFree(&CLIENT_REQUEST_RPC_HANDLE));
+
+ return (status);
+ }
+
+int main( int argc, char *argv[]) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ k5_ipc_stream send_stream = NULL;
+ k5_ipc_stream reply_stream = NULL;
+ char* message = "Hello, RPC!";
+
+
+ if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
+
+// send_test("krbcc.229026.0.ep");
+
+#if 0
+ err = cc_initialize(&context, ccapi_version_7, NULL, NULL);
+#endif
+
+ if (!err) {
+ err = cci_os_ipc_thread_init();
+ }
+ if (!err) {
+ err = krb5int_ipc_stream_new (&send_stream);
+ err = krb5int_ipc_stream_write(send_stream, message,
+ 1+strlen(message));
+ }
+
+ if (!err) {
+ err = cci_os_ipc_msg(TRUE, send_stream, CCMSG_PING, &reply_stream);
+ }
+ Sleep(10*1000);
+ cci_debug_printf("Try finishing async call.");
+
+ Sleep(INFINITE);
+ cci_debug_printf("main: return. err == %d", err);
+
+ return 0;
+ }
+
+
+
+/*********************************************************************/
+/* MIDL allocate and free */
+/*********************************************************************/
+
+void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) {
+ return(malloc(len));
+ }
+
+void __RPC_USER midl_user_free(void __RPC_FAR * ptr) {
+ free(ptr);
+ }
diff --git a/src/ccapi/test/setlib.pl b/src/ccapi/test/setlib.pl
new file mode 100755
index 0000000000000..73c85b0ee2466
--- /dev/null
+++ b/src/ccapi/test/setlib.pl
@@ -0,0 +1,10 @@
+#!perl -w
+
+$b = "lib\\win\\srctmp";
+$a = $ENV{LIB};
+if (! ($a =~ /$b/) ) {
+ print "$b Not in LIB!\n";
+ system("del a.tmp");
+ }
+else {print "$b in LIB.\n";}
+exit(0); \ No newline at end of file
diff --git a/src/ccapi/test/simple_lock_test.c b/src/ccapi/test/simple_lock_test.c
new file mode 100644
index 0000000000000..8961d99992a72
--- /dev/null
+++ b/src/ccapi/test/simple_lock_test.c
@@ -0,0 +1,91 @@
+/*
+ simple_lock_test.c
+
+ Initializes two contexts in two different threads and tries to get read locks on both at the same time.
+ Hangs at line 24.
+*/
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "test_ccapi_log.h"
+
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+#include <TargetConditionals.h>
+#endif
+
+#ifdef TARGET_OS_MAC
+#include <stdlib.h>
+#include <pthread.h>
+#include <Kerberos/CredentialsCache.h>
+#else
+#include "CredentialsCache.h"
+#endif
+
+
+void *other_thread (void) {
+ cc_int32 err;
+ cc_context_t context = NULL;
+
+ err = cc_initialize(&context, ccapi_version_7, NULL, NULL);
+
+ log_error("thread: attempting lock. may hang. err == %d", err);
+
+ if (!err) {
+ // hangs with cc_lock_read which should succeed immediately, but does not hang with write, upgrade, and downgrade, which fail immediately
+ err = cc_context_lock(context, cc_lock_read, cc_lock_noblock);
+ }
+
+ if (context) {
+ cc_context_unlock(context);
+ cc_context_release(context);
+ context = NULL;
+ }
+ log_error("thread: return. err == %d", err);
+}
+
+
+int main (int argc, char *argv[]) {
+ cc_int32 err;
+ int status;
+ cc_context_t context = NULL;
+
+#ifdef TARGET_OS_MAC
+ pthread_t thread_id;
+#endif
+
+ err = cc_initialize(&context, ccapi_version_7, NULL, NULL);
+ if (!err) {
+ err = cc_context_lock(context, cc_lock_read, cc_lock_noblock);
+ }
+
+ log_error("main: initialized and read locked context. err == %d", err);
+
+#ifdef TARGET_OS_MAC
+ status = pthread_create (&thread_id, NULL, (void *) other_thread, NULL);
+ if (status != 0) {
+ log_error("pthread_create() returned %d", status);
+ exit(-1);
+ }
+
+ pthread_join(thread_id, NULL);
+#else
+
+#endif
+
+ log_error("main: unlocking and releasing context. err == %d", err);
+
+ if (context) {
+ log_error("main: calling cc_context_unlock");
+ cc_context_unlock(context);
+ log_error("main: calling cc_context_release");
+ cc_context_release(context);
+ context = NULL;
+ }
+
+ log_error("main: return. err == %d", err);
+
+#if defined(_WIN32)
+ UNREFERENCED_PARAMETER(status); // no whining!
+#endif
+ return 0;
+}
diff --git a/src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c b/src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c
new file mode 100644
index 0000000000000..1698535fdda99
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_clear_kdc_time_offset();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_compare.c b/src/ccapi/test/test_cc_ccache_compare.c
new file mode 100644
index 0000000000000..96aaa56c78cc7
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_compare.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_compare();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_destroy.c b/src/ccapi/test/test_cc_ccache_destroy.c
new file mode 100644
index 0000000000000..95c417ca5d3ae
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_destroy.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_destroy();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_get_change_time.c b/src/ccapi/test/test_cc_ccache_get_change_time.c
new file mode 100644
index 0000000000000..a515d5bdc8b25
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_get_change_time.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_get_change_time();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_get_credentials_version.c b/src/ccapi/test/test_cc_ccache_get_credentials_version.c
new file mode 100644
index 0000000000000..f5df7c078557d
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_get_credentials_version.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_get_credentials_version();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c b/src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c
new file mode 100644
index 0000000000000..13e61165ce5ba
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_get_kdc_time_offset();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_get_last_default_time.c b/src/ccapi/test/test_cc_ccache_get_last_default_time.c
new file mode 100644
index 0000000000000..4de22e4a0ad57
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_get_last_default_time.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_get_last_default_time();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_get_name.c b/src/ccapi/test/test_cc_ccache_get_name.c
new file mode 100644
index 0000000000000..f6649974f35ce
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_get_name.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_get_name();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_get_principal.c b/src/ccapi/test/test_cc_ccache_get_principal.c
new file mode 100644
index 0000000000000..05d7c4349c1dd
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_get_principal.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_get_principal();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_iterator_next.c b/src/ccapi/test/test_cc_ccache_iterator_next.c
new file mode 100644
index 0000000000000..945a98d26d5d0
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_iterator_next.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_iterator_next();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_move.c b/src/ccapi/test/test_cc_ccache_move.c
new file mode 100644
index 0000000000000..880198c89d850
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_move.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_move();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_new_credentials_iterator.c b/src/ccapi/test/test_cc_ccache_new_credentials_iterator.c
new file mode 100644
index 0000000000000..1338e832a566a
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_new_credentials_iterator.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_new_credentials_iterator();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_release.c b/src/ccapi/test/test_cc_ccache_release.c
new file mode 100644
index 0000000000000..75d604c91c4ca
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_release.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_release();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_remove_credentials.c b/src/ccapi/test/test_cc_ccache_remove_credentials.c
new file mode 100644
index 0000000000000..679da85c5c385
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_remove_credentials.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_remove_credentials();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_set_default.c b/src/ccapi/test/test_cc_ccache_set_default.c
new file mode 100644
index 0000000000000..71bba2a46cf56
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_set_default.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_set_default();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c b/src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c
new file mode 100644
index 0000000000000..b8b21e98700e0
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_set_kdc_time_offset();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_set_principal.c b/src/ccapi/test/test_cc_ccache_set_principal.c
new file mode 100644
index 0000000000000..ec55acd71cfbc
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_set_principal.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_set_principal();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_store_credentials.c b/src/ccapi/test/test_cc_ccache_store_credentials.c
new file mode 100644
index 0000000000000..c52125bdbb1d3
--- /dev/null
+++ b/src/ccapi/test/test_cc_ccache_store_credentials.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_ccache_store_credentials();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_close.c b/src/ccapi/test/test_cc_close.c
new file mode 100644
index 0000000000000..b6bc3afaaa828
--- /dev/null
+++ b/src/ccapi/test/test_cc_close.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_close();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_context_compare.c b/src/ccapi/test/test_cc_context_compare.c
new file mode 100644
index 0000000000000..f4965af3a6854
--- /dev/null
+++ b/src/ccapi/test/test_cc_context_compare.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_context_compare();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_context_create_ccache.c b/src/ccapi/test/test_cc_context_create_ccache.c
new file mode 100644
index 0000000000000..c94294513cca2
--- /dev/null
+++ b/src/ccapi/test/test_cc_context_create_ccache.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_context_create_ccache();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_context_create_default_ccache.c b/src/ccapi/test/test_cc_context_create_default_ccache.c
new file mode 100644
index 0000000000000..c3fb4054e020c
--- /dev/null
+++ b/src/ccapi/test/test_cc_context_create_default_ccache.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_context_create_default_ccache();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_context_create_new_ccache.c b/src/ccapi/test/test_cc_context_create_new_ccache.c
new file mode 100644
index 0000000000000..d89fa4f3fa1bc
--- /dev/null
+++ b/src/ccapi/test/test_cc_context_create_new_ccache.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_context_create_new_ccache();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_context_get_change_time.c b/src/ccapi/test/test_cc_context_get_change_time.c
new file mode 100644
index 0000000000000..ad5c0a346db22
--- /dev/null
+++ b/src/ccapi/test/test_cc_context_get_change_time.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_context_get_change_time();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_context_get_default_ccache_name.c b/src/ccapi/test/test_cc_context_get_default_ccache_name.c
new file mode 100644
index 0000000000000..06fff955f4bb6
--- /dev/null
+++ b/src/ccapi/test/test_cc_context_get_default_ccache_name.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_context_get_default_ccache_name();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_context_new_ccache_iterator.c b/src/ccapi/test/test_cc_context_new_ccache_iterator.c
new file mode 100644
index 0000000000000..82209854afd2a
--- /dev/null
+++ b/src/ccapi/test/test_cc_context_new_ccache_iterator.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_context_new_ccache_iterator();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_context_open_ccache.c b/src/ccapi/test/test_cc_context_open_ccache.c
new file mode 100644
index 0000000000000..461d8df630bda
--- /dev/null
+++ b/src/ccapi/test/test_cc_context_open_ccache.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_context_open_ccache();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_context_open_default_ccache.c b/src/ccapi/test/test_cc_context_open_default_ccache.c
new file mode 100644
index 0000000000000..09c6b7c390144
--- /dev/null
+++ b/src/ccapi/test/test_cc_context_open_default_ccache.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_context_open_default_ccache();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_context_release.c b/src/ccapi/test/test_cc_context_release.c
new file mode 100644
index 0000000000000..03faf233dfd9e
--- /dev/null
+++ b/src/ccapi/test/test_cc_context_release.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_context_release();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_create.c b/src/ccapi/test/test_cc_create.c
new file mode 100644
index 0000000000000..a21c44334a77a
--- /dev/null
+++ b/src/ccapi/test/test_cc_create.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_create();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_credentials_iterator_next.c b/src/ccapi/test/test_cc_credentials_iterator_next.c
new file mode 100644
index 0000000000000..ff5f46737ccf8
--- /dev/null
+++ b/src/ccapi/test/test_cc_credentials_iterator_next.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+#include "test_ccapi_iterators.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_credentials_iterator_next();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_destroy.c b/src/ccapi/test/test_cc_destroy.c
new file mode 100644
index 0000000000000..e55a8378848ce
--- /dev/null
+++ b/src/ccapi/test/test_cc_destroy.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_destroy();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_get_NC_info.c b/src/ccapi/test/test_cc_get_NC_info.c
new file mode 100644
index 0000000000000..6b8eb374804ca
--- /dev/null
+++ b/src/ccapi/test/test_cc_get_NC_info.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_get_NC_info();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_get_change_time.c b/src/ccapi/test/test_cc_get_change_time.c
new file mode 100644
index 0000000000000..d2058fec561d6
--- /dev/null
+++ b/src/ccapi/test/test_cc_get_change_time.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_get_change_time();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_get_cred_version.c b/src/ccapi/test/test_cc_get_cred_version.c
new file mode 100644
index 0000000000000..1ff86781eb2d2
--- /dev/null
+++ b/src/ccapi/test/test_cc_get_cred_version.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_get_cred_version();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_get_name.c b/src/ccapi/test/test_cc_get_name.c
new file mode 100644
index 0000000000000..5b6e1462a72e2
--- /dev/null
+++ b/src/ccapi/test/test_cc_get_name.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_get_name();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_get_principal.c b/src/ccapi/test/test_cc_get_principal.c
new file mode 100644
index 0000000000000..a809e5d12cdf8
--- /dev/null
+++ b/src/ccapi/test/test_cc_get_principal.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_get_principal();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_initialize.c b/src/ccapi/test/test_cc_initialize.c
new file mode 100644
index 0000000000000..1669a29a3d4b2
--- /dev/null
+++ b/src/ccapi/test/test_cc_initialize.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_initialize();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_open.c b/src/ccapi/test/test_cc_open.c
new file mode 100644
index 0000000000000..83bb602019707
--- /dev/null
+++ b/src/ccapi/test/test_cc_open.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_open();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_remove_cred.c b/src/ccapi/test/test_cc_remove_cred.c
new file mode 100644
index 0000000000000..6f841bbc0067d
--- /dev/null
+++ b/src/ccapi/test/test_cc_remove_cred.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_remove_cred();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_seq_fetch_NCs_begin.c b/src/ccapi/test/test_cc_seq_fetch_NCs_begin.c
new file mode 100644
index 0000000000000..329ca26ed9959
--- /dev/null
+++ b/src/ccapi/test/test_cc_seq_fetch_NCs_begin.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_seq_fetch_NCs_begin();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_seq_fetch_NCs_next.c b/src/ccapi/test/test_cc_seq_fetch_NCs_next.c
new file mode 100644
index 0000000000000..31b5ac07c126a
--- /dev/null
+++ b/src/ccapi/test/test_cc_seq_fetch_NCs_next.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_seq_fetch_NCs_next();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_seq_fetch_creds_begin.c b/src/ccapi/test/test_cc_seq_fetch_creds_begin.c
new file mode 100644
index 0000000000000..5bb5e916455ab
--- /dev/null
+++ b/src/ccapi/test/test_cc_seq_fetch_creds_begin.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_seq_fetch_creds_begin();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_seq_fetch_creds_next.c b/src/ccapi/test/test_cc_seq_fetch_creds_next.c
new file mode 100644
index 0000000000000..83528b30e3996
--- /dev/null
+++ b/src/ccapi/test/test_cc_seq_fetch_creds_next.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_seq_fetch_creds_next();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_set_principal.c b/src/ccapi/test/test_cc_set_principal.c
new file mode 100644
index 0000000000000..04b55df9eec85
--- /dev/null
+++ b/src/ccapi/test/test_cc_set_principal.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_set_principal();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_shutdown.c b/src/ccapi/test/test_cc_shutdown.c
new file mode 100644
index 0000000000000..8756ca9f3f2c5
--- /dev/null
+++ b/src/ccapi/test/test_cc_shutdown.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_shutdown();
+ return err;
+}
diff --git a/src/ccapi/test/test_cc_store.c b/src/ccapi/test/test_cc_store.c
new file mode 100644
index 0000000000000..507b36120aaee
--- /dev/null
+++ b/src/ccapi/test/test_cc_store.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_v2.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_cc_store();
+ return err;
+}
diff --git a/src/ccapi/test/test_ccapi.bat b/src/ccapi/test/test_ccapi.bat
new file mode 100644
index 0000000000000..2d5bec53b7c39
--- /dev/null
+++ b/src/ccapi/test/test_ccapi.bat
@@ -0,0 +1,43 @@
+# test_ccapi.bat
+
+@echo "\nBeginning test of CCAPI...\n"
+@echo "\nThese tests are based on the CCAPI v3 revision 8 draft documentation.\n"
+
+#run_test simple_lock_test
+
+teststest_constants.exe
+tests\test_cc_initialize.exe
+tests\test_cc_context_get_version.exe
+exit 0
+
+tests\test_cc_context_release.exe
+tests\test_cc_context_get_change_time.exe
+tests\test_cc_context_get_default_ccache_name.exe
+tests\test_cc_context_open_ccache.exe
+tests\test_cc_context_open_default_ccache.exe
+tests\test_cc_context_create_ccache.exe
+tests\test_cc_context_create_default_ccache.exe
+tests\test_cc_context_create_new_ccache.exe
+tests\test_cc_context_new_ccache_iterator.exe
+tests\test_cc_context_compare.exe
+tests\test_cc_ccache_release.exe
+tests\test_cc_ccache_destroy.exe
+tests\test_cc_ccache_set_default.exe
+tests\test_cc_ccache_get_credentials_version.exe
+tests\test_cc_ccache_get_name.exe
+tests\test_cc_ccache_get_principal.exe
+tests\test_cc_ccache_set_principal.exe
+tests\test_cc_ccache_store_credentials.exe
+tests\test_cc_ccache_remove_credentials.exe
+tests\test_cc_ccache_new_credentials_iterator.exe
+tests\test_cc_ccache_get_change_time.exe
+tests\test_cc_ccache_get_last_default_time.exe
+tests\test_cc_ccache_move.exe
+tests\test_cc_ccache_compare.exe
+tests\test_cc_ccache_get_kdc_time_offset.exe
+tests\test_cc_ccache_set_kdc_time_offset.exe
+tests\test_cc_ccache_clear_kdc_time_offset.exe
+tests\test_cc_ccache_iterator_next.exe
+tests\test_cc_credentials_iterator_next.exe
+
+@echo "Finished testing CCAPI."
diff --git a/src/ccapi/test/test_ccapi.sh b/src/ccapi/test/test_ccapi.sh
new file mode 100755
index 0000000000000..c8959d688eb3e
--- /dev/null
+++ b/src/ccapi/test/test_ccapi.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+# run with ./test-ccapi.sh to run CCAPI tests
+
+TEST_DIR="tests"
+failure_count=0
+
+function run_test {
+ if [[ -e $TEST_DIR/$1 ]]; then
+ ./$TEST_DIR/$1
+ failure_count=`expr $failure_count + $?`
+ fi
+}
+
+printf "\nBeginning test of CCAPI...\n"
+printf "\nThese tests are based on the CCAPI v3 revision 8 draft documentation.\n"
+
+run_test simple_lock_test
+
+run_test test_constants
+
+run_test test_cc_initialize
+run_test test_cc_context_release
+run_test test_cc_context_get_change_time
+run_test test_cc_context_get_default_ccache_name
+run_test test_cc_context_open_ccache
+run_test test_cc_context_open_default_ccache
+run_test test_cc_context_create_ccache
+run_test test_cc_context_create_default_ccache
+run_test test_cc_context_create_new_ccache
+run_test test_cc_context_new_ccache_iterator
+run_test test_cc_context_compare
+
+run_test test_cc_ccache_release
+run_test test_cc_ccache_destroy
+run_test test_cc_ccache_set_default
+run_test test_cc_ccache_get_credentials_version
+run_test test_cc_ccache_get_name
+run_test test_cc_ccache_get_principal
+run_test test_cc_ccache_set_principal
+run_test test_cc_ccache_store_credentials
+run_test test_cc_ccache_remove_credentials
+run_test test_cc_ccache_new_credentials_iterator
+run_test test_cc_ccache_get_change_time
+run_test test_cc_ccache_get_last_default_time
+run_test test_cc_ccache_move
+run_test test_cc_ccache_compare
+run_test test_cc_ccache_get_kdc_time_offset
+run_test test_cc_ccache_set_kdc_time_offset
+run_test test_cc_ccache_clear_kdc_time_offset
+
+run_test test_cc_ccache_iterator_next
+
+run_test test_cc_credentials_iterator_next
+
+run_test test_cc_shutdown
+run_test test_cc_get_change_time
+run_test test_cc_open
+run_test test_cc_create
+run_test test_cc_close
+run_test test_cc_destroy
+run_test test_cc_get_cred_version
+run_test test_cc_get_name
+run_test test_cc_get_principal
+run_test test_cc_set_principal
+run_test test_cc_store
+run_test test_cc_remove_cred
+run_test test_cc_seq_fetch_NCs_begin
+run_test test_cc_seq_fetch_NCs_next
+run_test test_cc_seq_fetch_creds_begin
+run_test test_cc_seq_fetch_creds_next
+run_test test_cc_get_NC_info
+
+printf "\nFinished testing CCAPI. $failure_count failures in total.\n"
+
+exit 0 \ No newline at end of file
diff --git a/src/ccapi/test/test_ccapi_ccache.c b/src/ccapi/test/test_ccapi_ccache.c
new file mode 100644
index 0000000000000..a0fd84af10b22
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_ccache.c
@@ -0,0 +1,2034 @@
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include "test_ccapi_check.h"
+#include "test_ccapi_util.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_release(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+
+ BEGIN_TEST("cc_ccache_release");
+
+ #ifndef cc_ccache_release
+ log_error("cc_ccache_release is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+
+
+
+ if (!err) {
+ check_once_cc_ccache_release(context, ccache, ccNoError, NULL);
+ ccache = NULL;
+ }
+
+ if (context) { cc_context_release(context); }
+
+ #endif /* cc_ccache_release */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_release(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+
+ cc_int32 possible_return_values[2] = {
+ ccNoError,
+ ccErrInvalidCCache,
+ };
+
+ cc_string_t name = NULL;
+
+ err = cc_ccache_get_name(ccache, &name);
+ err = cc_ccache_release(ccache);
+ ccache = NULL;
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_release
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err && name) { // try opening released ccache to make sure it still exists
+ err = cc_context_open_ccache(context, name->data, &ccache);
+ }
+ check_if(err == ccErrCCacheNotFound, "released ccache was actually destroyed instead");
+
+ if (ccache) { cc_ccache_destroy(ccache); }
+ if (name) { cc_string_release(name); }
+
+ #endif /* cc_ccache_release */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_destroy(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+
+ BEGIN_TEST("cc_ccache_destroy");
+
+ #ifndef cc_ccache_destroy
+ log_error("cc_ccache_destroy is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+
+
+
+ if (!err) {
+ check_once_cc_ccache_destroy(context, ccache, ccNoError, NULL);
+ ccache = NULL;
+ }
+
+ if (context) { cc_context_release(context); }
+
+ #endif /* cc_ccache_destroy */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_destroy(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+
+ cc_int32 possible_return_values[2] = {
+ ccNoError,
+ ccErrInvalidCCache,
+ };
+
+ cc_string_t name = NULL;
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_destroy
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_ccache_get_name(ccache, &name);
+ err = cc_ccache_destroy(ccache);
+ ccache = NULL;
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err && name) { // try opening released ccache to make sure it still exists
+ err = cc_context_open_ccache(context, name->data, &ccache);
+ }
+ check_if(err != ccErrCCacheNotFound, "destroyed ccache was actually released instead");
+
+ if (ccache) { cc_ccache_destroy(ccache); }
+ if (name) { cc_string_release(name); }
+
+ #endif /* cc_ccache_destroy */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_set_default(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+
+ BEGIN_TEST("cc_ccache_set_default");
+
+ #ifndef cc_ccache_set_default
+ log_error("cc_ccache_set_default is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ // try when it's the only ccache (already default)
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's the only ccache (already default)");
+ }
+ if (ccache) {
+ err = cc_ccache_release(ccache);
+ ccache = NULL;
+ }
+
+ // try when it's not the only ccache (and not default)
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "baz@BAR.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's not the only ccache (and not default)");
+ }
+ if (ccache) {
+ err = cc_ccache_release(ccache);
+ ccache = NULL;
+ }
+
+ // try when it's not the only ccache (and already default)
+ if (!err) {
+ err = cc_context_open_default_ccache(context, &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's not the only ccache (and already default)");
+ }
+ if (ccache) {
+ err = cc_ccache_release(ccache);
+ ccache = NULL;
+ }
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+
+ if (context) { cc_context_release(context); }
+
+ #endif /* cc_ccache_set_default */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_set_default(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+
+ cc_int32 possible_return_values[3] = {
+ ccNoError,
+ ccErrInvalidCCache,
+ ccErrCCacheNotFound,
+ };
+
+ cc_ccache_t default_ccache = NULL;
+ cc_string_t name = NULL;
+ cc_string_t default_name = NULL;
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_set_default
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_ccache_set_default(ccache);
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ err = cc_ccache_get_name(ccache, &name);
+ }
+ if (!err) {
+ err = cc_context_open_default_ccache(context, &default_ccache);
+ }
+ if (!err) {
+ err = cc_ccache_get_name(default_ccache, &default_name);
+ }
+ if (name && default_name) {
+ check_if(strcmp(name->data, default_name->data), NULL);
+ }
+ else {
+ check_if(1, "cc_ccache_get_name failed");
+ }
+
+ if (default_ccache) { cc_ccache_release(default_ccache); }
+ //if (ccache) { cc_ccache_destroy(ccache); } // ccache is released by the caller
+ if (default_name) { cc_string_release(default_name); }
+ if (name) { cc_string_release(name); }
+
+ #endif /* cc_ccache_set_default */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_get_credentials_version(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+
+ BEGIN_TEST("cc_ccache_get_credentials_version");
+
+ #ifndef cc_ccache_get_credentials_version
+ log_error("cc_ccache_get_credentials_version is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ // try one created with v5 creds
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v5, ccNoError, "v5 creds");
+ }
+ else {
+ log_error("cc_context_create_new_ccache failed, can't complete test");
+ failure_count++;
+ }
+
+ // try it with added v4 creds
+ if (!err) {
+ err = cc_ccache_set_principal(ccache, cc_credentials_v4, "foo@BAR.ORG");
+ }
+ if (!err) {
+ check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v4_v5, ccNoError, "v5 with v4 creds added");
+ }
+ else {
+ log_error("cc_ccache_set_principal failed, can't complete test");
+ failure_count++;
+ }
+
+ if (ccache) {
+ cc_ccache_destroy(ccache);
+ ccache = NULL;
+ }
+
+ err = ccNoError;
+
+ // try one created with v4 creds
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo@BAR.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v4, ccNoError, "v4 creds");
+ }
+ else {
+ log_error("cc_context_create_new_ccache failed, can't complete test");
+ failure_count++;
+ }
+
+ // try it with added v5 creds
+ if (!err) {
+ err = cc_ccache_set_principal(ccache, cc_credentials_v5, "foo@BAR.ORG");
+ }
+ if (!err) {
+ check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v4_v5, ccNoError, "v4 with v5 creds added");
+ }
+ else {
+ log_error("cc_ccache_set_principal failed, can't complete test");
+ failure_count++;
+ }
+
+ if (ccache) {
+ cc_ccache_destroy(ccache);
+ ccache = NULL;
+ }
+
+ if (context) { cc_context_release(context); }
+
+ #endif /* cc_ccache_get_credentials_version */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_get_credentials_version(cc_ccache_t ccache, cc_uint32 expected_cred_vers, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+
+ cc_int32 possible_return_values[4] = {
+ ccNoError,
+ ccErrInvalidCCache,
+ ccErrBadParam,
+ ccErrCCacheNotFound,
+ };
+
+ cc_uint32 stored_cred_vers = 0;
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_get_credentials_version
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_ccache_get_credentials_version(ccache, &stored_cred_vers);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ check_if(stored_cred_vers != expected_cred_vers, NULL);
+ }
+
+ #endif /* cc_ccache_get_credentials_version */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_get_name(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+
+ BEGIN_TEST("cc_ccache_get_name");
+
+ #ifndef cc_ccache_get_name
+ log_error("cc_ccache_get_name is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+
+ // try with unique ccache (which happens to be default)
+ if (!err) {
+ err = cc_context_create_ccache(context, "0", cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_get_name(ccache, "0", ccNoError, "unique ccache (which happens to be default)");
+ }
+ else {
+ log_error("cc_context_create_ccache failed, can't complete test");
+ failure_count++;
+ }
+ if (ccache) {
+ cc_ccache_release(ccache);
+ ccache = NULL;
+ }
+
+ // try with unique ccache (which is not default)
+ if (!err) {
+ err = cc_context_create_ccache(context, "1", cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_get_name(ccache, "1", ccNoError, "unique ccache (which is not default)");
+ }
+ else {
+ log_error("cc_context_create_ccache failed, can't complete test");
+ failure_count++;
+ }
+
+ // try with bad param
+ if (!err) {
+ check_once_cc_ccache_get_name(ccache, NULL, ccErrBadParam, "NULL param");
+ }
+ if (ccache) {
+ cc_ccache_release(ccache);
+ ccache = NULL;
+ }
+
+ if (context) {
+ err = destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ #endif /* cc_ccache_get_name */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_get_name(cc_ccache_t ccache, const char *expected_name, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+
+ cc_int32 possible_return_values[4] = {
+ ccNoError,
+ ccErrInvalidCCache,
+ ccErrBadParam,
+ ccErrCCacheNotFound,
+ };
+
+ cc_string_t stored_name = NULL;
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_get_name
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (expected_name == NULL) { // we want to try with a NULL param
+ err = cc_ccache_get_name(ccache, NULL);
+ }
+ else {
+ err = cc_ccache_get_name(ccache, &stored_name);
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ check_if(strcmp(stored_name->data, expected_name), NULL);
+ }
+
+ if (stored_name) { cc_string_release(stored_name); }
+
+ #endif /* cc_ccache_get_name */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+cc_int32 check_once_cc_ccache_get_principal(cc_ccache_t ccache,
+ cc_uint32 cred_vers,
+ const char *expected_principal,
+ cc_int32 expected_err,
+ const char *description) {
+ cc_int32 err = ccNoError;
+ cc_string_t stored_principal = NULL;
+
+ cc_int32 possible_return_values[6] = {
+ ccNoError,
+ ccErrNoMem,
+ ccErrBadCredentialsVersion,
+ ccErrBadParam,
+ ccErrInvalidCCache,
+ ccErrCCacheNotFound,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_get_principal
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (expected_principal == NULL) { // we want to try with a NULL param
+ err = cc_ccache_get_principal(ccache, cred_vers, NULL);
+ }
+ else {
+ err = cc_ccache_get_principal(ccache, cred_vers, &stored_principal);
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ check_if(strcmp(stored_principal->data, expected_principal), "expected princ == \"%s\" stored princ == \"%s\"", expected_principal, stored_principal->data);
+ }
+
+ if (stored_principal) { cc_string_release(stored_principal); }
+
+ #endif /* cc_ccache_get_principal */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_get_principal(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+
+ BEGIN_TEST("cc_ccache_get_principal");
+
+ #ifndef cc_ccache_get_principal
+ log_error("cc_ccache_get_principal is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+
+ // try with krb5 principal
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo/BAR@BAZ.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_get_principal(ccache, cc_credentials_v5, "foo/BAR@BAZ.ORG", ccNoError, "trying to get krb5 princ for krb5 ccache");
+ }
+ else {
+ log_error("cc_context_create_new_ccache failed, can't complete test");
+ failure_count++;
+ }
+ if (ccache) {
+ cc_ccache_release(ccache);
+ ccache = NULL;
+ }
+
+ // try with krb4 principal
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo.BAR@BAZ.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_get_principal(ccache, cc_credentials_v4, "foo.BAR@BAZ.ORG", ccNoError, "trying to get krb4 princ for krb4 ccache");
+ }
+ else {
+ log_error("cc_context_create_new_ccache failed, can't complete test");
+ failure_count++;
+ }
+
+ // try with bad param
+ if (!err) {
+ // cc_ccache_t doesn't have any concept of the difference between a v4 and v5 principal
+ check_once_cc_ccache_get_principal(ccache, cc_credentials_v4_v5, "foo.BAR@BAZ.ORG",
+ ccErrBadCredentialsVersion,
+ "passing cc_credentials_v4_v5 (shouldn't be allowed)");
+ check_once_cc_ccache_get_principal(ccache, cc_credentials_v5, NULL, ccErrBadParam, "passed null out param");
+ }
+
+ if (ccache) {
+ cc_ccache_release(ccache);
+ ccache = NULL;
+ }
+
+ if (context) {
+ err = destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ #endif /* cc_ccache_get_principal */
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_set_principal(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+
+ BEGIN_TEST("cc_ccache_set_principal");
+
+ #ifndef cc_ccache_set_principal
+ log_error("cc_ccache_set_principal is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+
+ // bad params
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_set_principal(ccache, cc_credentials_v4_v5, "foo/BAZ@BAR.ORG", ccErrBadCredentialsVersion, "cc_credentials_v4_v5 (not allowed)");
+ check_once_cc_ccache_set_principal(ccache, cc_credentials_v5, NULL, ccErrBadParam, "NULL principal");
+ }
+ else {
+ log_error("cc_context_create_new_ccache failed, can't complete test");
+ failure_count++;
+ }
+ if (ccache) {
+ cc_ccache_destroy(ccache);
+ ccache = NULL;
+ }
+
+
+ // empty ccache
+
+ // replace v5 only ccache's principal
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_set_principal(ccache, cc_credentials_v5, "foo/BAZ@BAR.ORG", ccNoError, "replace v5 only ccache's principal (empty ccache)");
+ }
+ else {
+ log_error("cc_context_create_new_ccache failed, can't complete test");
+ failure_count++;
+ }
+ if (ccache) {
+ cc_ccache_destroy(ccache);
+ ccache = NULL;
+ }
+
+ // add v4 principal to v5 only ccache
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_set_principal(ccache, cc_credentials_v4, "foo.BAZ@BAR.ORG", ccNoError, "add v4 principal to v5 only ccache (empty ccache)");
+ }
+ else {
+ log_error("cc_context_create_new_ccache failed, can't complete test");
+ failure_count++;
+ }
+ if (ccache) {
+ cc_ccache_destroy(ccache);
+ ccache = NULL;
+ }
+
+ // replace v4 only ccache's principal
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo@BAZ.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_set_principal(ccache, cc_credentials_v4, "foo.BAZ@BAR.ORG", ccNoError, "replace v4 only ccache's principal (empty ccache)");
+ }
+ else {
+ log_error("cc_context_create_new_ccache failed, can't complete test");
+ failure_count++;
+ }
+ if (ccache) {
+ cc_ccache_destroy(ccache);
+ ccache = NULL;
+ }
+
+ // add v5 principal to v4 only ccache
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo@BAZ.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_set_principal(ccache, cc_credentials_v5, "foo/BAZ@BAR.ORG", ccNoError, "add v5 principal to v4 only ccache (empty ccache)");
+ }
+ else {
+ log_error("cc_context_create_new_ccache failed, can't complete test");
+ failure_count++;
+ }
+ if (ccache) {
+ cc_ccache_destroy(ccache);
+ ccache = NULL;
+ }
+
+ // with credentials
+
+ // replace v5 only ccache's principal
+
+ // add v4 principal to v5 only ccache
+
+ // replace v4 only ccache's principal
+
+ // add v5 principal to v4 only ccache
+
+ if (context) {
+ err = destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ #endif /* cc_ccache_set_principal */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_set_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+ cc_string_t stored_principal = NULL;
+
+ cc_int32 possible_return_values[6] = {
+ ccNoError,
+ ccErrNoMem,
+ ccErrInvalidCCache,
+ ccErrBadCredentialsVersion,
+ ccErrBadParam,
+ ccErrCCacheNotFound,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_set_principal
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_ccache_set_principal(ccache, cred_vers, in_principal);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ err = cc_ccache_get_principal(ccache, cred_vers, &stored_principal);
+ }
+
+ // compare stored with input
+ if (!err) {
+ check_if(strcmp(stored_principal->data, in_principal), "expected princ == \"%s\" stored princ == \"%s\"", in_principal, stored_principal->data);
+ }
+
+ if (stored_principal) { cc_string_release(stored_principal); }
+
+ #endif /* cc_ccache_set_principal */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_store_credentials(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+ cc_ccache_t dup_ccache = NULL;
+ cc_credentials_union creds_union;
+ cc_string_t name = NULL;
+
+ BEGIN_TEST("cc_ccache_store_credentials");
+
+ #ifndef cc_ccache_store_credentials
+ log_error("cc_ccache_store_credentials is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+
+ // cred with matching version and realm
+ if (!err) {
+ err = new_v5_creds_union(&creds_union, "BAR.ORG");
+ }
+
+ if (!err) {
+ check_once_cc_ccache_store_credentials(ccache, &creds_union, ccNoError, "ok creds");
+ }
+
+ if (&creds_union) { release_v5_creds_union(&creds_union); }
+
+ // try with bad params
+ check_once_cc_ccache_store_credentials(ccache, NULL, ccErrBadParam, "NULL creds param");
+
+ // invalid creds
+ if (!err) {
+ err = new_v5_creds_union(&creds_union, "BAR.ORG");
+ }
+
+ if (!err) {
+ if (creds_union.credentials.credentials_v5->client) {
+ free(creds_union.credentials.credentials_v5->client);
+ creds_union.credentials.credentials_v5->client = NULL;
+ }
+ check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrBadParam, "invalid creds (NULL client string)");
+ }
+
+ if (&creds_union) { release_v5_creds_union(&creds_union); }
+
+ // bad creds version
+ if (!err) {
+ err = new_v5_creds_union(&creds_union, "BAR.ORG");
+ }
+
+ if (!err) {
+ creds_union.version = cc_credentials_v4_v5;
+ check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrBadCredentialsVersion, "v4_v5 creds (invalid) into a ccache with only v5 princ");
+ creds_union.version = cc_credentials_v4;
+ check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrBadCredentialsVersion, "v4 creds into a ccache with only v5 princ");
+ creds_union.version = cc_credentials_v5;
+ }
+
+ if (&creds_union) { release_v5_creds_union(&creds_union); }
+
+ // non-existent ccache
+ if (ccache) {
+ err = cc_ccache_get_name(ccache, &name);
+ if (!err) {
+ err = cc_context_open_ccache(context, name->data, &dup_ccache);
+ }
+ if (name) { cc_string_release(name); }
+ if (dup_ccache) { cc_ccache_destroy(dup_ccache); }
+ }
+
+ if (!err) {
+ err = new_v5_creds_union(&creds_union, "BAR.ORG");
+ }
+
+ if (!err) {
+ check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrInvalidCCache, "invalid ccache");
+ }
+
+ if (&creds_union) { release_v5_creds_union(&creds_union); }
+ if (ccache) { cc_ccache_release(ccache); }
+ if (context) {
+ destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ #endif /* cc_ccache_store_credentials */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_store_credentials(cc_ccache_t ccache, const cc_credentials_union *credentials, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+ cc_credentials_iterator_t creds_iterator = NULL;
+ cc_credentials_t creds = NULL;
+
+ cc_int32 possible_return_values[6] = {
+ ccNoError,
+ ccErrBadParam,
+ ccErrInvalidCCache,
+ ccErrInvalidCredentials,
+ ccErrBadCredentialsVersion,
+ ccErrCCacheNotFound,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_store_credentials
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_ccache_store_credentials(ccache, credentials);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ // make sure credentials were truly stored
+ if (!err) {
+ err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator);
+ }
+ while (!err) {
+ err = cc_credentials_iterator_next(creds_iterator, &creds);
+ if (creds) {
+ if (compare_v5_creds_unions(credentials, creds->data) == 0) {
+ break;
+ }
+ cc_credentials_release(creds);
+ creds = NULL;
+ }
+ }
+
+ if (err == ccIteratorEnd) {
+ check_if((creds != NULL), "stored credentials not found in ccache");
+ err = ccNoError;
+ }
+ if (creds) { cc_credentials_release(creds); }
+
+ #endif /* cc_ccache_store_credentials */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_remove_credentials(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+ cc_ccache_t dup_ccache = NULL;
+ cc_credentials_t creds_array[10];
+ cc_credentials_t creds = NULL;
+ cc_credentials_union creds_union;
+ cc_credentials_iterator_t creds_iterator = NULL;
+ cc_string_t name = NULL;
+ unsigned int i;
+
+ BEGIN_TEST("cc_ccache_remove_credentials");
+
+ #ifndef cc_ccache_remove_credentials
+ log_error("cc_ccache_remove_credentials is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+
+ // store 10 creds and retrieve their cc_credentials_t representations
+ for(i = 0; !err && (i < 10); i++) {
+ new_v5_creds_union(&creds_union, "BAR.ORG");
+ err = cc_ccache_store_credentials(ccache, &creds_union);
+ if (&creds_union) { release_v5_creds_union(&creds_union); }
+ }
+ if (err) {
+ log_error("failure to store creds_union in remove_creds test");
+ }
+ if (!err) {
+ err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator);
+ }
+ i = 0;
+ while (!err && i < 10) {
+ err = cc_credentials_iterator_next(creds_iterator, &creds);
+ if (creds) {
+ creds_array[i++] = creds;
+ creds = NULL;
+ }
+ }
+ if (err == ccIteratorEnd) { err = ccNoError; }
+
+ // remove 10 valid creds
+ for (i = 0; !err && (i < 8); i++) {
+ check_once_cc_ccache_remove_credentials(ccache, creds_array[i], ccNoError, "10 ok creds");
+ }
+
+ // NULL param
+ check_once_cc_ccache_remove_credentials(ccache, NULL, ccErrBadParam, "NULL creds in param");
+
+ // non-existent creds (remove same one twice)
+ check_once_cc_ccache_remove_credentials(ccache, creds_array[0], ccErrInvalidCredentials, "removed same creds twice");
+
+ // non-existent ccache
+ if (ccache) {
+ err = cc_ccache_get_name(ccache, &name);
+ if (!err) {
+ err = cc_context_open_ccache(context, name->data, &dup_ccache);
+ }
+ if (name) { cc_string_release(name); }
+ if (dup_ccache) { cc_ccache_destroy(dup_ccache); }
+ }
+
+ if (!err) {
+ err = new_v5_creds_union(&creds_union, "BAR.ORG");
+ }
+
+ if (!err) {
+ check_once_cc_ccache_remove_credentials(ccache, creds_array[8], ccErrInvalidCCache, "invalid ccache");
+ }
+
+ for(i = 0; i < 10; i++) {
+ if (creds_array[i]) { cc_credentials_release(creds_array[i]); }
+ }
+
+ if (ccache) { cc_ccache_release(ccache); }
+ if (context) {
+ destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ #endif /* cc_ccache_remove_credentials */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_remove_credentials(cc_ccache_t ccache, cc_credentials_t in_creds, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+ cc_credentials_iterator_t creds_iterator = NULL;
+ cc_credentials_t creds = NULL;
+
+ cc_int32 possible_return_values[6] = {
+ ccNoError,
+ ccErrBadParam,
+ ccErrInvalidCCache,
+ ccErrInvalidCredentials,
+ ccErrCredentialsNotFound,
+ ccErrCCacheNotFound,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_remove_credentials
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_ccache_remove_credentials(ccache, in_creds);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ // make sure credentials were truly removed
+ if (!err) {
+ err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator);
+ }
+ while (!err) {
+ err = cc_credentials_iterator_next(creds_iterator, &creds);
+ if (creds) {
+ if (compare_v5_creds_unions(in_creds->data, creds->data) == 0) {
+ break;
+ }
+ cc_credentials_release(creds);
+ creds = NULL;
+ }
+ }
+
+ if (err == ccIteratorEnd) {
+ err = ccNoError;
+ }
+ else {
+ check_if((creds != NULL), "credentials not removed from ccache");
+ }
+ if (creds) { cc_credentials_release(creds); }
+
+ #endif /* cc_ccache_remove_credentials */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_new_credentials_iterator(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+ cc_ccache_t dup_ccache = NULL;
+ cc_credentials_iterator_t creds_iterator = NULL;
+ cc_string_t name = NULL;
+
+ BEGIN_TEST("cc_ccache_new_credentials_iterator");
+
+ #ifndef cc_ccache_new_credentials_iterator
+ log_error("cc_ccache_new_credentials_iterator is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+
+ // valid params
+ if (!err) {
+ check_once_cc_ccache_new_credentials_iterator(ccache, &creds_iterator, ccNoError, "valid params");
+ }
+ if (creds_iterator) {
+ cc_credentials_iterator_release(creds_iterator);
+ creds_iterator = NULL;
+ }
+
+ // NULL out param
+ if (!err) {
+ check_once_cc_ccache_new_credentials_iterator(ccache, NULL, ccErrBadParam, "NULL out iterator param");
+ }
+ if (creds_iterator) {
+ cc_credentials_iterator_release(creds_iterator);
+ creds_iterator = NULL;
+ }
+
+ // non-existent ccache
+ if (ccache) {
+ err = cc_ccache_get_name(ccache, &name);
+ if (!err) {
+ err = cc_context_open_ccache(context, name->data, &dup_ccache);
+ }
+ if (name) { cc_string_release(name); }
+ if (dup_ccache) { cc_ccache_destroy(dup_ccache); }
+ }
+
+ if (!err) {
+ check_once_cc_ccache_new_credentials_iterator(ccache, &creds_iterator, ccErrInvalidCCache, "invalid ccache");
+ }
+
+ if (creds_iterator) {
+ cc_credentials_iterator_release(creds_iterator);
+ creds_iterator = NULL;
+ }
+ if (ccache) { cc_ccache_release(ccache); }
+ if (context) {
+ destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ #endif /* cc_ccache_new_credentials_iterator */
+
+ END_TEST_AND_RETURN
+}
+
+
+cc_int32 check_once_cc_ccache_new_credentials_iterator(cc_ccache_t ccache, cc_credentials_iterator_t *iterator, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+
+ cc_int32 possible_return_values[5] = {
+ ccNoError,
+ ccErrBadParam,
+ ccErrNoMem,
+ ccErrCCacheNotFound,
+ ccErrInvalidCCache,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_new_credentials_iterator
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_ccache_new_credentials_iterator(ccache, iterator);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ #endif /* cc_ccache_new_credentials_iterator */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+cc_int32 check_once_cc_ccache_get_change_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+ cc_time_t this_time = 0;
+
+ cc_int32 possible_return_values[4] = {
+ ccNoError,
+ ccErrInvalidCCache,
+ ccErrBadParam,
+ ccErrCCacheNotFound,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_get_change_time
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (last_time == NULL) {
+ err = cc_ccache_get_change_time(ccache, NULL); // passed NULL to compare against because intention is actually to pass bad param instead
+ } else {
+ err = cc_ccache_get_change_time(ccache, &this_time);
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if ((!err) && last_time) {
+ check_if(this_time <= *last_time, "change time didn't increase when expected");
+ *last_time = this_time;
+ }
+
+ #endif /* cc_ccache_get_change_time */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_get_change_time(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t dummy_ccache = NULL;
+ cc_ccache_t ccache = NULL;
+ cc_credentials_union creds_union;
+ cc_credentials_iterator_t creds_iterator = NULL;
+ cc_credentials_t credentials = NULL;
+ cc_time_t last_time = 0;
+
+ BEGIN_TEST("cc_ccache_get_change_time");
+
+ #ifndef cc_ccache_get_change_time
+ log_error("cc_ccache_get_change_time is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+
+ // create some ccaches (so that the one we keep around as 'ccache' is not default)
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+ if (ccache) {
+ cc_ccache_release(ccache);
+ }
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache);
+ }
+
+ // change it in all the ways it can change, checking after each
+
+ // the ccache is created
+ if (!err) {
+ check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "new ccache (change time should be > 0)");
+ }
+
+ // the ccache is made default
+ if (!err) {
+ err = cc_ccache_set_default(ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "non-default ccache became default");
+ }
+
+ // the ccache is made not-default
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "something@ELSE.COM", &dummy_ccache);
+ }
+ if (!err) {
+ err = cc_ccache_set_default(dummy_ccache);
+ }
+ if (dummy_ccache) {
+ cc_ccache_release(dummy_ccache);
+ }
+ if (!err) {
+ check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "default ccache became non-default");
+ }
+
+ // try with bad params
+
+ // NULL out param
+ if (!err) {
+ check_once_cc_ccache_get_change_time(ccache, NULL, ccErrBadParam, "NULL out param for time");
+ }
+
+ // store a credential
+ if (!err) {
+ new_v5_creds_union(&creds_union, "BAR.ORG");
+ err = cc_ccache_store_credentials(ccache, &creds_union);
+ release_v5_creds_union(&creds_union);
+ }
+ check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "stored new credential");
+
+ if (!err) {
+ // change principal (fails with ccErrBadInternalMessage)
+ err = cc_ccache_set_principal(ccache, cc_credentials_v5, "foo@BAR.ORG");
+ if (err) {
+ log_error("failed to change ccache's principal - %s (%d)", translate_ccapi_error(err), err);
+ failure_count++;
+ err = ccNoError;
+ }
+ }
+ check_once_cc_context_get_change_time(context, &last_time, ccNoError, "after changing a principle");
+
+ // remove a credential
+ if (!err) {
+ err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator);
+ }
+ if (!err) {
+ err = cc_credentials_iterator_next(creds_iterator, &credentials);
+ }
+ if (err == ccIteratorEnd) {
+ err = ccNoError;
+ }
+ if (!err) {
+ err = cc_ccache_remove_credentials(ccache, credentials);
+ }
+ check_once_cc_context_get_change_time(context, &last_time, ccNoError, "after removing a credential");
+
+
+ // invalid ccache
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+ if (!err) {
+ check_once_cc_ccache_get_change_time(ccache, &last_time, ccErrInvalidCCache, "getting change time on destroyed ccache");
+ }
+
+ if (ccache) { cc_ccache_release(ccache); }
+ if (context) {
+ destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ #endif /* cc_ccache_get_change_time */
+
+ END_TEST_AND_RETURN
+}
+
+
+// ---------------------------------------------------------------------------
+
+cc_int32 check_once_cc_ccache_get_last_default_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+ cc_time_t this_time = 0;
+
+ cc_int32 possible_return_values[5] = {
+ ccNoError,
+ ccErrInvalidCCache,
+ ccErrBadParam,
+ ccErrNeverDefault,
+ ccErrCCacheNotFound,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_get_last_default_time
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (last_time == NULL) {
+ err = cc_ccache_get_last_default_time(ccache, NULL); // passed NULL to compare against because intention is actually to pass bad param instead
+ } else {
+ err = cc_ccache_get_last_default_time(ccache, &this_time);
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err && last_time) {
+ check_if(this_time > *last_time, "last default time isn't as expected");
+ *last_time = this_time;
+ }
+
+ #endif /* cc_ccache_get_last_default_time */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_get_last_default_time(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache_1 = NULL;
+ cc_ccache_t ccache_2 = NULL;
+ cc_time_t last_time_1 = 0;
+ cc_time_t last_time_2 = 0;
+ cc_string_t name = NULL;
+
+ BEGIN_TEST("cc_ccache_get_last_default_time");
+
+ #ifndef cc_ccache_get_last_default_time
+ log_error("cc_ccache_get_last_default_time is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+
+ // create 2 ccaches
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@ONE.ORG", &ccache_1);
+ }
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@TWO.ORG", &ccache_2);
+ }
+
+ if (!err) {
+ err = cc_ccache_get_change_time(ccache_1, &last_time_1);
+ }
+
+ // since we destroyed all ccaches before creating these two,
+ // ccache_1 should be default and ccache_2 should never have been default
+ if (!err) {
+ check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccNoError, "ccache_1 default at creation");
+ check_once_cc_ccache_get_last_default_time(ccache_2, &last_time_2, ccErrNeverDefault, "ccache_2 never default");
+ }
+
+ // make ccache_2 default and check each of their times again
+ if (!err) {
+ err = cc_ccache_set_default(ccache_2);
+ }
+ if (!err) {
+ err = cc_ccache_get_change_time(ccache_2, &last_time_2);
+ }
+ if (!err) {
+ check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccNoError, "ccache_1 no longer default");
+ check_once_cc_ccache_get_last_default_time(ccache_2, &last_time_2, ccNoError, "ccache_2 newly default");
+ }
+
+ // NULL param
+ if (!err) {
+ check_once_cc_ccache_get_last_default_time(ccache_1, NULL, ccErrBadParam, "NULL out param");
+ }
+
+ // non-existent ccache
+ if (ccache_2) {
+ cc_ccache_release(ccache_2);
+ ccache_2 = NULL;
+ }
+ if (!err) {
+ err = cc_ccache_get_name(ccache_1, &name);
+ }
+ if (!err) {
+ err = cc_context_open_ccache(context, name->data, &ccache_2);
+ }
+ if (!err) {
+ cc_ccache_destroy(ccache_2);
+ ccache_2 = NULL;
+ }
+
+ if (!err) {
+ check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccErrInvalidCCache, "destroyed ccache");
+ }
+
+ if (ccache_1) { cc_ccache_release(ccache_1); }
+
+ if (context) {
+ destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ #endif /* cc_ccache_get_last_default_time */
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_move(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t source = NULL;
+ cc_ccache_t destination = NULL;
+
+ cc_credentials_union creds_union;
+ unsigned int i = 0;
+
+ BEGIN_TEST("cc_ccache_move");
+
+ #ifndef cc_ccache_move
+ log_error("cc_ccache_move is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+
+ // create 2 ccaches
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@ONE.ORG", &source);
+ }
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@TWO.ORG", &destination);
+ }
+
+ // store credentials in each
+ for (i = 0; !err && (i < 10); i++) {
+ new_v5_creds_union(&creds_union, "ONE.ORG");
+ err = cc_ccache_store_credentials(source, &creds_union);
+ }
+ for (i = 0; !err && (i < 10); i++) {
+ new_v5_creds_union(&creds_union, "TWO.ORG");
+ err = cc_ccache_store_credentials(destination, &creds_union);
+ }
+
+ // move source into destination
+ if (!err) {
+ check_once_cc_ccache_move(source, destination, ccNoError, "valid params");
+ }
+
+ // NULL param
+ if (!err) {
+ check_once_cc_ccache_move(destination, NULL, ccErrBadParam, "NULL destination param");
+ }
+
+ // non-existent ccache
+ if (!err) {
+ check_once_cc_ccache_move(destination, source, ccErrInvalidCCache, "recently moved source as destination param");
+ }
+
+ if (source) { cc_ccache_release(source); }
+ if (destination) { cc_ccache_release(destination); }
+
+ if (context) {
+ destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ #endif /* cc_ccache_move */
+
+ END_TEST_AND_RETURN
+
+
+}
+
+cc_int32 check_once_cc_ccache_move(cc_ccache_t source, cc_ccache_t destination, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+ cc_credentials_t dst_creds[10] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, };
+ cc_credentials_t creds = NULL;
+ cc_credentials_iterator_t cred_iterator = NULL;
+ unsigned int i = 0;
+
+ cc_string_t src_principal = NULL;
+ cc_string_t dst_principal = NULL;
+
+ cc_int32 possible_return_values[4] = {
+ ccNoError,
+ ccErrBadParam,
+ ccErrInvalidCCache,
+ ccErrCCacheNotFound,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_move
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (destination) {
+ // verify all of destination's credentials are no longer there (save a list and call remove_cred for each, expecting an err in response)
+ if (!err) {
+ err = cc_ccache_new_credentials_iterator(destination, &cred_iterator);
+ }
+ while (!err && (i < 10)) {
+ err = cc_credentials_iterator_next(cred_iterator, &creds);
+ if (creds) {
+ dst_creds[i++] = creds;
+ }
+ }
+ if (err == ccIteratorEnd) {
+ err = ccNoError;
+ }
+ if (cred_iterator) {
+ cc_credentials_iterator_release(cred_iterator);
+ cred_iterator = NULL;
+ }
+
+ // verify that destination's principal has changed to source's (strcmp)
+ if (!err) {
+ err = cc_ccache_get_principal(source, cc_credentials_v5, &src_principal);
+ }
+ }
+
+
+ if (!err) {
+ err = cc_ccache_move(source, destination);
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+
+ if (!err) {
+ // verify all of destination's credentials are no longer there (save a list and call remove_cred for each, expecting an err in response)
+ i = 0;
+ while (dst_creds[i] && (i < 10)) {
+ err = cc_ccache_remove_credentials(destination, dst_creds[i]);
+ check_if(!(!err || err == ccErrCredentialsNotFound || ccErrInvalidCredentials), "credentials in destination not removed as promised");
+ cc_credentials_release(dst_creds[i]);
+ i++;
+ }
+ err = ccNoError;
+ }
+
+ // verify that destination's principal has changed to source's (strcmp)
+ if (!err) {
+ err = cc_ccache_get_principal(destination, cc_credentials_v5, &dst_principal);
+ }
+ if (!err) {
+ check_if(strcmp(src_principal->data, dst_principal->data), "destination principal not overwritten by source");
+ }
+
+ // verify that handles for source are no longer valid (get_change_time)
+ if (src_principal) {
+ cc_string_release(src_principal);
+ src_principal = NULL;
+ }
+ if (!err) {
+ err = cc_ccache_get_principal(source, cc_credentials_v5, &src_principal);
+ check_if(err != ccErrInvalidCCache, "source ccache was not invalidated after move");
+ }
+
+
+ if (cred_iterator) { cc_credentials_iterator_release(cred_iterator); }
+ if (src_principal) { cc_string_release(src_principal); }
+ if (dst_principal) { cc_string_release(dst_principal); }
+
+ #endif /* cc_ccache_move */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_compare(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache_a = NULL;
+ cc_ccache_t ccache_b = NULL;
+ cc_uint32 equal = 0;
+
+ BEGIN_TEST("cc_ccache_compare");
+
+ #ifndef cc_ccache_compare
+ log_error("cc_ccache_compare is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache_a);
+ }
+ if (!err) {
+ err = cc_context_open_default_ccache(context, &ccache_b);
+ }
+
+ equal = 1;
+ check_once_cc_ccache_compare(ccache_a, ccache_a, &equal, ccNoError, "compare ccache with same pointer");
+ equal = 1;
+ check_once_cc_ccache_compare(ccache_a, ccache_b, &equal, ccNoError, "compare different handles to same ccache");
+
+ if (ccache_b) {
+ cc_ccache_release(ccache_b);
+ ccache_b = NULL;
+ }
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "baz@BAR.ORG", &ccache_b);
+ }
+ equal = 0;
+ check_once_cc_ccache_compare(ccache_a, ccache_b, &equal, ccNoError, "compare different ccaches");
+ check_once_cc_ccache_compare(ccache_a, NULL, &equal, ccErrBadParam, "NULL compare_to ccache");
+ check_once_cc_ccache_compare(ccache_a, ccache_b, NULL, ccErrBadParam, "NULL out param");
+
+ if (ccache_a) { cc_ccache_release(ccache_a); }
+ if (ccache_b) { cc_ccache_release(ccache_b); }
+
+ if (context) {
+ err = destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ #endif /* cc_ccache_compare */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_compare(cc_ccache_t ccache, cc_ccache_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+ cc_uint32 actually_equal = 0;
+
+ cc_int32 possible_return_values[4] = {
+ ccNoError,
+ ccErrInvalidContext,
+ ccErrBadParam,
+ ccErrServerUnavailable,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_compare
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (equal) {
+ actually_equal = *equal;
+ }
+
+ err = cc_ccache_compare(ccache, compare_to, equal);
+
+ if (!err && equal) {
+ if (actually_equal) {
+ check_if(actually_equal != *equal, "equal ccaches not considered equal");
+ }
+ else {
+ check_if(actually_equal != *equal, "non-equal ccaches considered equal");
+ }
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ #endif /* cc_ccache_compare */
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_get_kdc_time_offset(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+ cc_time_t time_offset = 0;
+
+ BEGIN_TEST("cc_ccache_get_kdc_time_offset");
+
+ #ifndef cc_ccache_get_kdc_time_offset
+ log_error("cc_ccache_get_kdc_time_offset is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+
+ time_offset = 0;
+ check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, &time_offset, ccErrTimeOffsetNotSet, "brand new ccache (offset not yet set)");
+
+ time_offset = 10;
+ if (!err) {
+ err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, time_offset);
+ }
+ if (!err) {
+ check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, &time_offset, ccNoError, "offset set for v5 but not v4");
+ }
+ if (!err) {
+ check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v4, &time_offset, ccErrTimeOffsetNotSet, "asking for v4 offset when only v5 is set");
+ }
+ if (!err) {
+ err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4, time_offset);
+ }
+ if (!err) {
+ check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v4, &time_offset, ccNoError, "asking for v4 offset when v4 and v5 are set");
+ }
+
+
+ check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, NULL, ccErrBadParam, "NULL time_offset out param");
+ check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v4_v5, &time_offset, ccErrBadCredentialsVersion, "v4_v5 creds_vers in param (invalid)");
+
+ if (ccache) { cc_ccache_release(ccache); }
+
+ if (context) {
+ err = destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ #endif /* cc_ccache_get_kdc_time_offset */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_get_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t *time_offset, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+ cc_time_t expected_offset;
+
+ cc_int32 possible_return_values[7] = {
+ ccNoError,
+ ccErrTimeOffsetNotSet,
+ ccErrCCacheNotFound,
+ ccErrInvalidCCache,
+ ccErrBadParam,
+ ccErrServerUnavailable,
+ ccErrBadCredentialsVersion,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_get_kdc_time_offset
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (time_offset) {
+ expected_offset = *time_offset;
+ }
+
+ err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, time_offset);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err && time_offset) {
+ check_if(*time_offset != expected_offset, "kdc time offset doesn't match expected value");
+ }
+
+ #endif /* cc_ccache_get_kdc_time_offset */
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_set_kdc_time_offset(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+
+ BEGIN_TEST("cc_ccache_set_kdc_time_offset");
+
+ #ifndef cc_ccache_set_kdc_time_offset
+ log_error("cc_ccache_set_kdc_time_offset is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+
+ check_once_cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, 0, ccNoError, "first time setting offset (v5)");
+ check_once_cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4, 0, ccNoError, "first time setting offset (v4)");
+
+ check_once_cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4_v5, 0, ccErrBadCredentialsVersion, "invalid creds_vers (v4_v5)");
+
+ if (ccache) { cc_ccache_release(ccache); }
+
+ if (context) {
+ err = destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ #endif /* cc_ccache_set_kdc_time_offset */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_set_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t time_offset, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+ cc_time_t stored_offset = 0;
+
+ cc_int32 possible_return_values[6] = {
+ ccNoError,
+ ccErrCCacheNotFound,
+ ccErrInvalidCCache,
+ ccErrBadParam,
+ ccErrServerUnavailable,
+ ccErrBadCredentialsVersion,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_set_kdc_time_offset
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_ccache_set_kdc_time_offset(ccache, credentials_version, time_offset);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, &stored_offset);
+ }
+
+ if (!err) {
+ check_if(time_offset != stored_offset, "kdc time offset doesn't match expected value");
+ }
+
+ #endif /* cc_ccache_set_kdc_time_offset */
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_clear_kdc_time_offset(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+
+ BEGIN_TEST("cc_ccache_clear_kdc_time_offset");
+
+ #ifndef cc_ccache_clear_kdc_time_offset
+ log_error("cc_ccache_clear_kdc_time_offset is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+
+ check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v5, ccNoError, "clearing an offset that was never set (v5)");
+ check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v4, ccNoError, "clearing an offset that was never set (v4)");
+
+ err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, 0);
+ err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4, 0);
+
+ check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v5, ccNoError, "clearing v5");
+ check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v4, ccNoError, "clearing v4");
+
+ check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v4_v5, ccErrBadCredentialsVersion, "bad in param creds vers (v4_v5)");
+
+ if (ccache) { cc_ccache_release(ccache); }
+
+ if (context) {
+ err = destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ #endif /* cc_ccache_clear_kdc_time_offset */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_clear_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+ cc_time_t stored_offset = 0;
+
+ cc_int32 possible_return_values[6] = {
+ ccNoError,
+ ccErrCCacheNotFound,
+ ccErrInvalidCCache,
+ ccErrBadParam,
+ ccErrServerUnavailable,
+ ccErrBadCredentialsVersion,
+ };
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_ccache_clear_kdc_time_offset
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_ccache_clear_kdc_time_offset(ccache, credentials_version);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, &stored_offset);
+ check_if(err != ccErrTimeOffsetNotSet, "time offset not cleared");
+ }
+
+ #endif /* cc_ccache_clear_kdc_time_offset */
+
+ return err;
+}
diff --git a/src/ccapi/test/test_ccapi_ccache.h b/src/ccapi/test/test_ccapi_ccache.h
new file mode 100644
index 0000000000000..ecb06219788ee
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_ccache.h
@@ -0,0 +1,49 @@
+#ifndef _TEST_CCAPI_CCACHE_H_
+#define _TEST_CCAPI_CCACHE_H_
+
+#include "test_ccapi_globals.h"
+
+int check_cc_ccache_release(void);
+cc_int32 check_once_cc_ccache_release(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description);
+int check_cc_ccache_destroy(void);
+cc_int32 check_once_cc_ccache_destroy(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description);
+int check_cc_ccache_set_default(void);
+cc_int32 check_once_cc_ccache_set_default(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description);
+int check_cc_ccache_get_credentials_version(void);
+cc_int32 check_once_cc_ccache_get_credentials_version(cc_ccache_t ccache, cc_uint32 expected_cred_vers, cc_int32 expected_err, const char *description);
+int check_cc_ccache_get_name(void);
+cc_int32 check_once_cc_ccache_get_name(cc_ccache_t ccache, const char *expected_name, cc_int32 expected_err, const char *description);
+int check_cc_ccache_get_principal(void);
+cc_int32 check_once_cc_ccache_get_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *expected_principal, cc_int32 expected_err, const char *description);
+int check_cc_ccache_set_principal(void);
+cc_int32 check_once_cc_ccache_set_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_store_credentials(void);
+cc_int32 check_once_cc_ccache_store_credentials(cc_ccache_t ccache, const cc_credentials_union *credentials, cc_int32 expected_err, const char *description);
+int check_cc_ccache_remove_credentials(void);
+cc_int32 check_once_cc_ccache_remove_credentials(cc_ccache_t ccache, cc_credentials_t in_creds, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_new_credentials_iterator(void);
+cc_int32 check_once_cc_ccache_new_credentials_iterator(cc_ccache_t ccache, cc_credentials_iterator_t *iterator, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_get_change_time(void);
+cc_int32 check_once_cc_ccache_get_change_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description);
+int check_cc_ccache_get_last_default_time(void);
+cc_int32 check_once_cc_ccache_get_last_default_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_move(void);
+cc_int32 check_once_cc_ccache_move(cc_ccache_t source, cc_ccache_t destination, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_compare(void);
+cc_int32 check_once_cc_ccache_compare(cc_ccache_t ccache, cc_ccache_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_get_kdc_time_offset(void);
+cc_int32 check_once_cc_ccache_get_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t *time_offset, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_set_kdc_time_offset(void);
+cc_int32 check_once_cc_ccache_set_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t time_offset, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_clear_kdc_time_offset(void);
+cc_int32 check_once_cc_ccache_clear_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_int32 expected_err, const char *description);
+
+#endif /* _TEST_CCAPI_CCACHE_H_ */
diff --git a/src/ccapi/test/test_ccapi_check.c b/src/ccapi/test/test_ccapi_check.c
new file mode 100644
index 0000000000000..7f55b45573ec4
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_check.c
@@ -0,0 +1,37 @@
+#include "test_ccapi_check.h"
+
+int _check_if(int expression, const char *file, int line, const char *expression_string, const char *format, ...) {
+ if (expression) {
+ failure_count++;
+ // call with NULL format to get a generic error message
+ if (format == NULL) {
+ _log_error(file, line, expression_string);
+ }
+ // call with format and varargs for a more useful error message
+ else {
+ va_list ap;
+ va_start(ap, format);
+ _log_error_v(file, line, format, ap);
+ va_end(ap);
+ }
+
+ if (current_test_activity) {
+ fprintf(stdout, " (%s)", current_test_activity);
+ }
+ }
+
+ return (expression != 0);
+}
+
+int array_contains_int(cc_int32 *array, int size, cc_int32 value) {
+ if (array != NULL && size > 0) {
+ int i = 0;
+ while (i < size && array[i] != value) {
+ i++;
+ }
+ if (i < size) {
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/src/ccapi/test/test_ccapi_check.h b/src/ccapi/test/test_ccapi_check.h
new file mode 100644
index 0000000000000..0a953481a4068
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_check.h
@@ -0,0 +1,43 @@
+#ifndef _TEST_CCAPI_CHECK_H_
+#define _TEST_CCAPI_CHECK_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "test_ccapi_log.h"
+#include "test_ccapi_globals.h"
+
+int _check_if(int expression, const char *file, int line, const char *expression_string, const char *format, ...);
+
+#define check_int(a, b) \
+ check_if(a != b, NULL)
+
+/*
+ * if expression evaluates to true, check_if increments the failure_count and prints:
+ *
+ * check_if(a!=a, NULL);
+ * ==> "/path/to/file:line: a!=a"
+ *
+ * check_if(a!=a, "This shouldn't be happening");
+ * ==> "/path/to/file:line: This shouldn't be happening"
+ *
+ * check_if(a!=a, "This has happened %d times now", 3);
+ * ==> "/path/to/file:line: This has happened 3 times now"
+*/
+
+#define check_if(expression, format, ...) \
+ _check_if(expression, __FILE__, __LINE__, #expression, format , ## __VA_ARGS__)
+
+#define check_if_not(expression, format, ...) \
+ check_if(!(expression), format, ## __VA_ARGS__)
+
+// first check if err is what we were expecting to get back
+// then check if err is even in the set of errors documented for the function
+#define check_err(err, expected_err, possible_return_values) \
+ do { \
+ check_if(err != expected_err, "unexpected error %s (%d), expected %s (%d)", translate_ccapi_error(err), err, translate_ccapi_error(expected_err), expected_err); \
+ check_if_not(array_contains_int(possible_return_values, possible_ret_val_count, err), "error not documented as a possible return value: %s (%d)", translate_ccapi_error(err), err); \
+ } while( 0 )
+
+int array_contains_int(cc_int32 *array, int size, cc_int32 value);
+
+#endif /* _TEST_CCAPI_CHECK_H_ */
diff --git a/src/ccapi/test/test_ccapi_constants.c b/src/ccapi/test/test_ccapi_constants.c
new file mode 100644
index 0000000000000..9f2aecbc278e6
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_constants.c
@@ -0,0 +1,66 @@
+#include "test_ccapi_constants.h"
+#include "test_ccapi_globals.h"
+#include "test_ccapi_check.h"
+
+int check_constants(void) {
+ BEGIN_TEST("constants");
+ /* API versions */
+
+ check_int(ccapi_version_2, 2);
+ check_int(ccapi_version_3, 3);
+ check_int(ccapi_version_4, 4);
+ check_int(ccapi_version_5, 5);
+ check_int(ccapi_version_6, 6);
+
+ /* Errors */
+
+ check_int(ccNoError , 0 ); // 0
+ check_int(ccIteratorEnd , 201); // 201
+ check_int(ccErrBadParam , 202); // 202
+ check_int(ccErrNoMem , 203); // 203
+ check_int(ccErrInvalidContext , 204); // 204
+ check_int(ccErrInvalidCCache , 205); // 205
+ check_int(ccErrInvalidString , 206); // 206
+ check_int(ccErrInvalidCredentials , 207); // 207
+ check_int(ccErrInvalidCCacheIterator , 208); // 208
+ check_int(ccErrInvalidCredentialsIterator , 209); // 209
+ check_int(ccErrInvalidLock , 210); // 210
+ check_int(ccErrBadName , 211); // 211
+ check_int(ccErrBadCredentialsVersion , 212); // 212
+ check_int(ccErrBadAPIVersion , 213); // 213
+ check_int(ccErrContextLocked , 214); // 214
+ check_int(ccErrContextUnlocked , 215); // 215
+ check_int(ccErrCCacheLocked , 216); // 216
+ check_int(ccErrCCacheUnlocked , 217); // 217
+ check_int(ccErrBadLockType , 218); // 218
+ check_int(ccErrNeverDefault , 219); // 219
+ check_int(ccErrCredentialsNotFound , 220); // 220
+ check_int(ccErrCCacheNotFound , 221); // 221
+ check_int(ccErrContextNotFound , 222); // 222
+ check_int(ccErrServerUnavailable , 223); // 223
+ check_int(ccErrServerInsecure , 224); // 224
+ check_int(ccErrServerCantBecomeUID , 225); // 225
+ check_int(ccErrTimeOffsetNotSet , 226); // 226
+ check_int(ccErrBadInternalMessage , 227); // 227
+ check_int(ccErrNotImplemented , 228); // 228
+
+ /* Credentials versions */
+
+ check_int(cc_credentials_v4, 1);
+ check_int(cc_credentials_v5, 2);
+ check_int(cc_credentials_v4_v5, (cc_credentials_v4 | cc_credentials_v5));
+
+ /* Lock types */
+
+ check_int(cc_lock_read, 0);
+ check_int(cc_lock_write, 1);
+ check_int(cc_lock_upgrade, 2);
+ check_int(cc_lock_downgrade, 3);
+
+ /* Locking Modes */
+
+ check_int(cc_lock_noblock, 0);
+ check_int(cc_lock_block, 1);
+
+ END_TEST_AND_RETURN
+}
diff --git a/src/ccapi/test/test_ccapi_constants.h b/src/ccapi/test/test_ccapi_constants.h
new file mode 100644
index 0000000000000..bc3f4f3b71599
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_constants.h
@@ -0,0 +1,6 @@
+#ifndef _TEST_CCAPI_CONSTANTS_H_
+#define _TEST_CCAPI_CONSTANTS_H_
+
+int check_constants(void);
+
+#endif /* _TEST_CCAPI_CONSTANTS_H_ */
diff --git a/src/ccapi/test/test_ccapi_context.c b/src/ccapi/test/test_ccapi_context.c
new file mode 100644
index 0000000000000..09feebee5fcab
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_context.c
@@ -0,0 +1,990 @@
+#include <string.h>
+#include "test_ccapi_context.h"
+#include <limits.h>
+#include "test_ccapi_check.h"
+#include "test_ccapi_util.h"
+
+int check_cc_initialize(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+
+ BEGIN_TEST("cc_initialize");
+
+ // try every api_version
+ err = check_once_cc_initialize(&context, ccapi_version_2, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_2"); // err == CC_BAD_API_VERSION (9) would be imported by CredentialsCache2.h
+ err = check_once_cc_initialize(&context, ccapi_version_3, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_3"); // !err
+ err = check_once_cc_initialize(&context, ccapi_version_4, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_4"); // "
+ err = check_once_cc_initialize(&context, ccapi_version_5, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_5"); // "
+ err = check_once_cc_initialize(&context, ccapi_version_6, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_6"); // "
+
+ // try bad api_version
+ err = check_once_cc_initialize(&context, INT_MAX, NULL, NULL, ccErrBadAPIVersion, NULL); // err == ccErrBadAPIVersion
+
+ // try bad param
+ err = check_once_cc_initialize(NULL, ccapi_version_3, NULL, NULL, ccErrBadParam, NULL); // err == ccErrBadParam
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_initialize(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description) {
+ cc_int32 err = 0;
+ cc_context_t context;
+
+ cc_int32 possible_return_values[4] = {
+ ccNoError,
+ ccErrNoMem,
+ ccErrBadAPIVersion,
+ ccErrBadParam,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_initialize(out_context, in_version, out_supported_version, out_vendor);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (out_context) { context = *out_context; }
+ else { context = NULL; }
+
+ // check output parameters
+ if (!err) {
+ check_if(context == NULL, NULL);
+ if (context) {
+ cc_context_release(context);
+ *out_context = NULL;
+ }
+ } else {
+ check_if(context != NULL, NULL);
+ }
+
+ return err;
+}
+
+int check_cc_context_release(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+
+ BEGIN_TEST("cc_context_release");
+
+ #ifndef cc_context_release
+ log_error("cc_context_release is not implemented yet");
+ failure_count++;
+ #else
+
+ // try with valid context
+ err = check_once_cc_context_release(&context, ccNoError, NULL);
+
+ // try with NULL
+ //err = check_once_cc_context_release(NULL, ccErrInvalidContext);
+ /* calling with NULL context crashes, because this macro expands to
+ ((NULL) -> functions -> release (NULL)) which is dereferencing NULL which is bad. */
+
+ if (context) { cc_context_release(context); }
+
+ #endif /* cc_context_release */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_release(cc_context_t *out_context, cc_int32 expected_err, const char *description) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+
+ cc_int32 possible_return_values[2] = {
+ ccNoError,
+ ccErrInvalidContext,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_context_release
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (out_context) {
+ err = cc_initialize(out_context, ccapi_version_3, NULL, NULL);
+ if (!err) {
+ context = *out_context;
+ }
+ }
+
+ if (err != ccNoError) {
+ log_error("failure in cc_initialize, unable to perform check");
+ return err;
+ }
+ else {
+ err = cc_context_release(context);
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+ }
+
+ *out_context = NULL;
+
+ #endif /* cc_context_release */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+int check_cc_context_get_change_time(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_time_t last_change_time = 0;
+ cc_ccache_t ccache = NULL;
+ cc_credentials_union creds_union;
+ cc_credentials_iterator_t creds_iterator = NULL;
+ cc_credentials_t credentials = NULL;
+
+ BEGIN_TEST("cc_context_get_change_time");
+
+ #ifndef cc_context_get_change_time
+ log_error("cc_context_get_change_time is not implemented yet");
+ failure_count++;
+ #else
+
+ /*
+ * Make a context
+ * make sure the change time changes after:
+ * a ccache is created
+ * a ccache is destroyed
+ * a credential is stored
+ * a credential is removed
+ * a ccache principal is changed
+ * the default ccache is changed
+ * clean up memory
+ */
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+ if (!err) {
+
+ // try bad parameters first
+ err = check_once_cc_context_get_change_time(context, NULL, ccErrBadParam, "NULL param, should fail");
+
+ // make sure we have a default ccache
+ err = cc_context_open_default_ccache(context, &ccache);
+ if (err == ccErrCCacheNotFound) {
+ err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache);
+ }
+ if (!err) {
+ err = cc_ccache_release(ccache);
+ }
+ // either the default ccache already existed or we just created it
+ // either way, the get_change_time should now give something > 0
+ check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "first-run, should be > 0");
+
+ // create a ccache
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after creating a new ccache");
+
+ // store a credential
+ if (!err) {
+ new_v5_creds_union(&creds_union, "BAR.ORG");
+ err = cc_ccache_store_credentials(ccache, &creds_union);
+ release_v5_creds_union(&creds_union);
+ }
+ check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after storing a credential");
+
+ if (!err) {
+ // change principal (fails with ccErrBadInternalMessage)
+ err = cc_ccache_set_principal(ccache, cc_credentials_v5, "foo@BAR.ORG");
+ if (err) {
+ log_error("failed to change ccache's principal - %s (%d)", translate_ccapi_error(err), err);
+ failure_count++;
+ err = ccNoError;
+ }
+ }
+ check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after changing a principle");
+
+ // remove a credential
+ if (!err) {
+ err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator);
+ }
+ if (!err) {
+ err = cc_credentials_iterator_next(creds_iterator, &credentials);
+ }
+ if (err == ccIteratorEnd) {
+ err = ccNoError;
+ }
+ if (!err) {
+ err = cc_ccache_remove_credentials(ccache, credentials);
+ }
+ check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after removing a credential");
+
+ if (!err) {
+ // change default ccache
+ err = cc_ccache_set_default(ccache);
+ check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after changing default ccache");
+ }
+
+ if (ccache) {
+ // destroy a ccache
+ err = cc_ccache_destroy(ccache);
+ check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after destroying a ccache");
+ }
+ }
+
+ if (context) { cc_context_release(context); }
+
+ #endif /* cc_get_change_time */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_get_change_time(cc_context_t context, cc_time_t *time, cc_int32 expected_err, const char *description) {
+ cc_int32 err = 0;
+ cc_time_t last_change_time;
+ cc_time_t current_change_time = 0;
+
+ cc_int32 possible_return_values[3] = {
+ ccNoError,
+ ccErrInvalidContext,
+ ccErrBadParam,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_context_get_change_time
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (time != NULL) { // if we were passed NULL, then we're looking to pass a bad param
+ err = cc_context_get_change_time(context, &current_change_time);
+ } else {
+ err = cc_context_get_change_time(context, NULL);
+ }
+
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ last_change_time = *time;
+ check_if(current_change_time <= last_change_time, "context change time did not increase when it was supposed to (%d <= %d)", current_change_time, last_change_time);
+ *time = current_change_time;
+ }
+
+ #endif /* cc_context_get_change_time */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+int check_cc_context_get_default_ccache_name(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+ cc_string_t name = NULL;
+
+ BEGIN_TEST("cc_context_get_default_ccache_name");
+
+ #ifndef cc_context_get_default_ccache_name
+ log_error("cc_context_get_default_ccache_name is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+ if (!err) {
+ // try bad parameters first
+ err = check_once_cc_context_get_default_ccache_name(context, NULL, ccErrBadParam, NULL);
+
+ // try with no default
+ err = destroy_all_ccaches(context);
+ err = cc_context_open_default_ccache(context, &ccache);
+ if (err != ccErrCCacheNotFound) {
+ log_error("didn't remove all ccaches");
+ }
+ err = check_once_cc_context_get_default_ccache_name(context, &name, ccNoError, NULL);
+
+ // try normally
+ err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ if (ccache) { cc_ccache_release(ccache); }
+ err = check_once_cc_context_get_default_ccache_name(context, &name, ccNoError, NULL);
+
+ }
+
+ if (context) { cc_context_release(context); }
+
+ #endif /* cc_context_get_default_ccache_name */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_get_default_ccache_name(cc_context_t context, cc_string_t *name, cc_int32 expected_err, const char *description) {
+ cc_int32 err = 0;
+
+ cc_int32 possible_return_values[4] = {
+ ccNoError,
+ ccErrInvalidContext,
+ ccErrBadParam,
+ ccErrNoMem,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_context_get_default_ccache_name
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (name != NULL) { // if we were passed NULL, then we're looking to pass a bad param
+ err = cc_context_get_default_ccache_name(context, name);
+ } else {
+ err = cc_context_get_default_ccache_name(context, NULL);
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ // not really anything else to check
+
+ if (name && *name) { cc_string_release(*name); }
+
+ #endif /* cc_context_get_default_ccache_name */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+int check_cc_context_open_ccache(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+ cc_string_t name = NULL;
+
+ BEGIN_TEST("cc_context_open_ccache");
+
+ #ifndef cc_context_open_ccache
+ log_error("cc_context_open_ccache is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+ if (!err) {
+ // make sure we have a default ccache
+ err = cc_context_open_default_ccache(context, &ccache);
+ if (err == ccErrCCacheNotFound) {
+ err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache);
+ }
+ if (!err) {
+ err = cc_ccache_release(ccache);
+ ccache = NULL;
+ }
+
+ // try default ccache
+ err = cc_context_get_default_ccache_name(context, &name);
+ if (!err) {
+ err = check_once_cc_context_open_ccache(context, name->data, &ccache, ccNoError, NULL);
+ }
+
+ // try bad parameters
+ err = check_once_cc_context_open_ccache(context, NULL, &ccache, ccErrBadParam, NULL);
+ err = check_once_cc_context_open_ccache(context, name->data, NULL, ccErrBadParam, NULL);
+
+ // try a ccache that doesn't exist (create one and then destroy it)
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ if (!err) {
+ err = cc_ccache_get_name(ccache, &name);
+ }
+ if (!err) {
+ err = cc_ccache_destroy(ccache);
+ ccache = NULL;
+ }
+
+ err = check_once_cc_context_open_ccache(context, name->data, &ccache, ccErrCCacheNotFound, NULL);
+ }
+
+ if (context) { cc_context_release(context); }
+
+ #endif /* cc_context_open_ccache */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_open_ccache(cc_context_t context, const char *name, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) {
+ cc_int32 err = 0;
+ cc_string_t stored_name = NULL;
+
+ cc_int32 possible_return_values[6] = {
+ ccNoError,
+ ccErrBadName,
+ ccErrInvalidContext,
+ ccErrNoMem,
+ ccErrCCacheNotFound,
+ ccErrBadParam,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_context_open_ccache
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (ccache != NULL) { // if we were passed NULL, then we're looking to pass a bad param
+ err = cc_context_open_ccache(context, name, ccache);
+ } else {
+ err = cc_context_open_ccache(context, name, NULL);
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ check_if(*ccache == NULL, NULL);
+
+ if (!err) {
+ err = cc_ccache_get_name(*ccache, &stored_name);
+ }
+ if (!err) {
+ check_if(strcmp(stored_name->data, name), NULL);
+ }
+ if (stored_name) { cc_string_release(stored_name); }
+
+
+ if (ccache && *ccache) {
+ cc_ccache_release(*ccache);
+ *ccache = NULL;
+ }
+ }
+
+ #endif /* cc_context_open_ccache */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+int check_cc_context_open_default_ccache(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+
+ BEGIN_TEST("cc_context_open_default_ccache");
+
+ #ifndef cc_context_open_default_ccache
+ log_error("cc_context_open_default_ccache is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+ if (!err) {
+ // make sure we have a default ccache
+ err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache);
+ if (ccache) { cc_ccache_release(ccache); }
+
+ // try default ccache
+ if (!err) {
+ err = check_once_cc_context_open_default_ccache(context, &ccache, ccNoError, NULL);
+ }
+
+ // try bad parameters
+ err = check_once_cc_context_open_default_ccache(context, NULL, ccErrBadParam, NULL);
+
+ // try with no default ccache (destroy all ccaches first)
+ err = destroy_all_ccaches(context);
+
+ err = check_once_cc_context_open_default_ccache(context, &ccache, ccErrCCacheNotFound, NULL);
+ }
+
+ if (context) { cc_context_release(context); }
+
+ #endif /* cc_context_open_default_ccache */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_open_default_ccache(cc_context_t context, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) {
+ cc_int32 err = 0;
+ cc_string_t given_name = NULL;
+ cc_string_t default_name = NULL;
+
+ cc_int32 possible_return_values[5] = {
+ ccNoError,
+ ccErrInvalidContext,
+ ccErrNoMem,
+ ccErrCCacheNotFound,
+ ccErrBadParam,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_context_open_default_ccache
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (ccache != NULL) { // if we were passed NULL, then we're looking to pass a bad param
+ err = cc_context_open_default_ccache(context, ccache);
+ } else {
+ err = cc_context_open_default_ccache(context, NULL);
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ check_if(*ccache == NULL, NULL);
+
+ // make sure this ccache is the one we were looking to get back (compare name with cc_context_get_default_ccache_name)
+ err = cc_ccache_get_name(*ccache, &given_name);
+ err = cc_context_get_default_ccache_name(context, &default_name);
+ if (given_name && default_name) {
+ check_if(strcmp(given_name->data, default_name->data), "name of ccache returned by cc_context_open_default_ccache doesn't match name returned by cc_context_get_default_ccache_name");
+ }
+ if (given_name) { cc_string_release(given_name); }
+ if (default_name) { cc_string_release(default_name); }
+
+ if (ccache && *ccache) {
+ cc_ccache_release(*ccache);
+ *ccache = NULL;
+ }
+ }
+
+ #endif /* cc_context_open_default_ccache */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+int check_cc_context_create_ccache(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+ cc_string_t name = NULL;
+
+ BEGIN_TEST("cc_context_create_ccache");
+
+ #ifndef cc_context_create_ccache
+ log_error("cc_context_create_ccache is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+ if (!err) {
+ // try making a ccache with a non-unique name (the existing default's name)
+ if (!err) {
+ err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache);
+ }
+ if (!err) {
+ err = cc_ccache_get_name(ccache, &name);
+ }
+ if (ccache) { cc_ccache_release(ccache); }
+ if (!err) {
+ err = check_once_cc_context_create_ccache(context, name->data, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccNoError, NULL);
+ }
+
+ // try making a ccache with a unique name (the now destroyed default's name)
+ if (ccache) { cc_ccache_destroy(ccache); }
+ if (!err) {
+ err = check_once_cc_context_create_ccache(context, name->data, cc_credentials_v5, "foo/baz@BAR.ORG", &ccache, ccNoError, NULL);
+ }
+
+ // try bad parameters
+ err = check_once_cc_context_create_ccache(context, NULL, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccErrBadParam, "NULL name"); // NULL name
+ err = check_once_cc_context_create_ccache(context, "name", cc_credentials_v4_v5, "foo@BAR.ORG", &ccache, ccErrBadCredentialsVersion, "invalid creds_vers"); // invalid creds_vers
+ err = check_once_cc_context_create_ccache(context, "name", cc_credentials_v5, NULL, &ccache, ccErrBadParam, "NULL principal"); // NULL principal
+ err = check_once_cc_context_create_ccache(context, "name", cc_credentials_v5, "foo@BAR.ORG", NULL, ccErrBadParam, "NULL ccache"); // NULL ccache
+ }
+
+ if (name) { cc_string_release(name); }
+ if (ccache) { cc_ccache_destroy(ccache); }
+ if (context) { cc_context_release(context); }
+
+ #endif /* cc_context_create_ccache */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_create_ccache(cc_context_t context, const char *name, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) {
+ cc_int32 err = 0;
+ cc_string_t stored_name = NULL;
+ cc_string_t stored_principal = NULL;
+ cc_uint32 stored_creds_vers = 0;
+
+ cc_int32 possible_return_values[6] = {
+ ccNoError,
+ ccErrBadName,
+ ccErrBadParam,
+ ccErrInvalidContext,
+ ccErrNoMem,
+ ccErrBadCredentialsVersion,
+ };
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_context_create_ccache
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_context_create_ccache(context, name, cred_vers, principal, ccache);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ check_if(*ccache == NULL, NULL);
+
+ // make sure all of the ccache's info matches what we gave it
+ // name
+ err = cc_ccache_get_name(*ccache, &stored_name);
+ if (!err) { check_if(strcmp(stored_name->data, name), NULL); }
+ if (stored_name) { cc_string_release(stored_name); }
+ // cred_vers
+ // FIXME Documented function name of cc_ccache_get_credentials_version is a typo.
+ // FIXME Documented type of creds param the wrong signedness (should be unsigned) for cc_ccache_get_credentials_version, cc_context_create_ccache, cc_context_create_default_ccache, cc_context_create_new_ccache
+ err = cc_ccache_get_credentials_version(*ccache, &stored_creds_vers);
+ if (!err) { check_if(stored_creds_vers != cred_vers, NULL); }
+ // principal
+ err = cc_ccache_get_principal(*ccache, cc_credentials_v5, &stored_principal);
+ if (!err) { check_if(strcmp(stored_principal->data, principal), NULL); }
+ if (stored_principal) { cc_string_release(stored_principal); }
+
+ if (ccache && *ccache) {
+ cc_ccache_destroy(*ccache);
+ *ccache = NULL;
+ }
+ }
+
+ #endif /* cc_context_create_ccache */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+int check_cc_context_create_default_ccache(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+ cc_string_t name = NULL;
+
+ BEGIN_TEST("cc_context_create_default_ccache");
+
+ #ifndef cc_context_create_default_ccache
+ log_error("cc_context_create_default_ccache is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+ if (!err) {
+ // try making the default when there are no existing ccaches
+ err = destroy_all_ccaches(context);
+ if (!err) {
+ err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccNoError, NULL);
+ }
+ if (ccache) { cc_ccache_release(ccache); }
+
+ // try making a new default when one already exists
+ if (!err) {
+ err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, "foo/baz@BAR.ORG", &ccache, ccNoError, NULL);
+ }
+
+ // try bad parameters
+ err = check_once_cc_context_create_default_ccache(context, cc_credentials_v4_v5, "foo@BAR.ORG", &ccache, ccErrBadCredentialsVersion, "invalid creds_vers"); // invalid creds_vers
+ err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, NULL, &ccache, ccErrBadParam, "NULL principal"); // NULL principal
+ err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", NULL, ccErrBadParam, "NULL ccache"); // NULL ccache
+ }
+
+ if (name) { cc_string_release(name); }
+ if (ccache) { cc_ccache_destroy(ccache); }
+ if (context) { cc_context_release(context); }
+
+ #endif /* cc_context_create_default_ccache */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_create_default_ccache(cc_context_t context, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) {
+ cc_int32 err = 0;
+ cc_string_t stored_principal = NULL;
+ cc_uint32 stored_creds_vers = 0;
+
+ cc_int32 possible_return_values[6] = {
+ ccNoError,
+ ccErrBadName, // how can this be possible when the name isn't a parameter?
+ ccErrBadParam,
+ ccErrInvalidContext,
+ ccErrNoMem,
+ ccErrBadCredentialsVersion,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_context_create_default_ccache
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_context_create_default_ccache(context, cred_vers, principal, ccache);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ if (ccache) { check_if(*ccache == NULL, NULL); }
+ // make sure all of the ccache's info matches what we gave it
+ // cred_vers
+ err = cc_ccache_get_credentials_version(*ccache, &stored_creds_vers);
+ if (!err) { check_if(stored_creds_vers != cred_vers, NULL); }
+ // principal
+ err = cc_ccache_get_principal(*ccache, cc_credentials_v5, &stored_principal);
+ if (!err) { check_if(strcmp(stored_principal->data, principal), NULL); }
+ if (stored_principal) { cc_string_release(stored_principal); }
+
+ if (ccache && *ccache) {
+ cc_ccache_release(*ccache);
+ *ccache = NULL;
+ }
+ }
+
+ #endif /* cc_context_create_default_ccache */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+int check_cc_context_create_new_ccache(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+ cc_string_t name = NULL;
+
+ BEGIN_TEST("cc_context_create_new_ccache");
+
+ #ifndef cc_context_create_new_ccache
+ log_error("cc_context_create_new_ccache is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+ if (!err) {
+ // try making when there are no existing ccaches (should have name of default)
+ err = destroy_all_ccaches(context);
+ if (!err) {
+ err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccNoError, NULL);
+ }
+ if (ccache) { cc_ccache_release(ccache); }
+
+ // try making a new ccache when one already exists (should not have name of default)
+ if (!err) {
+ err = check_once_cc_context_create_new_ccache(context, 0, cc_credentials_v5, "foo/baz@BAR.ORG", &ccache, ccNoError, NULL);
+ }
+ if (ccache) { cc_ccache_release(ccache); }
+
+ // try bad parameters
+ err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v4_v5, "foo@BAR.ORG", &ccache, ccErrBadCredentialsVersion, "invalid creds_vers"); // invalid creds_vers
+ err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v5, NULL, &ccache, ccErrBadParam, "NULL principal"); // NULL principal
+ err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v5, "foo@BAR.ORG", NULL, ccErrBadParam, "NULL ccache"); // NULL ccache
+ }
+
+ if (name) { cc_string_release(name); }
+ if (ccache) { cc_ccache_destroy(ccache); }
+ if (context) { cc_context_release(context); }
+
+ #endif /* cc_context_create_new_ccache */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_create_new_ccache(cc_context_t context, cc_int32 should_be_default, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) {
+ cc_int32 err = 0;
+ cc_string_t name = NULL;
+ cc_string_t stored_name = NULL;
+ cc_string_t stored_principal = NULL;
+ cc_uint32 stored_creds_vers = 0;
+
+ cc_int32 possible_return_values[6] = {
+ ccNoError,
+ ccErrBadName, // how can this be possible when the name isn't a parameter?
+ ccErrBadParam,
+ ccErrInvalidContext,
+ ccErrNoMem,
+ ccErrBadCredentialsVersion,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_context_create_new_ccache
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_context_create_new_ccache(context, cred_vers, principal, ccache);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ if (ccache) { check_if(*ccache == NULL, NULL); }
+ // make sure all of the ccache's info matches what we gave it
+ if (!err) {
+ err = cc_context_get_default_ccache_name(context, &name);
+ }
+ if (!err) {
+ err = cc_ccache_get_name(*ccache, &stored_name);
+ }
+ if (!err) {
+ if (should_be_default) {
+ check_if(strcmp(stored_name->data, name->data), "new ccache does not have name of default");
+ }
+ else {
+ check_if((strcmp(stored_name->data, name->data) == 0), "new cache has name of default");
+ }
+ }
+ if (name) { cc_string_release(name); }
+ if (stored_name) { cc_string_release(stored_name); }
+
+ // cred_vers
+ err = cc_ccache_get_credentials_version(*ccache, &stored_creds_vers);
+ if (!err) { check_if(stored_creds_vers != cred_vers, NULL); }
+ // principal
+ err = cc_ccache_get_principal(*ccache, cc_credentials_v5, &stored_principal);
+ if (!err) { check_if(strcmp(stored_principal->data, principal), NULL); }
+ if (stored_principal) { cc_string_release(stored_principal); }
+
+ if (ccache && *ccache) {
+ cc_ccache_release(*ccache);
+ *ccache = NULL;
+ }
+ }
+
+ #endif /* cc_context_create_new_ccache */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+int check_cc_context_new_ccache_iterator(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+ cc_string_t name = NULL;
+ cc_ccache_iterator_t iterator = NULL;
+
+ BEGIN_TEST("cc_context_new_ccache_iterator");
+
+ #ifndef cc_context_new_ccache_iterator
+ log_error("cc_context_new_ccache_iterator is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+ if (!err) {
+ // try making when there are no existing ccaches (shouldn't make a difference, but just in case)
+ check_once_cc_context_new_ccache_iterator(context, &iterator, ccNoError, "when there are no existing ccaches");
+
+ err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+ if (!err) {
+ // try making when at least one ccache already exists (just to cover all our bases)
+ check_once_cc_context_new_ccache_iterator(context, &iterator, ccNoError, "when at least one ccache already exists");
+
+ // try bad parameters
+ check_once_cc_context_new_ccache_iterator(context, NULL, ccErrBadParam, "NULL param"); // NULL iterator
+ }
+ // we'll do a comprehensive test of cc_ccache_iterator related functions later in the test suite
+
+ if (name) { cc_string_release(name); }
+ if (ccache) { cc_ccache_destroy(ccache); }
+ if (context) { cc_context_release(context); }
+
+ #endif /* cc_context_new_ccache_iterator */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_new_ccache_iterator(cc_context_t context, cc_ccache_iterator_t *iterator, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+
+ cc_int32 possible_return_values[4] = {
+ ccNoError,
+ ccErrBadParam,
+ ccErrNoMem,
+ ccErrInvalidContext,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_context_create_new_ccache
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_context_new_ccache_iterator(context, iterator);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ // we'll do a comprehensive test of cc_ccache_iterator related functions later
+
+ #endif /* cc_context_create_new_ccache */
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_context_compare(void) {
+ cc_int32 err = 0;
+ cc_context_t context_a = NULL;
+ cc_context_t context_b = NULL;
+ cc_uint32 equal = 0;
+
+ BEGIN_TEST("cc_context_compare");
+
+ #ifndef cc_context_compare
+ log_error("cc_context_compare is not implemented yet");
+ failure_count++;
+ #else
+
+ err = cc_initialize(&context_a, ccapi_version_3, NULL, NULL);
+ if (!err) {
+ err = cc_initialize(&context_b, ccapi_version_3, NULL, NULL);
+ }
+
+ check_once_cc_context_compare(context_a, context_a, &equal, ccNoError, "valid params, same contexts");
+ check_once_cc_context_compare(context_a, context_b, &equal, ccNoError, "valid params, different contexts");
+ check_once_cc_context_compare(context_a, NULL, &equal, ccErrBadParam, "NULL compare_to context");
+ check_once_cc_context_compare(context_a, context_b, NULL, ccErrBadParam, "NULL out param");
+
+ if (context_a) { cc_context_release(context_a); }
+ if (context_b) { cc_context_release(context_b); }
+
+ #endif /* cc_context_compare */
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_compare(cc_context_t context, cc_context_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+
+ cc_int32 possible_return_values[4] = {
+ ccNoError,
+ ccErrInvalidContext,
+ ccErrBadParam,
+ ccErrServerUnavailable,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #ifdef cc_context_compare
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_context_compare(context, compare_to, equal);
+
+ if (!err) {
+ *equal = 0;
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ #endif /* cc_context_compare */
+
+ return err;
+}
diff --git a/src/ccapi/test/test_ccapi_context.h b/src/ccapi/test/test_ccapi_context.h
new file mode 100644
index 0000000000000..2c3a4ab8f8115
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_context.h
@@ -0,0 +1,32 @@
+#ifndef _TEST_CCAPI_CONTEXT_H_
+#define _TEST_CCAPI_CONTEXT_H_
+
+#include "test_ccapi_globals.h"
+
+int check_cc_initialize(void);
+cc_int32 check_once_cc_initialize(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description);
+int check_cc_context_get_version(void);
+cc_int32 check_once_cc_context_get_version(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description);
+int check_cc_context_release(void);
+cc_int32 check_once_cc_context_release(cc_context_t *out_context, cc_int32 expected_err, const char *description);
+int check_cc_context_get_change_time(void);
+cc_int32 check_once_cc_context_get_change_time(cc_context_t context, cc_time_t *time, cc_int32 expected_err, const char *description);
+int check_cc_context_get_default_ccache_name(void);
+cc_int32 check_once_cc_context_get_default_ccache_name(cc_context_t context, cc_string_t *name, cc_int32 expected_err, const char *description);
+int check_cc_context_open_ccache(void);
+cc_int32 check_once_cc_context_open_ccache(cc_context_t context, const char *name, cc_ccache_t *ccache, cc_int32 expected_err, const char *description);
+int check_cc_context_open_default_ccache(void);
+cc_int32 check_once_cc_context_open_default_ccache(cc_context_t context, cc_ccache_t *ccache, cc_int32 expected_err, const char *description);
+int check_cc_context_create_ccache(void);
+cc_int32 check_once_cc_context_create_ccache(cc_context_t context, const char *name, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description);
+int check_cc_context_create_default_ccache(void);
+cc_int32 check_once_cc_context_create_default_ccache(cc_context_t context, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description);
+int check_cc_context_create_new_ccache(void);
+cc_int32 check_once_cc_context_create_new_ccache(cc_context_t context, cc_int32 should_be_default, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description);
+int check_cc_context_new_ccache_iterator(void);
+cc_int32 check_once_cc_context_new_ccache_iterator(cc_context_t context, cc_ccache_iterator_t *iterator, cc_int32 expected_err, const char *description);
+
+int check_cc_context_compare(void);
+cc_int32 check_once_cc_context_compare(cc_context_t context, cc_context_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description);
+
+#endif /* _TEST_CCAPI_CONTEXT_H_ */
diff --git a/src/ccapi/test/test_ccapi_globals.c b/src/ccapi/test/test_ccapi_globals.c
new file mode 100644
index 0000000000000..a4ea63158d347
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_globals.c
@@ -0,0 +1,87 @@
+#include "test_ccapi_globals.h"
+
+/* GLOBALS */
+unsigned int total_failure_count = 0;
+unsigned int failure_count = 0;
+
+const char *current_test_name;
+const char *current_test_activity;
+
+const char * ccapi_error_strings[30] = {
+
+ "ccNoError", /* 0 */
+ "ccIteratorEnd", /* 201 */
+ "ccErrBadParam",
+ "ccErrNoMem",
+ "ccErrInvalidContext",
+ "ccErrInvalidCCache",
+
+ "ccErrInvalidString", /* 206 */
+ "ccErrInvalidCredentials",
+ "ccErrInvalidCCacheIterator",
+ "ccErrInvalidCredentialsIterator",
+ "ccErrInvalidLock",
+
+ "ccErrBadName", /* 211 */
+ "ccErrBadCredentialsVersion",
+ "ccErrBadAPIVersion",
+ "ccErrContextLocked",
+ "ccErrContextUnlocked",
+
+ "ccErrCCacheLocked", /* 216 */
+ "ccErrCCacheUnlocked",
+ "ccErrBadLockType",
+ "ccErrNeverDefault",
+ "ccErrCredentialsNotFound",
+
+ "ccErrCCacheNotFound", /* 221 */
+ "ccErrContextNotFound",
+ "ccErrServerUnavailable",
+ "ccErrServerInsecure",
+ "ccErrServerCantBecomeUID",
+
+ "ccErrTimeOffsetNotSet", /* 226 */
+ "ccErrBadInternalMessage",
+ "ccErrNotImplemented",
+
+};
+
+const char * ccapiv2_error_strings[24] = {
+
+ "CC_NOERROR",
+ "CC_BADNAME",
+ "CC_NOTFOUND",
+ "CC_END",
+ "CC_IO",
+ "CC_WRITE",
+ "CC_NOMEM",
+ "CC_FORMAT",
+ "CC_LOCKED",
+ "CC_BAD_API_VERSION",
+ "CC_NO_EXIST",
+ "CC_NOT_SUPP",
+ "CC_BAD_PARM",
+ "CC_ERR_CACHE_ATTACH",
+ "CC_ERR_CACHE_RELEASE",
+ "CC_ERR_CACHE_FULL",
+ "CC_ERR_CRED_VERSION"
+
+};
+
+const char *translate_ccapi_error(cc_int32 err) {
+
+ if (err == 0) {
+ return ccapi_error_strings[0];
+ } else
+ if (err >= 0 && err <= 16){
+ return ccapiv2_error_strings[err];
+ } else
+ if (err >= 201 && err <= 228){
+ return ccapi_error_strings[err - 200];
+ }
+ else {
+ return "\"Invalid or private CCAPI error\"";
+ }
+
+ return "";
+}
diff --git a/src/ccapi/test/test_ccapi_globals.h b/src/ccapi/test/test_ccapi_globals.h
new file mode 100644
index 0000000000000..fb2d5dbbd6667
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_globals.h
@@ -0,0 +1,57 @@
+#ifndef _TEST_CCAPI_GLOBALS_H_
+#define _TEST_CCAPI_GLOBALS_H_
+
+#include <krb5.h> // gets us TARGET_OS_MAC
+
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+#include <TargetConditionals.h>
+#endif
+
+#ifdef TARGET_OS_MAC
+#include <Kerberos/CredentialsCache.h>
+#else
+#include <CredentialsCache.h>
+#endif
+
+/* GLOBALS */
+extern unsigned int total_failure_count;
+extern unsigned int failure_count;
+
+extern const char *current_test_name;
+extern const char *current_test_activity;
+
+extern const char * ccapi_error_strings[30];
+
+const char *translate_ccapi_error(cc_int32 err);
+
+#define T_CCAPI_INIT \
+ do { \
+ current_test_name = NULL; \
+ current_test_activity = NULL; \
+ } while( 0 )
+
+#define BEGIN_TEST(name) \
+ do { \
+ current_test_name = name; \
+ failure_count = 0; \
+ test_header(current_test_name); \
+ } while( 0 )
+
+#define BEGIN_CHECK_ONCE(x) \
+ do { \
+ if (x) { \
+ current_test_activity = x; \
+ } \
+ } while( 0 )
+
+#define END_CHECK_ONCE \
+ do { \
+ current_test_activity = NULL; \
+ } while( 0 )
+
+#define END_TEST_AND_RETURN \
+ test_footer(current_test_name, failure_count); \
+ total_failure_count += failure_count; \
+ return failure_count;
+
+#endif /* _TEST_CCAPI_GLOBALS_H_ */
diff --git a/src/ccapi/test/test_ccapi_iterators.c b/src/ccapi/test/test_ccapi_iterators.c
new file mode 100644
index 0000000000000..e51c7cf32aa64
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_iterators.c
@@ -0,0 +1,246 @@
+#include "test_ccapi_globals.h"
+#include "test_ccapi_iterators.h"
+#include "test_ccapi_check.h"
+#include "test_ccapi_util.h"
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_iterator_next(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+ cc_ccache_iterator_t iterator = NULL;
+ unsigned int i;
+
+ BEGIN_TEST("cc_ccache_iterator_next");
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+
+ // iterate with no ccaches
+ if (!err) {
+ err = cc_context_new_ccache_iterator(context, &iterator);
+ }
+ check_once_cc_ccache_iterator_next(iterator, 0, ccNoError, "iterating over an empty collection");
+ if (iterator) {
+ cc_ccache_iterator_release(iterator);
+ iterator = NULL;
+ }
+
+ // iterate with one ccache
+ if (!err) {
+ destroy_all_ccaches(context);
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+ if (ccache) {
+ cc_ccache_release(ccache);
+ ccache = NULL;
+ }
+ if (!err) {
+ err = cc_context_new_ccache_iterator(context, &iterator);
+ }
+ check_once_cc_ccache_iterator_next(iterator, 1, ccNoError, "iterating over a collection of 1 ccache");
+ if (iterator) {
+ cc_ccache_iterator_release(iterator);
+ iterator = NULL;
+ }
+
+ // iterate with several ccaches
+ if (!err) {
+ destroy_all_ccaches(context);
+ }
+ for(i = 0; !err && (i < 1000); i++)
+ {
+ if (i%100 == 0) fprintf(stdout, ".");
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ if (ccache) {
+ cc_ccache_release(ccache);
+ ccache = NULL;
+ }
+ }
+ if (!err) {
+ err = cc_context_new_ccache_iterator(context, &iterator);
+ }
+ check_once_cc_ccache_iterator_next(iterator, 1000, ccNoError, "iterating over a collection of 1000 ccache");
+ if (iterator) {
+ cc_ccache_iterator_release(iterator);
+ iterator = NULL;
+ }
+
+
+ if (ccache) { cc_ccache_release(ccache); }
+ if (iterator) { cc_ccache_iterator_release(iterator); }
+ if (context) {
+ destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_iterator_next(cc_ccache_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+
+// BEGIN_CHECK_ONCE(description);
+
+ cc_int32 possible_return_values[6] = {
+ ccNoError,
+ ccIteratorEnd,
+ ccErrBadParam,
+ ccErrNoMem,
+ ccErrInvalidCCacheIterator,
+ ccErrCCacheNotFound,
+ };
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ cc_ccache_t ccache = NULL;
+ cc_uint32 actual_count = 0;
+
+ while (!err) {
+ err = cc_ccache_iterator_next(iterator, &ccache);
+ if (ccache) {
+ actual_count++;
+ cc_ccache_release(ccache);
+ ccache = NULL;
+ }
+ }
+ if (err == ccIteratorEnd) {
+ err = ccNoError;
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches");
+
+// END_CHECK_ONCE;
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_credentials_iterator_next(void) {
+ cc_int32 err = 0;
+ cc_context_t context = NULL;
+ cc_ccache_t ccache = NULL;
+ cc_credentials_union creds_union;
+ cc_credentials_iterator_t iterator = NULL;
+ unsigned int i;
+
+ BEGIN_TEST("cc_credentials_iterator_next");
+
+ err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches(context);
+ }
+
+ // iterate with no creds
+ if (!err) {
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+ if (!err) {
+ err = cc_ccache_new_credentials_iterator(ccache, &iterator);
+ }
+ check_once_cc_credentials_iterator_next(iterator, 0, ccNoError, "iterating over an empty ccache");
+ if (iterator) {
+ cc_ccache_iterator_release(iterator);
+ iterator = NULL;
+ }
+ if (ccache) {
+ cc_ccache_release(ccache);
+ ccache = NULL;
+ }
+
+ // iterate with one cred
+ if (!err) {
+ destroy_all_ccaches(context);
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+ if (!err) {
+ new_v5_creds_union(&creds_union, "BAR.ORG");
+ err = cc_ccache_store_credentials(ccache, &creds_union);
+ release_v5_creds_union(&creds_union);
+ }
+ if (!err) {
+ err = cc_ccache_new_credentials_iterator(ccache, &iterator);
+ }
+ check_once_cc_credentials_iterator_next(iterator, 1, ccNoError, "iterating over a ccache with 1 cred");
+ if (iterator) {
+ cc_credentials_iterator_release(iterator);
+ iterator = NULL;
+ }
+ if (ccache) {
+ cc_ccache_release(ccache);
+ ccache = NULL;
+ }
+
+ // iterate with several creds
+ if (!err) {
+ destroy_all_ccaches(context);
+ err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+ }
+ for(i = 0; !err && (i < 1000); i++) {
+ if (i%100 == 0) fprintf(stdout, ".");
+ new_v5_creds_union(&creds_union, "BAR.ORG");
+ err = cc_ccache_store_credentials(ccache, &creds_union);
+ release_v5_creds_union(&creds_union);
+ }
+ if (!err) {
+ err = cc_ccache_new_credentials_iterator(ccache, &iterator);
+ }
+ check_once_cc_credentials_iterator_next(iterator, 1000, ccNoError, "iterating over a ccache with 1000 creds");
+
+ if (ccache) { cc_ccache_release(ccache); }
+ if (iterator) { cc_credentials_iterator_release(iterator); }
+ if (context) {
+ destroy_all_ccaches(context);
+ cc_context_release(context);
+ }
+
+ END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_credentials_iterator_next(cc_credentials_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description) {
+ cc_int32 err = ccNoError;
+ cc_credentials_t creds = NULL;
+ cc_uint32 actual_count = 0;
+
+ cc_int32 possible_return_values[5] = {
+ ccNoError,
+ ccIteratorEnd,
+ ccErrBadParam,
+ ccErrNoMem,
+ ccErrInvalidCredentialsIterator,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+ #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ while (!err) {
+ err = cc_credentials_iterator_next(iterator, &creds);
+ if (creds) {
+ actual_count++;
+ cc_credentials_release(creds);
+ creds = NULL;
+ }
+ }
+ if (err == ccIteratorEnd) {
+ err = ccNoError;
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches");
+
+ END_CHECK_ONCE;
+
+ return err;
+}
diff --git a/src/ccapi/test/test_ccapi_iterators.h b/src/ccapi/test/test_ccapi_iterators.h
new file mode 100644
index 0000000000000..7308c7c49d279
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_iterators.h
@@ -0,0 +1,12 @@
+#ifndef _TEST_CCAPI_ITERATORS_H_
+#define _TEST_CCAPI_ITERATORS_H_
+
+#include "test_ccapi_globals.h"
+
+int check_cc_ccache_iterator_next(void);
+cc_int32 check_once_cc_ccache_iterator_next(cc_ccache_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description);
+
+int check_cc_credentials_iterator_next(void);
+cc_int32 check_once_cc_credentials_iterator_next(cc_credentials_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description);
+
+#endif /* _TEST_CCAPI_ITERATORS_H_ */
diff --git a/src/ccapi/test/test_ccapi_log.c b/src/ccapi/test/test_ccapi_log.c
new file mode 100644
index 0000000000000..8ecb6931f243e
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_log.c
@@ -0,0 +1,45 @@
+#ifndef _TEST_CCAPI_LOG_C_
+#define _TEST_CCAPI_LOG_C_
+
+#include "test_ccapi_log.h"
+
+void _log_error_v(const char *file, int line, const char *format, va_list ap)
+{
+ fprintf(stdout, "\n\t%s:%d: ", file, line);
+ if (!format) {
+ fprintf(stdout, "An unknown error occurred");
+ } else {
+ vfprintf(stdout, format, ap);
+ }
+ fflush(stdout);
+}
+
+void _log_error(const char *file, int line, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ _log_error_v(file, line, format, ap);
+ va_end(ap);
+}
+
+void test_header(const char *msg) {
+ if (msg != NULL) {
+ fprintf(stdout, "\nChecking %s... ", msg);
+ fflush(stdout);
+ }
+}
+
+void test_footer(const char *msg, int err) {
+ if (msg != NULL) {
+ if (!err) {
+ fprintf(stdout, "OK\n");
+ }
+ else {
+ fprintf(stdout, "\n*** %d failure%s in %s ***\n", err, (err == 1) ? "" : "s", msg);
+ }
+ }
+}
+
+
+
+#endif /* _TEST_CCAPI_LOG_C_ */
diff --git a/src/ccapi/test/test_ccapi_log.h b/src/ccapi/test/test_ccapi_log.h
new file mode 100644
index 0000000000000..6305c1845fcd0
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_log.h
@@ -0,0 +1,20 @@
+#ifndef _TEST_CCAPI_LOG_H_
+#define _TEST_CCAPI_LOG_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "test_ccapi_globals.h"
+
+#define log_error(format, ...) \
+ _log_error(__FILE__, __LINE__, format , ## __VA_ARGS__)
+
+void _log_error_v(const char *file, int line, const char *format, va_list ap);
+void _log_error(const char *file, int line, const char *format, ...)
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+__attribute__ ((__format__ (__printf__, 3, 4)))
+#endif
+;
+void test_header(const char *msg);
+void test_footer(const char *msg, int err);
+
+#endif /* _TEST_CCAPI_LOG_H_ */
diff --git a/src/ccapi/test/test_ccapi_util.c b/src/ccapi/test/test_ccapi_util.c
new file mode 100644
index 0000000000000..9af1a6b63ec9b
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_util.c
@@ -0,0 +1,142 @@
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+#include "k5-platform.h" /* pull in asprintf decl/defn */
+#include "test_ccapi_util.h"
+
+
+// ---------------------------------------------------------------------------
+
+cc_int32 destroy_all_ccaches(cc_context_t context) {
+ cc_int32 err = ccNoError;
+ cc_ccache_t ccache = NULL;
+
+ while (!err) {
+ err = cc_context_open_default_ccache(context, &ccache);
+ if (!err) {
+ err = cc_ccache_destroy(ccache);
+ }
+ }
+ if (err == ccErrCCacheNotFound) {
+ err = ccNoError;
+ }
+ else {
+ log_error("cc_context_open_default_ccache or cc_ccache_destroy failed with %s (%d)", translate_ccapi_error(err), err);
+ }
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+cc_int32 new_v5_creds_union (cc_credentials_union *out_union, const char *realm)
+{
+ cc_int32 err = ccNoError;
+ cc_credentials_union *cred_union = NULL;
+ cc_credentials_v5_t *v5creds = NULL;
+ static int num_runs = 1;
+ char *client = NULL;
+ char *server = NULL;
+
+ if (!out_union) { err = ccErrBadParam; }
+
+ if (!err) {
+ v5creds = malloc (sizeof (*v5creds));
+ if (!v5creds) {
+ err = ccErrNoMem;
+ }
+ }
+
+ if (!err) {
+ asprintf(&client, "client@%s", realm);
+ asprintf(&server, "host/%d%s@%s", num_runs++, realm, realm);
+ if (!client || !server) {
+ err = ccErrNoMem;
+ }
+ }
+
+ if (!err) {
+ v5creds->client = client;
+ v5creds->server = server;
+ v5creds->keyblock.type = 1;
+ v5creds->keyblock.length = 0;
+ v5creds->keyblock.data = NULL;
+ v5creds->authtime = time (NULL);
+ v5creds->starttime = time (NULL);
+ v5creds->endtime = time(NULL) + 1000;
+ v5creds->renew_till = time(NULL) + 10000;
+ v5creds->is_skey = 0;
+ v5creds->ticket_flags = TKT_FLG_FORWARDABLE | TKT_FLG_PROXIABLE | TKT_FLG_RENEWABLE | TKT_FLG_INITIAL;
+ v5creds->addresses = NULL;
+ v5creds->ticket.type = 0;
+ v5creds->ticket.length = 0;
+ v5creds->ticket.data = NULL;
+ v5creds->second_ticket.type = 0;
+ v5creds->second_ticket.length = 0;
+ v5creds->second_ticket.data = NULL;
+ v5creds->authdata = NULL;
+ }
+
+
+ if (!err) {
+ cred_union = malloc (sizeof (*cred_union));
+ if (cred_union) {
+ cred_union->version = cc_credentials_v5;
+ cred_union->credentials.credentials_v5 = v5creds;
+ } else {
+ err = ccErrNoMem;
+ }
+ }
+ if (!err) {
+ *out_union = *cred_union;
+ cred_union = NULL;
+ }
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+void release_v5_creds_union(cc_credentials_union *creds_union) {
+ cc_credentials_v5_t *v5creds = NULL;
+
+ if (creds_union) {
+ if (creds_union->credentials.credentials_v5) {
+ v5creds = creds_union->credentials.credentials_v5;
+ if (v5creds->client) { free(v5creds->client); }
+ if (v5creds->server) { free(v5creds->server); }
+ if (v5creds->keyblock.data) { free(v5creds->keyblock.data); }
+ if (v5creds->ticket.data) { free(v5creds->ticket.data); }
+ if (v5creds->second_ticket.data) { free(v5creds->second_ticket.data); }
+ free(v5creds);
+ }
+ //free(creds_union);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+
+// return zero when both unions are considered equal, non-zero when not
+
+int compare_v5_creds_unions(const cc_credentials_union *a, const cc_credentials_union *b) {
+ int retval = -1;
+
+ if (a &&
+ b &&
+ (a->version == cc_credentials_v5) &&
+ (a->version == b->version) &&
+ (strcmp(a->credentials.credentials_v5->client, b->credentials.credentials_v5->client) == 0) &&
+ (strcmp(a->credentials.credentials_v5->server, b->credentials.credentials_v5->server) == 0))
+ {
+ retval = 0;
+ }
+
+ return retval;
+}
diff --git a/src/ccapi/test/test_ccapi_util.h b/src/ccapi/test/test_ccapi_util.h
new file mode 100644
index 0000000000000..4e98e257e2630
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_util.h
@@ -0,0 +1,13 @@
+#ifndef _TEST_CCAPI_UTIL_H_
+#define _TEST_CCAPI_UTIL_H_
+
+#include "test_ccapi_globals.h"
+#include "test_ccapi_log.h"
+
+cc_int32 destroy_all_ccaches(cc_context_t context);
+
+cc_int32 new_v5_creds_union(cc_credentials_union *out_union, const char *realm);
+void release_v5_creds_union(cc_credentials_union *creds_union);
+int compare_v5_creds_unions(const cc_credentials_union *a, const cc_credentials_union *b);
+
+#endif /* _TEST_CCAPI_UTIL_H_ */
diff --git a/src/ccapi/test/test_ccapi_v2.c b/src/ccapi/test/test_ccapi_v2.c
new file mode 100644
index 0000000000000..e0205ce469651
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_v2.c
@@ -0,0 +1,1839 @@
+#include <string.h>
+#include "k5-platform.h" /* pull in asprintf decl/defn */
+#include "test_ccapi_v2.h"
+#include <limits.h>
+#include <time.h>
+#include "test_ccapi_check.h"
+#include "test_ccapi_util.h"
+
+// ---------------------------------------------------------------------------
+
+static cc_result destroy_all_ccaches_v2(apiCB *context) {
+ cc_result err = CC_NOERROR;
+ infoNC **info = NULL;
+ int i = 0;
+
+ err = cc_get_NC_info(context, &info);
+
+ for (i = 0; !err && info[i]; i++) {
+ ccache_p *ccache = NULL;
+
+ err = cc_open(context, info[i]->name, info[i]->vers, 0, &ccache);
+
+ if (!err) { cc_destroy(context, &ccache); }
+ }
+
+ if (info) { cc_free_NC_info(context, &info); }
+
+ if (err) {
+ log_error("cc_get_NC_info or cc_open failed with %s (%d)", translate_ccapi_error(err), err);
+ }
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+// return zero when both unions are considered equal, non-zero when not
+
+static int compare_v5_creds_unions_compat(const cred_union *a, const cred_union *b) {
+ int retval = -1;
+
+ if (a && b && a->cred_type == b->cred_type) {
+ if (a->cred_type == CC_CRED_V5) {
+ if (!strcmp(a->cred.pV5Cred->client, b->cred.pV5Cred->client) &&
+ !strcmp(a->cred.pV5Cred->server, b->cred.pV5Cred->server) &&
+ a->cred.pV5Cred->starttime == b->cred.pV5Cred->starttime) {
+ retval = 0;
+ }
+ } else if (a->cred_type == CC_CRED_V4) {
+ if (!strcmp (a->cred.pV4Cred->principal,
+ b->cred.pV4Cred->principal) &&
+ !strcmp (a->cred.pV4Cred->principal_instance,
+ b->cred.pV4Cred->principal_instance) &&
+ !strcmp (a->cred.pV4Cred->service,
+ b->cred.pV4Cred->service) &&
+ !strcmp (a->cred.pV4Cred->service_instance,
+ b->cred.pV4Cred->service_instance) &&
+ !strcmp (a->cred.pV4Cred->realm,
+ b->cred.pV4Cred->realm) &&
+ a->cred.pV4Cred->issue_date == b->cred.pV4Cred->issue_date) {
+ retval = 0;
+ }
+ }
+ }
+
+ return retval;
+}
+
+// ---------------------------------------------------------------------------
+
+static cc_result new_v5_creds_union_compat (cred_union *out_union, const char *realm)
+{
+ cc_result err = CC_NOERROR;
+ cred_union *creds_union = NULL;
+ cc_credentials_v5_compat *v5creds = NULL;
+ static int num_runs = 1;
+ char *client = NULL;
+ char *server = NULL;
+
+ if (!out_union) { err = CC_BAD_PARM; }
+
+ if (!err) {
+ v5creds = malloc (sizeof (*v5creds));
+ if (!v5creds) {
+ err = CC_NOMEM;
+ }
+ }
+
+ if (!err) {
+ asprintf(&client, "client@%s", realm);
+ asprintf(&server, "host/%d%s@%s", num_runs++, realm, realm);
+ if (!client || !server) {
+ err = CC_NOMEM;
+ }
+ }
+
+ if (!err) {
+ v5creds->client = client;
+ v5creds->server = server;
+ v5creds->keyblock.type = 1;
+ v5creds->keyblock.length = 0;
+ v5creds->keyblock.data = NULL;
+ v5creds->authtime = time (NULL);
+ v5creds->starttime = time (NULL);
+ v5creds->endtime = time(NULL) + 1000;
+ v5creds->renew_till = time(NULL) + 10000;
+ v5creds->is_skey = 0;
+ v5creds->ticket_flags = TKT_FLG_FORWARDABLE | TKT_FLG_PROXIABLE | TKT_FLG_RENEWABLE | TKT_FLG_INITIAL;
+ v5creds->addresses = NULL;
+ v5creds->ticket.type = 0;
+ v5creds->ticket.length = 0;
+ v5creds->ticket.data = NULL;
+ v5creds->second_ticket.type = 0;
+ v5creds->second_ticket.length = 0;
+ v5creds->second_ticket.data = NULL;
+ v5creds->authdata = NULL;
+ }
+
+
+ if (!err) {
+ creds_union = malloc (sizeof (*creds_union));
+ if (creds_union) {
+ creds_union->cred_type = CC_CRED_V5;
+ creds_union->cred.pV5Cred = v5creds;
+ } else {
+ err = CC_NOMEM;
+ }
+ }
+ if (!err) {
+ *out_union = *creds_union;
+ creds_union = NULL;
+ }
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+static void release_v5_creds_union_compat(cred_union *creds_union) {
+ cc_credentials_v5_compat *v5creds = NULL;
+
+ if (creds_union) {
+ if (creds_union->cred.pV5Cred) {
+ v5creds = creds_union->cred.pV5Cred;
+ if (v5creds->client) { free(v5creds->client); }
+ if (v5creds->server) { free(v5creds->server); }
+ if (v5creds->keyblock.data) { free(v5creds->keyblock.data); }
+ if (v5creds->ticket.data) { free(v5creds->ticket.data); }
+ if (v5creds->second_ticket.data) { free(v5creds->second_ticket.data); }
+ free(v5creds);
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_shutdown(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+
+ BEGIN_TEST("cc_shutdown");
+
+ // try with valid context
+ err = check_once_cc_shutdown(&context, CC_NOERROR, NULL);
+
+ // try with NULL
+ err = check_once_cc_shutdown(NULL, CC_BAD_PARM, NULL);
+
+ if (context) { cc_shutdown(&context); }
+
+ END_TEST_AND_RETURN
+}
+
+cc_result check_once_cc_shutdown(apiCB **out_context, cc_result expected_err, const char *description) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+
+ cc_result possible_return_values[2] = {
+ CC_NOERROR,
+ CC_BAD_PARM,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (out_context) {
+ err = cc_initialize(out_context, ccapi_version_2, NULL, NULL);
+ if (!err) {
+ context = *out_context;
+ } else {
+ log_error("failure in cc_initialize, unable to perform check");
+ return err;
+ }
+ }
+
+ if (!err) {
+ err = cc_shutdown(&context);
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ }
+
+ if (out_context) {
+ *out_context = NULL;
+ }
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_get_change_time(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ cc_time_t last_change_time = 0;
+ ccache_p *ccache = NULL;
+ cred_union creds_union;
+
+ BEGIN_TEST("cc_get_change_time");
+
+ /*
+ * Make a context
+ * make sure the change time changes after:
+ * a ccache is created
+ * a ccache is destroyed
+ * a credential is stored
+ * a credential is removed
+ * a ccache principal is changed
+ * clean up memory
+ */
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+ if (!err) {
+
+ // try bad parameters first
+ err = check_once_cc_get_change_time(context, NULL, CC_BAD_PARM, "NULL param, should fail");
+
+ // get_change_time should always give something > 0
+ check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "first-run, should be > 0");
+
+ // create a ccache
+ err = cc_create(context, "TEST_CCACHE", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ if (err) {
+ log_error("failed to create a ccache - %s (%d)", translate_ccapi_error(err), err);
+ failure_count++;
+ }
+ check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after creating a new ccache");
+
+ if (!err) {
+ // change principal
+ err = cc_set_principal(context, ccache, CC_CRED_V5, "foo@BAR.ORG");
+ if (err) {
+ log_error("failed to change ccache's principal - %s (%d)", translate_ccapi_error(err), err);
+ failure_count++;
+ err = CC_NOERROR;
+ }
+ }
+ check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after changing a principle");
+
+ new_v5_creds_union_compat(&creds_union, "BAR.ORG");
+
+ // store a credential
+ if (!err) {
+ err = cc_store(context, ccache, creds_union);
+ if (err) {
+ log_error("failed to store a credential - %s (%d)", translate_ccapi_error(err), err);
+ failure_count++;
+ err = CC_NOERROR;
+ }
+ }
+ check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after storing a credential");
+
+ // remove a credential
+ if (!err) {
+ err = cc_remove_cred(context, ccache, creds_union);
+ if (err) {
+ log_error("failed to remove a credential - %s (%d)", translate_ccapi_error(err), err);
+ failure_count++;
+ err = CC_NOERROR;
+ }
+ }
+ check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after removing a credential");
+
+ release_v5_creds_union_compat(&creds_union);
+
+ if (ccache) {
+ // destroy a ccache
+ err = cc_destroy(context, &ccache);
+ check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after destroying a ccache");
+ }
+ }
+
+ if (context) { cc_shutdown(&context); }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_int32 check_once_cc_get_change_time(apiCB *context, cc_time_t *last_time, cc_result expected_err, const char *description) {
+ cc_result err = 0;
+ cc_time_t last_change_time;
+ cc_time_t current_change_time = 0;
+
+ cc_result possible_return_values[3] = {
+ CC_NOERROR,
+ CC_BAD_PARM,
+ CC_NO_EXIST,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (last_time != NULL) { // if we were passed NULL, then we're looking to pass a bad param
+ err = cc_get_change_time(context, &current_change_time);
+ } else {
+ err = cc_get_change_time(context, NULL);
+ }
+
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ last_change_time = *last_time;
+ check_if(current_change_time <= last_change_time, "context change time did not increase when it was supposed to (%d <= %d)", current_change_time, last_change_time);
+ *last_time = current_change_time;
+ }
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_open(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ char *name = "TEST_OPEN_CCACHE";
+
+ BEGIN_TEST("cc_open");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+ if (!err) {
+ // create a ccache
+ err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ if (err) {
+ log_error("failed to create a ccache - %s (%d)", translate_ccapi_error(err), err);
+ failure_count++;
+ }
+ if (!err) {
+ err = cc_close(context, &ccache);
+ ccache = NULL;
+ }
+
+ // try default ccache
+ if (!err) {
+ err = check_once_cc_open(context, name, CC_CRED_V5, &ccache, CC_NOERROR, NULL);
+ }
+
+ // check version
+ if (!err) {
+ err = check_once_cc_open(context, name, CC_CRED_V4, &ccache, CC_ERR_CRED_VERSION, NULL);
+ }
+ // try bad parameters
+ err = check_once_cc_open(context, NULL, CC_CRED_V5, &ccache, CC_BAD_PARM, NULL);
+ err = check_once_cc_open(context, name, CC_CRED_V5, NULL, CC_BAD_PARM, NULL);
+ err = check_once_cc_open(context, name, CC_CRED_UNKNOWN, &ccache, CC_ERR_CRED_VERSION, NULL);
+ }
+
+ if (context) { cc_shutdown(&context); }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_result check_once_cc_open(apiCB *context, const char *name, cc_int32 version, ccache_p **ccache, cc_result expected_err, const char *description) {
+ cc_result err = 0;
+ char *stored_name = NULL;
+
+ cc_result possible_return_values[5] = {
+ CC_NOERROR,
+ CC_BAD_PARM,
+ CC_NO_EXIST,
+ CC_NOMEM,
+ CC_ERR_CRED_VERSION
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (ccache != NULL) { // if we were passed NULL, then we're looking to pass a bad param
+ err = cc_open(context, name, version, 0, ccache);
+ } else {
+ err = cc_open(context, name, version, 0, NULL);
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ check_if(*ccache == NULL, NULL);
+
+ if (!err) {
+ err = cc_get_name(context, *ccache, &stored_name);
+ }
+ if (!err) {
+ check_if(strcmp(stored_name, name), NULL);
+ }
+ if (stored_name) { cc_free_name(context, &stored_name); }
+
+
+ if (ccache && *ccache) {
+ cc_ccache_release(*ccache);
+ *ccache = NULL;
+ }
+ }
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_create(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ char *name = "TEST_CC_CREATE";
+
+ BEGIN_TEST("cc_create");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+ if (!err) {
+ if (!err) {
+ err = cc_open(context, name, CC_CRED_V5, 0, &ccache);
+ if (!err) {
+ err = cc_destroy (context, &ccache);
+ } else {
+ err = CC_NOERROR; /* ccache does not exist */
+ }
+ }
+ // try making a ccache with a unique name (the now destroyed cache's name)
+ if (!err) {
+ err = check_once_cc_create(context, name, CC_CRED_V5, "foo@BAR.ORG", &ccache, CC_NOERROR, NULL);
+ }
+
+ // try making a ccache with a non-unique name (the existing cache's name)
+ if (!err) {
+ err = check_once_cc_create(context, name, CC_CRED_V5, "foo/baz@BAR.ORG", &ccache, CC_NOERROR, NULL);
+ }
+
+ // try bad parameters
+ err = check_once_cc_create(context, NULL, CC_CRED_V5, "foo@BAR.ORG", &ccache, CC_BAD_PARM, "NULL name"); // NULL name
+ err = check_once_cc_create(context, "name", CC_CRED_MAX, "foo@BAR.ORG", &ccache, CC_ERR_CRED_VERSION, "invalid creds_vers"); // invalid creds_vers
+ err = check_once_cc_create(context, "name", CC_CRED_V5, NULL, &ccache, CC_BAD_PARM, "NULL principal"); // NULL principal
+ err = check_once_cc_create(context, "name", CC_CRED_V5, "foo@BAR.ORG", NULL, CC_BAD_PARM, "NULL ccache"); // NULL ccache
+ }
+
+ if (ccache) { cc_destroy(context, &ccache); }
+ if (context) { cc_shutdown(&context); }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_result check_once_cc_create(apiCB *context, const char *name, cc_int32 cred_vers, const char *principal, ccache_p **ccache, cc_int32 expected_err, const char *description) {
+ cc_result err = 0;
+ char *stored_name = NULL;
+ char *stored_principal = NULL;
+ cc_int32 stored_creds_vers = 0;
+
+ cc_result possible_return_values[6] = {
+ CC_NOERROR,
+ CC_BADNAME,
+ CC_BAD_PARM,
+ CC_NO_EXIST,
+ CC_NOMEM,
+ CC_ERR_CRED_VERSION,
+ };
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_create(context, name, principal, cred_vers, 0, ccache);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ check_if(*ccache == NULL, NULL);
+
+ // make sure all of the ccache's info matches what we gave it
+ // name
+ err = cc_get_name(context, *ccache, &stored_name);
+ if (!err) { check_if(strcmp(stored_name, name), NULL); }
+ if (stored_name) { cc_free_name(context, &stored_name); }
+ // cred_vers
+ err = cc_get_cred_version(context, *ccache, &stored_creds_vers);
+ if (!err) { check_if(stored_creds_vers != cred_vers, NULL); }
+ // principal
+ err = cc_get_principal(context, *ccache, &stored_principal);
+ if (!err) { check_if(strcmp(stored_principal, principal), NULL); }
+ if (stored_principal) { cc_free_principal(context, &stored_principal); }
+
+ if (ccache && *ccache) {
+ cc_destroy(context, ccache);
+ *ccache = NULL;
+ }
+ }
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_close(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ char *name = "TEST_CC_CLOSE";
+
+ BEGIN_TEST("cc_close");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+
+ if (!err) {
+ err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ }
+
+ if (!err) {
+ check_once_cc_close(context, ccache, CC_NOERROR, NULL);
+ ccache = NULL;
+ }
+
+ if (context) { cc_shutdown(&context); }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_result check_once_cc_close(apiCB *context, ccache_p *ccache, cc_result expected_err, const char *description) {
+ cc_result err = CC_NOERROR;
+
+ cc_result possible_return_values[2] = {
+ CC_NOERROR,
+ CC_BAD_PARM
+ };
+
+ char *name = NULL;
+
+ err = cc_get_name(context, ccache, &name);
+ err = cc_close(context, &ccache);
+ ccache = NULL;
+
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err && name) { // try opening released ccache to make sure it still exists
+ err = cc_open(context, name, CC_CRED_V5, 0, &ccache);
+ }
+ check_if(err == CC_NO_EXIST, "released ccache was actually destroyed instead");
+ check_if(err != CC_NOERROR, "released ccache cannot be opened");
+
+ if (ccache) { cc_destroy(context, &ccache); }
+ if (name) { cc_free_name(context, &name); }
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_destroy(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ char *name = "TEST_CC_DESTROY";
+
+ BEGIN_TEST("cc_destroy");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+
+ if (!err) {
+ err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ }
+
+ if (!err) {
+ check_once_cc_destroy(context, ccache, CC_NOERROR, NULL);
+ ccache = NULL;
+ }
+
+ if (context) { cc_shutdown(&context); }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_result check_once_cc_destroy(apiCB *context, ccache_p *ccache, cc_int32 expected_err, const char *description) {
+ cc_result err = CC_NOERROR;
+
+ cc_result possible_return_values[2] = {
+ CC_NOERROR,
+ CC_BAD_PARM,
+ };
+
+ char *name = NULL;
+
+ BEGIN_CHECK_ONCE(description);
+
+#ifdef cc_ccache_destroy
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_get_name(context, ccache, &name);
+ err = cc_destroy(context, &ccache);
+ ccache = NULL;
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err && name) { // try opening released ccache to make sure it still exists
+ err = cc_open(context, name, CC_CRED_V5, 0, &ccache);
+ }
+ check_if(err != CC_NO_EXIST, "destroyed ccache was actually released instead");
+
+ if (ccache) { cc_destroy(context, &ccache); }
+ if (name) { cc_free_name(context, &name); }
+
+#endif /* cc_ccache_destroy */
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_get_cred_version(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ char *name = "TEST_CC_GET_CRED_VERSION_V5";
+
+ BEGIN_TEST("cc_get_cred_version");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+
+ // try one created with v5 creds
+ if (!err) {
+ err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ }
+ if (!err) {
+ check_once_cc_get_cred_version(context, ccache, CC_CRED_V5, CC_NOERROR, "v5 creds");
+ }
+ else {
+ log_error("cc_context_create_new_ccache failed, can't complete test");
+ failure_count++;
+ }
+
+ if (ccache) {
+ cc_destroy(context, &ccache);
+ ccache = NULL;
+ }
+
+ err = CC_NOERROR;
+
+ // try one created with v4 creds
+ if (!err) {
+ err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V4, 0, &ccache);
+ }
+ if (!err) {
+ check_once_cc_get_cred_version(context, ccache, CC_CRED_V4, CC_NOERROR, "v4 creds");
+ }
+ else {
+ log_error("cc_context_create_new_ccache failed, can't complete test");
+ failure_count++;
+ }
+ if (ccache) {
+ cc_destroy(context, &ccache);
+ ccache = NULL;
+ }
+
+ if (context) { cc_shutdown(&context); }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_result check_once_cc_get_cred_version(apiCB *context, ccache_p *ccache, cc_int32 expected_cred_vers, cc_int32 expected_err, const char *description) {
+ cc_result err = CC_NOERROR;
+
+ cc_result possible_return_values[3] = {
+ CC_NOERROR,
+ CC_BAD_PARM,
+ CC_NO_EXIST,
+ };
+
+ cc_int32 stored_cred_vers = 0;
+
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_get_cred_version(context, ccache, &stored_cred_vers);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ check_if(stored_cred_vers != expected_cred_vers, NULL);
+ }
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_get_name(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+
+ BEGIN_TEST("cc_get_name");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches_v2(context);
+ }
+
+ // try with unique ccache (which happens to be default)
+ if (!err) {
+ err = cc_create(context, "0", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ }
+ if (!err) {
+ check_once_cc_get_name(context, ccache, "0", CC_NOERROR, "unique ccache (which happens to be default)");
+ }
+ else {
+ log_error("cc_context_create_ccache failed, can't complete test");
+ failure_count++;
+ }
+ if (ccache) {
+ cc_close(context, &ccache);
+ ccache = NULL;
+ }
+
+ // try with unique ccache (which is not default)
+ if (!err) {
+ err = cc_context_create_ccache(context, "1", CC_CRED_V5, "foo@BAR.ORG", &ccache);
+ }
+ if (!err) {
+ check_once_cc_get_name(context, ccache, "1", CC_NOERROR, "unique ccache (which is not default)");
+ }
+ else {
+ log_error("cc_context_create_ccache failed, can't complete test");
+ failure_count++;
+ }
+
+ // try with bad param
+ if (!err) {
+ check_once_cc_get_name(context, ccache, NULL, CC_BAD_PARM, "NULL param");
+ }
+ if (ccache) {
+ cc_close(context, &ccache);
+ ccache = NULL;
+ }
+
+ if (context) {
+ err = destroy_all_ccaches_v2(context);
+ cc_shutdown(&context);
+ }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_int32 check_once_cc_get_name(apiCB *context, ccache_p *ccache, const char *expected_name, cc_int32 expected_err, const char *description) {
+ cc_result err = CC_NOERROR;
+
+ cc_result possible_return_values[4] = {
+ CC_NOERROR,
+ CC_NOMEM,
+ CC_BAD_PARM,
+ CC_NO_EXIST,
+ };
+
+ char *stored_name = NULL;
+
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (expected_name == NULL) { // we want to try with a NULL param
+ err = cc_get_name(context, ccache, NULL);
+ }
+ else {
+ err = cc_get_name(context, ccache, &stored_name);
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ check_if(strcmp(stored_name, expected_name), NULL);
+ }
+
+ if (stored_name) { cc_free_name(context, &stored_name); }
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_get_principal(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ char *name_v5 = "TEST_CC_GET_PRINCIPAL_V5";
+ char *name_v4 = "TEST_CC_GET_PRINCIPAL_V4";
+
+ BEGIN_TEST("cc_get_principal");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches_v2(context);
+ }
+
+ // try with krb5 principal
+ if (!err) {
+ err = cc_create(context, name_v5, "foo/BAR@BAZ.ORG", CC_CRED_V5, 0, &ccache);
+ }
+ if (!err) {
+ check_once_cc_get_principal(context, ccache, "foo/BAR@BAZ.ORG", CC_NOERROR, "trying to get krb5 princ for krb5 ccache");
+ }
+ else {
+ log_error("cc_create failed, can't complete test");
+ failure_count++;
+ }
+ if (ccache) {
+ cc_close(context, &ccache);
+ ccache = NULL;
+ }
+
+ // try with krb4 principal
+ if (!err) {
+ err = cc_create(context, name_v4, "foo.BAR@BAZ.ORG", CC_CRED_V4, 0, &ccache);
+ }
+ if (!err) {
+ check_once_cc_get_principal(context, ccache, "foo.BAR@BAZ.ORG", CC_NOERROR, "trying to get krb4 princ for krb4 ccache");
+ }
+ else {
+ log_error("cc_create failed, can't complete test");
+ failure_count++;
+ }
+
+ // try with bad param
+ if (!err) {
+ check_once_cc_get_principal(context, ccache, NULL, CC_BAD_PARM, "passed null out param");
+ }
+
+ if (ccache) {
+ cc_close(context, &ccache);
+ ccache = NULL;
+ }
+
+ if (context) {
+ err = destroy_all_ccaches_v2(context);
+ cc_shutdown(&context);
+ }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_result check_once_cc_get_principal(apiCB *context,
+ ccache_p *ccache,
+ const char *expected_principal,
+ cc_int32 expected_err,
+ const char *description) {
+ cc_result err = CC_NOERROR;
+ char *stored_principal = NULL;
+
+ cc_result possible_return_values[4] = {
+ CC_NOERROR,
+ CC_NOMEM,
+ CC_NO_EXIST,
+ CC_BAD_PARM
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ if (expected_principal == NULL) { // we want to try with a NULL param
+ err = cc_get_principal(context, ccache, NULL);
+ }
+ else {
+ err = cc_get_principal(context, ccache, &stored_principal);
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ check_if(strcmp(stored_principal, expected_principal), "expected princ == \"%s\" stored princ == \"%s\"", expected_principal, stored_principal);
+ }
+
+ if (stored_principal) { cc_free_principal(context, &stored_principal); }
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_set_principal(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ char *name_v5 = "TEST_CC_GET_PRINCIPAL_V5";
+ char *name_v4 = "TEST_CC_GET_PRINCIPAL_V4";
+
+ BEGIN_TEST("cc_set_principal");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches_v2(context);
+ }
+
+ // bad params
+ if (!err) {
+ err = cc_create(context, name_v5, "foo@BAZ.ORG", CC_CRED_V5, 0, &ccache);
+ }
+ if (!err) {
+ check_once_cc_set_principal(context, ccache, CC_CRED_MAX, "foo/BAZ@BAR.ORG", CC_ERR_CRED_VERSION, "CC_CRED_MAX (not allowed)");
+ check_once_cc_set_principal(context, ccache, CC_CRED_V5, NULL, CC_BAD_PARM, "NULL principal");
+ }
+ else {
+ log_error("cc_create failed, can't complete test");
+ failure_count++;
+ }
+ if (ccache) {
+ cc_destroy(context, &ccache);
+ ccache = NULL;
+ }
+
+ // empty ccache
+
+ // replace v5 ccache's principal
+ if (!err) {
+ err = cc_create(context, name_v5, "foo@BAZ.ORG", CC_CRED_V5, 0, &ccache);
+ }
+ if (!err) {
+ check_once_cc_set_principal(context, ccache, CC_CRED_V5, "foo/BAZ@BAR.ORG", CC_NOERROR, "replace v5 only ccache's principal (empty ccache)");
+ check_once_cc_set_principal(context, ccache, CC_CRED_V4, "foo.BAZ@BAR.ORG", CC_ERR_CRED_VERSION, "replace v5 principal with v4");
+ }
+ else {
+ log_error("cc_create failed, can't complete test");
+ failure_count++;
+ }
+ if (ccache) {
+ cc_destroy(context, &ccache);
+ ccache = NULL;
+ }
+
+ // replace v4 ccache's principal
+ if (!err) {
+ err = cc_create(context, name_v4, "foo@BAZ.ORG", CC_CRED_V4, 0, &ccache);
+ }
+ if (!err) {
+ check_once_cc_set_principal(context, ccache, CC_CRED_V4, "foo.BAZ@BAR.ORG", CC_NOERROR, "replace v4 only ccache's principal (empty ccache)");
+ check_once_cc_set_principal(context, ccache, CC_CRED_V5, "foo/BAZ@BAR.ORG", CC_ERR_CRED_VERSION, "replace v4 principal with v5");
+ }
+ else {
+ log_error("cc_create failed, can't complete test");
+ failure_count++;
+ }
+ if (ccache) {
+ cc_destroy(context, &ccache);
+ ccache = NULL;
+ }
+
+ if (context) {
+ err = destroy_all_ccaches_v2(context);
+ cc_shutdown(&context);
+ }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_int32 check_once_cc_set_principal(apiCB *context, ccache_p *ccache, cc_int32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description) {
+ cc_result err = CC_NOERROR;
+ char *stored_principal = NULL;
+
+ cc_result possible_return_values[5] = {
+ CC_NOERROR,
+ CC_NOMEM,
+ CC_NO_EXIST,
+ CC_ERR_CRED_VERSION,
+ CC_BAD_PARM
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_set_principal(context, ccache, cred_vers, (char *) in_principal);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ if (!err) {
+ err = cc_get_principal(context, ccache, &stored_principal);
+ }
+
+ // compare stored with input
+ if (!err) {
+ check_if(strcmp(stored_principal, in_principal), "expected princ == \"%s\" stored princ == \"%s\"", in_principal, stored_principal);
+ }
+
+ if (stored_principal) { cc_free_principal(context, &stored_principal); }
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_store(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ ccache_p *dup_ccache = NULL;
+ cred_union creds_union;
+ char *name = NULL;
+
+ BEGIN_TEST("cc_store");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches_v2(context);
+ }
+
+ if (!err) {
+ err = cc_create(context, "TEST_CC_STORE", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ }
+
+ // cred with matching version and realm
+ if (!err) {
+ err = new_v5_creds_union_compat(&creds_union, "BAR.ORG");
+
+ if (!err) {
+ check_once_cc_store(context, ccache, creds_union, CC_NOERROR, "ok creds");
+ release_v5_creds_union_compat(&creds_union);
+ }
+ }
+
+ // invalid creds
+ if (!err) {
+ err = new_v5_creds_union_compat(&creds_union, "BAR.ORG");
+
+ if (!err) {
+ if (creds_union.cred.pV5Cred->client) {
+ free(creds_union.cred.pV5Cred->client);
+ creds_union.cred.pV5Cred->client = NULL;
+ }
+ check_once_cc_store(context, ccache, creds_union, CC_BAD_PARM, "invalid creds (NULL client string)");
+
+ release_v5_creds_union_compat(&creds_union);
+ }
+ }
+
+ // bad creds version
+ if (!err) {
+ err = new_v5_creds_union_compat(&creds_union, "BAR.ORG");
+
+ if (!err) {
+ creds_union.cred_type = CC_CRED_MAX;
+ check_once_cc_store(context, ccache, creds_union, CC_ERR_CRED_VERSION, "CC_CRED_MAX (invalid) into a ccache with only v5 princ");
+ creds_union.cred_type = CC_CRED_V4;
+ check_once_cc_store(context, ccache, creds_union, CC_ERR_CRED_VERSION, "v4 creds into a v5 ccache");
+ creds_union.cred_type = CC_CRED_V5;
+
+ release_v5_creds_union_compat(&creds_union);
+ }
+ }
+
+ // non-existent ccache
+ if (ccache) {
+ err = cc_get_name(context, ccache, &name);
+ if (!err) {
+ err = cc_open(context, name, CC_CRED_V5, 0, &dup_ccache);
+ }
+ if (name) { cc_free_name(context, &name); }
+ if (dup_ccache) { cc_destroy(context, &dup_ccache); }
+ }
+
+ if (!err) {
+ err = new_v5_creds_union_compat(&creds_union, "BAR.ORG");
+
+ if (!err) {
+ check_once_cc_store(context, ccache, creds_union, CC_NO_EXIST, "invalid ccache");
+
+ release_v5_creds_union_compat(&creds_union);
+ }
+ }
+
+ if (ccache) { cc_close(context, &ccache); }
+ if (context) {
+ destroy_all_ccaches_v2(context);
+ cc_shutdown(&context);
+ }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_result check_once_cc_store(apiCB *context, ccache_p *ccache, const cred_union in_creds, cc_int32 expected_err, const char *description) {
+ cc_result err = CC_NOERROR;
+ ccache_cit *iterator = NULL;
+ int found = 0;
+
+ cc_result possible_return_values[5] = {
+ CC_NOERROR,
+ CC_BAD_PARM,
+ CC_ERR_CACHE_FULL,
+ CC_ERR_CRED_VERSION,
+ CC_NO_EXIST
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_store(context, ccache, in_creds);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ // make sure credentials were truly stored
+ if (!err) {
+ err = cc_seq_fetch_creds_begin(context, ccache, &iterator);
+ }
+ while (!err && !found) {
+ cred_union *creds = NULL;
+
+ err = cc_seq_fetch_creds_next(context, &creds, iterator);
+ if (!err) {
+ found = !compare_v5_creds_unions_compat(&in_creds, creds);
+ }
+
+ if (creds) { cc_free_creds(context, &creds); }
+ }
+
+ if (err == CC_END) {
+ check_if(found, "stored credentials not found in ccache");
+ err = CC_NOERROR;
+ }
+
+ if (iterator) { cc_seq_fetch_creds_end(context, &iterator); }
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_remove_cred(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ cred_union *creds_array[10];
+ ccache_cit *iterator = NULL;
+ char *name = NULL;
+ unsigned int i;
+
+ BEGIN_TEST("cc_remove_cred");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches_v2(context);
+ }
+
+ if (!err) {
+ err = cc_create(context, "TEST_CC_REMOVE_CRED", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ }
+
+ // store 10 creds and retrieve their cc_credentials_t representations
+ for(i = 0; !err && (i < 10); i++) {
+ cred_union creds;
+
+ new_v5_creds_union_compat(&creds, "BAR.ORG");
+ err = cc_store(context, ccache, creds);
+ if (err) {
+ log_error("failure to store creds_union in remove_creds test");
+ }
+ release_v5_creds_union_compat(&creds);
+ }
+
+ if (!err) {
+ err = cc_seq_fetch_creds_begin(context, ccache, &iterator);
+ }
+
+ for (i = 0; !err && i < 10; i++) {
+ creds_array[i] = NULL;
+ err = cc_seq_fetch_creds_next(context, &creds_array[i], iterator);
+ }
+ if (err == CC_END) { err = CC_NOERROR; }
+
+ // remove 10 valid creds
+ for (i = 0; !err && (i < 10); i++) {
+ check_once_cc_remove_cred(context, ccache, *creds_array[i], CC_NOERROR, "10 ok creds");
+ }
+
+ // non-existent creds (remove same one twice)
+ check_once_cc_remove_cred(context, ccache, *creds_array[0], CC_NOTFOUND, "removed same creds twice");
+
+ // non-existent ccache
+ if (ccache) {
+ ccache_p *dup_ccache = NULL;
+
+ err = cc_get_name(context, ccache, &name);
+
+ if (!err) {
+ err = cc_open(context, name, CC_CRED_V5, 0, &dup_ccache);
+ }
+
+ if (!err) {
+ err = cc_destroy(context, &dup_ccache);
+ check_once_cc_remove_cred(context, ccache, *creds_array[0], CC_NO_EXIST, "invalid ccache");
+ }
+
+ if (name) { cc_free_name(context, &name); }
+ }
+
+ for(i = 0; i < 10 && creds_array[i]; i++) {
+ cc_free_creds(context, &creds_array[i]);
+ }
+
+
+ if (iterator) { cc_seq_fetch_creds_end(context, &iterator); iterator = NULL; }
+ if (ccache) { cc_close(context, &ccache); }
+ if (context) {
+ destroy_all_ccaches_v2(context);
+ cc_shutdown(&context);
+ }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_result check_once_cc_remove_cred(apiCB *context, ccache_p *ccache, cred_union in_creds, cc_int32 expected_err, const char *description) {
+ cc_result err = CC_NOERROR;
+ ccache_cit *iterator = NULL;
+ int found = 0;
+
+ cc_result possible_return_values[5] = {
+ CC_NOERROR,
+ CC_BAD_PARM,
+ CC_ERR_CRED_VERSION,
+ CC_NOTFOUND,
+ CC_NO_EXIST
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_remove_cred(context, ccache, in_creds);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ // make sure credentials were truly stored
+ if (!err) {
+ err = cc_seq_fetch_creds_begin(context, ccache, &iterator);
+ }
+
+ while (!err && !found) {
+ cred_union *creds = NULL;
+
+ err = cc_seq_fetch_creds_next(context, &creds, iterator);
+ if (!err) {
+ found = !compare_v5_creds_unions_compat(&in_creds, creds);
+ }
+
+ if (creds) { cc_free_creds(context, &creds); }
+ }
+
+ if (err == CC_END) {
+ check_if(found, "credentials not removed from ccache");
+ err = CC_NOERROR;
+ }
+
+ if (iterator) { cc_seq_fetch_creds_end(context, &iterator); }
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_seq_fetch_NCs_begin(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ ccache_cit *iterator = NULL;
+
+ BEGIN_TEST("cc_seq_fetch_NCs_begin");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+ if (!err) {
+ err = destroy_all_ccaches_v2(context);
+ }
+ if (!err) {
+ // try making when there are no existing ccaches (shouldn't make a difference, but just in case)
+ check_once_cc_seq_fetch_NCs_begin(context, &iterator, CC_NOERROR, "when there are no existing ccaches");
+
+ err = cc_create(context, "TEST_CC_SEQ_FETCH_NCS_BEGIN", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ }
+ if (!err) {
+ // try making when at least one ccache already exists (just to cover all our bases)
+ check_once_cc_seq_fetch_NCs_begin(context, &iterator, CC_NOERROR, "when at least one ccache already exists");
+
+ // try bad parameters
+ check_once_cc_seq_fetch_NCs_begin(context, NULL, CC_BAD_PARM, "NULL param"); // NULL iterator
+ }
+ // we'll do a comprehensive test of cc_ccache_iterator related functions later in the test suite
+
+ if (ccache ) { cc_close(context, &ccache); }
+ if (context) { cc_shutdown(&context); }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_result check_once_cc_seq_fetch_NCs_begin(apiCB *context, ccache_cit **iterator, cc_result expected_err, const char *description) {
+ cc_result err = CC_NOERROR;
+
+ cc_result possible_return_values[4] = {
+ CC_NOERROR,
+ CC_BAD_PARM,
+ CC_NOMEM,
+ CC_NO_EXIST
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_seq_fetch_NCs_begin(context, iterator);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ // we'll do a comprehensive test of cc_ccache_iterator related functions later
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_seq_fetch_NCs_next(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ ccache_cit *iterator = NULL;
+ unsigned int i;
+
+ BEGIN_TEST("cc_seq_fetch_NCs_next");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches_v2(context);
+ }
+
+ // iterate with no ccaches
+ if (!err) {
+ err = cc_seq_fetch_NCs_begin(context, &iterator);
+ }
+ check_once_cc_seq_fetch_NCs_next(context, iterator, 0, CC_NOERROR, "iterating over an empty collection");
+ if (iterator) {
+ cc_seq_fetch_creds_end(context, &iterator);
+ iterator = NULL;
+ }
+
+ // iterate with one ccache
+ if (!err) {
+ destroy_all_ccaches_v2(context);
+ err = cc_create(context, "TEST_CC_SEQ_FETCH_NCS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ }
+ if (ccache) {
+ cc_close(context, &ccache);
+ ccache = NULL;
+ }
+ if (!err) {
+ err = cc_seq_fetch_NCs_begin(context, &iterator);
+ }
+ check_once_cc_seq_fetch_NCs_next(context, iterator, 1, CC_NOERROR, "iterating over a collection of 1 ccache");
+ if (iterator) {
+ cc_seq_fetch_creds_end(context, &iterator);
+ iterator = NULL;
+ }
+
+ // iterate with several ccaches
+ if (!err) {
+ destroy_all_ccaches_v2(context);
+ }
+ for(i = 0; !err && (i < 1000); i++)
+ {
+ char *name = NULL;
+
+ if (i%100 == 0) fprintf(stdout, ".");
+ asprintf (&name, "TEST_CC_SEQ_FETCH_NCS_NEXT_%d", i);
+ err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ if (ccache) {
+ cc_close(context, &ccache);
+ ccache = NULL;
+ }
+ free (name);
+ }
+ if (!err) {
+ err = cc_seq_fetch_NCs_begin(context, &iterator);
+ }
+ check_once_cc_seq_fetch_NCs_next(context, iterator, 1000, CC_NOERROR, "iterating over a collection of 1000 ccache");
+ if (iterator) {
+ cc_seq_fetch_creds_end(context, &iterator);
+ iterator = NULL;
+ }
+
+
+ if (ccache) { cc_close(context, &ccache); }
+ if (iterator) { cc_seq_fetch_creds_end(context, &iterator); }
+ if (context) {
+ destroy_all_ccaches_v2(context);
+ cc_shutdown(&context);
+ }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_result check_once_cc_seq_fetch_NCs_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description) {
+ cc_result err = CC_NOERROR;
+
+ cc_result possible_return_values[5] = {
+ CC_NOERROR,
+ CC_END,
+ CC_BAD_PARM,
+ CC_NOMEM,
+ CC_NO_EXIST
+ };
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ ccache_p *ccache = NULL;
+ cc_uint32 actual_count = 0;
+
+ BEGIN_CHECK_ONCE(description);
+
+ while (!err) {
+ err = cc_seq_fetch_NCs_next(context, &ccache, iterator);
+ if (ccache) {
+ actual_count++;
+ cc_close(context, &ccache);
+ ccache = NULL;
+ }
+ }
+ if (err == CC_END) {
+ err = CC_NOERROR;
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches");
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_get_NC_info(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ unsigned int i;
+
+ BEGIN_TEST("cc_get_NC_info");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches_v2(context);
+ }
+
+ // iterate with no ccaches
+ check_once_cc_get_NC_info(context, "", "", CC_CRED_MAX, 0, CC_NOERROR, "iterating over an empty collection");
+
+ // iterate with one ccache
+ if (!err) {
+ destroy_all_ccaches_v2(context);
+ err = cc_create(context, "TEST_CC_GET_NC_INFO", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ }
+ if (ccache) {
+ cc_close(context, &ccache);
+ ccache = NULL;
+ }
+ check_once_cc_get_NC_info(context, "TEST_CC_GET_NC_INFO", "foo@BAR.ORG", CC_CRED_V5, 1, CC_NOERROR, "iterating over a collection of 1 ccache");
+
+ // iterate with several ccaches
+ if (!err) {
+ destroy_all_ccaches_v2(context);
+ }
+ for(i = 0; !err && (i < 1000); i++)
+ {
+ char *name = NULL;
+
+ if (i%100 == 0) fprintf(stdout, ".");
+ asprintf (&name, "TEST_CC_GET_NC_INFO_%d", i);
+ err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ if (ccache) {
+ cc_close(context, &ccache);
+ ccache = NULL;
+ }
+ free (name);
+ }
+ check_once_cc_get_NC_info(context, "TEST_CC_GET_NC_INFO", "foo@BAR.ORG", CC_CRED_V5, 1000, CC_NOERROR, "iterating over a collection of 1000 ccache");
+
+ if (ccache) { cc_close(context, &ccache); }
+ if (context) {
+ destroy_all_ccaches_v2(context);
+ cc_shutdown(&context);
+ }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_result check_once_cc_get_NC_info(apiCB *context,
+ const char *expected_name_prefix,
+ const char *expected_principal,
+ cc_int32 expected_version,
+ cc_uint32 expected_count,
+ cc_result expected_err,
+ const char *description) {
+ cc_result err = CC_NOERROR;
+ infoNC **info = NULL;
+
+ cc_result possible_return_values[4] = {
+ CC_NOERROR,
+ CC_BAD_PARM,
+ CC_NOMEM,
+ CC_NO_EXIST
+ };
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ cc_uint32 actual_count = 0;
+
+ BEGIN_CHECK_ONCE(description);
+
+ err = cc_get_NC_info(context, &info);
+
+ for (actual_count = 0; !err && info[actual_count]; actual_count++) {
+ check_if(strncmp(info[actual_count]->name, expected_name_prefix, strlen(expected_name_prefix)), "got incorrect ccache name");
+ check_if(strcmp(info[actual_count]->principal, expected_principal), "got incorrect principal name");
+ check_if(info[actual_count]->vers != expected_version, "got incorrect cred version");
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ check_if(actual_count != expected_count, "NC info didn't list all ccaches");
+
+ if (info) { cc_free_NC_info (context, &info); }
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_seq_fetch_creds_begin(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ ccache_p *dup_ccache = NULL;
+ ccache_cit *creds_iterator = NULL;
+ char *name = NULL;
+
+ BEGIN_TEST("cc_seq_fetch_creds_begin");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches_v2(context);
+ }
+
+ if (!err) {
+ err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_BEGIN", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ }
+
+ // valid params
+ if (!err) {
+ check_once_cc_seq_fetch_creds_begin(context, ccache, &creds_iterator, CC_NOERROR, "valid params");
+ }
+ if (creds_iterator) {
+ cc_seq_fetch_creds_end(context, &creds_iterator);
+ creds_iterator = NULL;
+ }
+
+ // NULL out param
+ if (!err) {
+ check_once_cc_seq_fetch_creds_begin(context, ccache, NULL, CC_BAD_PARM, "NULL out iterator param");
+ }
+ if (creds_iterator) {
+ cc_seq_fetch_creds_end(context, &creds_iterator);
+ creds_iterator = NULL;
+ }
+
+ // non-existent ccache
+ if (ccache) {
+ err = cc_get_name(context, ccache, &name);
+ if (!err) {
+ err = cc_open(context, name, CC_CRED_V5, 0, &dup_ccache);
+ }
+ if (name) { cc_free_name(context, &name); }
+ if (dup_ccache) { cc_destroy(context, &dup_ccache); }
+ }
+
+ if (!err) {
+ check_once_cc_seq_fetch_creds_begin(context, ccache, &creds_iterator, CC_NO_EXIST, "invalid ccache");
+ }
+
+ if (creds_iterator) {
+ cc_seq_fetch_creds_end(context, &creds_iterator);
+ creds_iterator = NULL;
+ }
+ if (ccache) { cc_close(context, &ccache); }
+ if (context) {
+ destroy_all_ccaches_v2(context);
+ cc_shutdown(&context);
+ }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_result check_once_cc_seq_fetch_creds_begin(apiCB *context, ccache_p *ccache, ccache_cit **iterator, cc_result expected_err, const char *description) {
+ cc_result err = CC_NOERROR;
+
+ cc_result possible_return_values[5] = {
+ CC_NOERROR,
+ CC_BAD_PARM,
+ CC_NOMEM,
+ CC_NO_EXIST
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ err = cc_seq_fetch_creds_begin(context, ccache, iterator);
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ END_CHECK_ONCE;
+
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+
+int check_cc_seq_fetch_creds_next(void) {
+ cc_result err = 0;
+ apiCB *context = NULL;
+ ccache_p *ccache = NULL;
+ cred_union creds_union;
+ ccache_cit *iterator = NULL;
+ unsigned int i;
+
+ BEGIN_TEST("cc_seq_fetch_creds_next");
+
+ err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
+
+ if (!err) {
+ err = destroy_all_ccaches_v2(context);
+ }
+
+ // iterate with no creds
+ if (!err) {
+ err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ }
+ if (!err) {
+ err = cc_seq_fetch_creds_begin(context, ccache, &iterator);
+ }
+ check_once_cc_seq_fetch_creds_next(context, iterator, 0, CC_NOERROR, "iterating over an empty ccache");
+ if (iterator) {
+ cc_seq_fetch_creds_end(context, &iterator);
+ iterator = NULL;
+ }
+ if (ccache) {
+ cc_close(context, &ccache);
+ ccache = NULL;
+ }
+
+ // iterate with one cred
+ if (!err) {
+ destroy_all_ccaches_v2(context);
+ err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ }
+ if (!err) {
+ new_v5_creds_union_compat(&creds_union, "BAR.ORG");
+ err = cc_store(context, ccache, creds_union);
+ release_v5_creds_union_compat(&creds_union);
+ }
+ if (!err) {
+ err = cc_seq_fetch_creds_begin(context, ccache, &iterator);
+ }
+ check_once_cc_seq_fetch_creds_next(context, iterator, 1, CC_NOERROR, "iterating over a ccache with 1 cred");
+ if (iterator) {
+ cc_seq_fetch_creds_end(context, &iterator);
+ iterator = NULL;
+ }
+ if (ccache) {
+ cc_close(context, &ccache);
+ ccache = NULL;
+ }
+
+ // iterate with several creds
+ if (!err) {
+ destroy_all_ccaches_v2(context);
+ err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
+ }
+ for(i = 0; !err && (i < 1000); i++) {
+ if (i%100 == 0) fprintf(stdout, ".");
+ new_v5_creds_union_compat(&creds_union, "BAR.ORG");
+ err = cc_store(context, ccache, creds_union);
+ release_v5_creds_union_compat(&creds_union);
+ }
+ if (!err) {
+ err = cc_seq_fetch_creds_begin(context, ccache, &iterator);
+ }
+ check_once_cc_seq_fetch_creds_next(context, iterator, 1000, CC_NOERROR, "iterating over a ccache with 1000 creds");
+
+ if (ccache) { cc_close(context, &ccache); }
+ if (iterator) { cc_seq_fetch_creds_end(context, &iterator); }
+ if (context) {
+ destroy_all_ccaches_v2(context);
+ cc_shutdown(&context);
+ }
+
+ END_TEST_AND_RETURN
+}
+
+// ---------------------------------------------------------------------------
+
+cc_result check_once_cc_seq_fetch_creds_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description) {
+ cc_result err = CC_NOERROR;
+ cred_union *creds = NULL;
+ cc_uint32 actual_count = 0;
+
+ cc_result possible_return_values[5] = {
+ CC_NOERROR,
+ CC_END,
+ CC_BAD_PARM,
+ CC_NOMEM,
+ CC_NO_EXIST,
+ };
+
+ BEGIN_CHECK_ONCE(description);
+
+#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+ while (!err) {
+ err = cc_seq_fetch_creds_next(context, &creds, iterator);
+ if (creds) {
+ actual_count++;
+ cc_free_creds(context, &creds);
+ creds = NULL;
+ }
+ }
+ if (err == CC_END) {
+ err = CC_NOERROR;
+ }
+
+ // check returned error
+ check_err(err, expected_err, possible_return_values);
+
+ check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches");
+
+ END_CHECK_ONCE;
+
+ return err;
+}
diff --git a/src/ccapi/test/test_ccapi_v2.h b/src/ccapi/test/test_ccapi_v2.h
new file mode 100644
index 0000000000000..8508daa45ec14
--- /dev/null
+++ b/src/ccapi/test/test_ccapi_v2.h
@@ -0,0 +1,73 @@
+#ifndef _TEST_CCAPI_V2_H_
+#define _TEST_CCAPI_V2_H_
+
+#include "test_ccapi_globals.h"
+#ifdef TARGET_OS_MAC
+#include <Kerberos/CredentialsCache2.h>
+#else
+#include <CredentialsCache2.h>
+#endif
+
+
+int check_cc_shutdown(void);
+cc_result check_once_cc_shutdown(apiCB **out_context, cc_result expected_err, const char *description);
+
+int check_cc_get_change_time(void);
+cc_int32 check_once_cc_get_change_time(apiCB *context, cc_time_t *time, cc_result expected_err, const char *description);
+
+int check_cc_open(void);
+cc_result check_once_cc_open(apiCB *context, const char *name, cc_int32 version, ccache_p **ccache, cc_result expected_err, const char *description);
+
+int check_cc_create(void);
+cc_result check_once_cc_create(apiCB *context, const char *name, cc_int32 cred_vers, const char *principal, ccache_p **ccache, cc_int32 expected_err, const char *description);
+
+int check_cc_close(void);
+cc_result check_once_cc_close(apiCB *context, ccache_p *ccache, cc_result expected_err, const char *description);
+
+int check_cc_destroy(void);
+cc_result check_once_cc_destroy(apiCB *context, ccache_p *ccache, cc_int32 expected_err, const char *description);
+
+int check_cc_get_cred_version(void);
+cc_result check_once_cc_get_cred_version(apiCB *context, ccache_p *ccache, cc_int32 expected_cred_vers, cc_int32 expected_err, const char *description);
+
+int check_cc_get_name(void);
+cc_int32 check_once_cc_get_name(apiCB *context, ccache_p *ccache, const char *expected_name, cc_int32 expected_err, const char *description);
+
+int check_cc_get_principal(void);
+cc_result check_once_cc_get_principal(apiCB *context,
+ ccache_p *ccache,
+ const char *expected_principal,
+ cc_int32 expected_err,
+ const char *description);
+
+int check_cc_set_principal(void);
+cc_int32 check_once_cc_set_principal(apiCB *context, ccache_p *ccache, cc_int32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description);
+
+int check_cc_store(void);
+cc_result check_once_cc_store(apiCB *context, ccache_p *ccache, const cred_union in_creds, cc_int32 expected_err, const char *description);
+
+int check_cc_remove_cred(void);
+cc_result check_once_cc_remove_cred(apiCB *context, ccache_p *ccache, cred_union in_creds, cc_int32 expected_err, const char *description);
+
+int check_cc_seq_fetch_NCs_begin(void);
+cc_result check_once_cc_seq_fetch_NCs_begin(apiCB *context, ccache_cit **iterator, cc_result expected_err, const char *description);
+
+int check_cc_seq_fetch_NCs_next(void);
+cc_result check_once_cc_seq_fetch_NCs_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description);
+
+int check_cc_get_NC_info(void);
+cc_result check_once_cc_get_NC_info(apiCB *context,
+ const char *expected_name,
+ const char *expected_principal,
+ cc_int32 expected_version,
+ cc_uint32 expected_count,
+ cc_result expected_err,
+ const char *description);
+
+int check_cc_seq_fetch_creds_begin(void);
+cc_result check_once_cc_seq_fetch_creds_begin(apiCB *context, ccache_p *ccache, ccache_cit **iterator, cc_result expected_err, const char *description);
+
+int check_cc_seq_fetch_creds_next(void);
+cc_result check_once_cc_seq_fetch_creds_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description);
+
+#endif /* _TEST_CCAPI_V2_H_ */
diff --git a/src/ccapi/test/test_constants.c b/src/ccapi/test/test_constants.c
new file mode 100644
index 0000000000000..f4f272c4dc581
--- /dev/null
+++ b/src/ccapi/test/test_constants.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <limits.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+ cc_int32 err = ccNoError;
+ T_CCAPI_INIT;
+ err = check_constants();
+ return err;
+}