summaryrefslogtreecommitdiff
path: root/lang/qt/tests
diff options
context:
space:
mode:
Diffstat (limited to 'lang/qt/tests')
-rw-r--r--lang/qt/tests/Makefile.am36
-rw-r--r--lang/qt/tests/Makefile.in184
-rwxr-xr-xlang/qt/tests/final.test6
-rw-r--r--lang/qt/tests/run-exportjob.cpp119
-rw-r--r--lang/qt/tests/run-importjob.cpp99
-rw-r--r--lang/qt/tests/run-receivekeysjob.cpp65
-rw-r--r--lang/qt/tests/t-addexistingsubkey.cpp260
-rw-r--r--lang/qt/tests/t-changeexpiryjob.cpp396
-rw-r--r--lang/qt/tests/t-config.cpp19
-rw-r--r--lang/qt/tests/t-encrypt.cpp34
-rw-r--r--lang/qt/tests/t-import.cpp169
-rw-r--r--lang/qt/tests/t-keylist.cpp7
-rw-r--r--lang/qt/tests/t-keylocate.cpp3
-rw-r--r--lang/qt/tests/t-ownertrust.cpp3
-rw-r--r--lang/qt/tests/t-remarks.cpp68
-rw-r--r--lang/qt/tests/t-support.cpp52
-rw-r--r--lang/qt/tests/t-support.h60
-rw-r--r--lang/qt/tests/t-tofuinfo.cpp7
-rw-r--r--lang/qt/tests/t-trustsignatures.cpp61
-rw-r--r--lang/qt/tests/t-various.cpp29
-rw-r--r--lang/qt/tests/t-wkdlookup.cpp155
-rw-r--r--lang/qt/tests/t-wkspublish.cpp3
22 files changed, 1603 insertions, 232 deletions
diff --git a/lang/qt/tests/Makefile.am b/lang/qt/tests/Makefile.am
index 41ea808..6c082b0 100644
--- a/lang/qt/tests/Makefile.am
+++ b/lang/qt/tests/Makefile.am
@@ -24,14 +24,22 @@ GPG = gpg
GNUPGHOME=$(abs_builddir)
TESTS_ENVIRONMENT = GNUPGHOME=$(GNUPGHOME)
-EXTRA_DIST = initial.test
+EXTRA_DIST = initial.test final.test
-TESTS = initial.test t-keylist t-keylocate t-ownertrust t-tofuinfo \
- t-encrypt t-verify t-various t-config t-remarks t-trustsignatures
+the_tests = \
+ t-addexistingsubkey \
+ t-keylist t-keylocate t-ownertrust t-tofuinfo \
+ t-encrypt t-verify t-various t-config t-remarks t-trustsignatures \
+ t-changeexpiryjob t-wkdlookup t-import
-moc_files = t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
- t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
- t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc
+TESTS = initial.test $(the_tests) final.test
+
+moc_files = \
+ t-addexistingsubkey.moc \
+ t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
+ t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
+ t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc \
+ t-changeexpiryjob.moc t-wkdlookup.moc t-import.moc
AM_LDFLAGS = -no-install
@@ -47,6 +55,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
support_src = t-support.h t-support.cpp
+t_addexistingsubkey_SOURCES = t-addexistingsubkey.cpp $(support_src)
t_keylist_SOURCES = t-keylist.cpp $(support_src)
t_keylocate_SOURCES = t-keylocate.cpp $(support_src)
t_ownertrust_SOURCES = t-ownertrust.cpp $(support_src)
@@ -58,15 +67,24 @@ t_various_SOURCES = t-various.cpp $(support_src)
t_config_SOURCES = t-config.cpp $(support_src)
t_remarks_SOURCES = t-remarks.cpp $(support_src)
t_trustsignatures_SOURCES = t-trustsignatures.cpp $(support_src)
+t_changeexpiryjob_SOURCES = t-changeexpiryjob.cpp $(support_src)
+t_wkdlookup_SOURCES = t-wkdlookup.cpp $(support_src)
+t_import_SOURCES = t-import.cpp $(support_src)
+run_exportjob_SOURCES = run-exportjob.cpp
+run_importjob_SOURCES = run-importjob.cpp
run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
+run_receivekeysjob_SOURCES = run-receivekeysjob.cpp
nodist_t_keylist_SOURCES = $(moc_files)
BUILT_SOURCES = $(moc_files) pubring-stamp
-noinst_PROGRAMS = t-keylist t-keylocate t-ownertrust t-tofuinfo t-encrypt \
- run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks \
- t-trustsignatures
+noinst_PROGRAMS = \
+ t-addexistingsubkey \
+ t-keylist t-keylocate t-ownertrust t-tofuinfo t-encrypt \
+ run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks \
+ t-trustsignatures t-changeexpiryjob t-wkdlookup t-import run-importjob \
+ run-exportjob run-receivekeysjob
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \
diff --git a/lang/qt/tests/Makefile.in b/lang/qt/tests/Makefile.in
index 2b0e0ee..89fad15 100644
--- a/lang/qt/tests/Makefile.in
+++ b/lang/qt/tests/Makefile.in
@@ -107,15 +107,15 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-TESTS = initial.test t-keylist$(EXEEXT) t-keylocate$(EXEEXT) \
- t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) t-encrypt$(EXEEXT) \
- t-verify$(EXEEXT) t-various$(EXEEXT) t-config$(EXEEXT) \
- t-remarks$(EXEEXT) t-trustsignatures$(EXEEXT)
-noinst_PROGRAMS = t-keylist$(EXEEXT) t-keylocate$(EXEEXT) \
- t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) t-encrypt$(EXEEXT) \
- run-keyformailboxjob$(EXEEXT) t-wkspublish$(EXEEXT) \
- t-verify$(EXEEXT) t-various$(EXEEXT) t-config$(EXEEXT) \
- t-remarks$(EXEEXT) t-trustsignatures$(EXEEXT)
+TESTS = initial.test $(am__EXEEXT_1) final.test
+noinst_PROGRAMS = t-addexistingsubkey$(EXEEXT) t-keylist$(EXEEXT) \
+ t-keylocate$(EXEEXT) t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) \
+ t-encrypt$(EXEEXT) run-keyformailboxjob$(EXEEXT) \
+ t-wkspublish$(EXEEXT) t-verify$(EXEEXT) t-various$(EXEEXT) \
+ t-config$(EXEEXT) t-remarks$(EXEEXT) \
+ t-trustsignatures$(EXEEXT) t-changeexpiryjob$(EXEEXT) \
+ t-wkdlookup$(EXEEXT) t-import$(EXEEXT) run-importjob$(EXEEXT) \
+ run-exportjob$(EXEEXT) run-receivekeysjob$(EXEEXT)
subdir = lang/qt/tests
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
@@ -137,16 +137,43 @@ CONFIG_HEADER = $(top_builddir)/conf/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
PROGRAMS = $(noinst_PROGRAMS)
-am_run_keyformailboxjob_OBJECTS = run-keyformailboxjob.$(OBJEXT)
-run_keyformailboxjob_OBJECTS = $(am_run_keyformailboxjob_OBJECTS)
-run_keyformailboxjob_LDADD = $(LDADD)
-run_keyformailboxjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+am_run_exportjob_OBJECTS = run-exportjob.$(OBJEXT)
+run_exportjob_OBJECTS = $(am_run_exportjob_OBJECTS)
+run_exportjob_LDADD = $(LDADD)
+run_exportjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
../src/libqgpgme.la ../../../src/libgpgme.la
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
+am_run_importjob_OBJECTS = run-importjob.$(OBJEXT)
+run_importjob_OBJECTS = $(am_run_importjob_OBJECTS)
+run_importjob_LDADD = $(LDADD)
+run_importjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
+am_run_keyformailboxjob_OBJECTS = run-keyformailboxjob.$(OBJEXT)
+run_keyformailboxjob_OBJECTS = $(am_run_keyformailboxjob_OBJECTS)
+run_keyformailboxjob_LDADD = $(LDADD)
+run_keyformailboxjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
+am_run_receivekeysjob_OBJECTS = run-receivekeysjob.$(OBJEXT)
+run_receivekeysjob_OBJECTS = $(am_run_receivekeysjob_OBJECTS)
+run_receivekeysjob_LDADD = $(LDADD)
+run_receivekeysjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
am__objects_1 = t-support.$(OBJEXT)
+am_t_addexistingsubkey_OBJECTS = t-addexistingsubkey.$(OBJEXT) \
+ $(am__objects_1)
+t_addexistingsubkey_OBJECTS = $(am_t_addexistingsubkey_OBJECTS)
+t_addexistingsubkey_LDADD = $(LDADD)
+t_addexistingsubkey_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
+am_t_changeexpiryjob_OBJECTS = t-changeexpiryjob.$(OBJEXT) \
+ $(am__objects_1)
+t_changeexpiryjob_OBJECTS = $(am_t_changeexpiryjob_OBJECTS)
+t_changeexpiryjob_LDADD = $(LDADD)
+t_changeexpiryjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
am_t_config_OBJECTS = t-config.$(OBJEXT) $(am__objects_1)
t_config_OBJECTS = $(am_t_config_OBJECTS)
t_config_LDADD = $(LDADD)
@@ -157,6 +184,11 @@ t_encrypt_OBJECTS = $(am_t_encrypt_OBJECTS)
t_encrypt_LDADD = $(LDADD)
t_encrypt_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
../src/libqgpgme.la ../../../src/libgpgme.la
+am_t_import_OBJECTS = t-import.$(OBJEXT) $(am__objects_1)
+t_import_OBJECTS = $(am_t_import_OBJECTS)
+t_import_LDADD = $(LDADD)
+t_import_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
am_t_keylist_OBJECTS = t-keylist.$(OBJEXT) $(am__objects_1)
am__objects_2 =
nodist_t_keylist_OBJECTS = $(am__objects_2)
@@ -201,6 +233,11 @@ t_verify_OBJECTS = $(am_t_verify_OBJECTS)
t_verify_LDADD = $(LDADD)
t_verify_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
../src/libqgpgme.la ../../../src/libgpgme.la
+am_t_wkdlookup_OBJECTS = t-wkdlookup.$(OBJEXT) $(am__objects_1)
+t_wkdlookup_OBJECTS = $(am_t_wkdlookup_OBJECTS)
+t_wkdlookup_LDADD = $(LDADD)
+t_wkdlookup_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
am_t_wkspublish_OBJECTS = t-wkspublish.$(OBJEXT) $(am__objects_1)
t_wkspublish_OBJECTS = $(am_t_wkspublish_OBJECTS)
t_wkspublish_LDADD = $(LDADD)
@@ -221,13 +258,19 @@ am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/conf
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__maybe_remake_depfiles = depfiles
-am__depfiles_remade = ./$(DEPDIR)/run-keyformailboxjob.Po \
- ./$(DEPDIR)/t-config.Po ./$(DEPDIR)/t-encrypt.Po \
+am__depfiles_remade = ./$(DEPDIR)/run-exportjob.Po \
+ ./$(DEPDIR)/run-importjob.Po \
+ ./$(DEPDIR)/run-keyformailboxjob.Po \
+ ./$(DEPDIR)/run-receivekeysjob.Po \
+ ./$(DEPDIR)/t-addexistingsubkey.Po \
+ ./$(DEPDIR)/t-changeexpiryjob.Po ./$(DEPDIR)/t-config.Po \
+ ./$(DEPDIR)/t-encrypt.Po ./$(DEPDIR)/t-import.Po \
./$(DEPDIR)/t-keylist.Po ./$(DEPDIR)/t-keylocate.Po \
./$(DEPDIR)/t-ownertrust.Po ./$(DEPDIR)/t-remarks.Po \
./$(DEPDIR)/t-support.Po ./$(DEPDIR)/t-tofuinfo.Po \
./$(DEPDIR)/t-trustsignatures.Po ./$(DEPDIR)/t-various.Po \
- ./$(DEPDIR)/t-verify.Po ./$(DEPDIR)/t-wkspublish.Po
+ ./$(DEPDIR)/t-verify.Po ./$(DEPDIR)/t-wkdlookup.Po \
+ ./$(DEPDIR)/t-wkspublish.Po
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@@ -265,19 +308,25 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
-SOURCES = $(run_keyformailboxjob_SOURCES) $(t_config_SOURCES) \
- $(t_encrypt_SOURCES) $(t_keylist_SOURCES) \
- $(nodist_t_keylist_SOURCES) $(t_keylocate_SOURCES) \
- $(t_ownertrust_SOURCES) $(t_remarks_SOURCES) \
- $(t_tofuinfo_SOURCES) $(t_trustsignatures_SOURCES) \
- $(t_various_SOURCES) $(t_verify_SOURCES) \
- $(t_wkspublish_SOURCES)
-DIST_SOURCES = $(run_keyformailboxjob_SOURCES) $(t_config_SOURCES) \
- $(t_encrypt_SOURCES) $(t_keylist_SOURCES) \
+SOURCES = $(run_exportjob_SOURCES) $(run_importjob_SOURCES) \
+ $(run_keyformailboxjob_SOURCES) $(run_receivekeysjob_SOURCES) \
+ $(t_addexistingsubkey_SOURCES) $(t_changeexpiryjob_SOURCES) \
+ $(t_config_SOURCES) $(t_encrypt_SOURCES) $(t_import_SOURCES) \
+ $(t_keylist_SOURCES) $(nodist_t_keylist_SOURCES) \
$(t_keylocate_SOURCES) $(t_ownertrust_SOURCES) \
$(t_remarks_SOURCES) $(t_tofuinfo_SOURCES) \
$(t_trustsignatures_SOURCES) $(t_various_SOURCES) \
- $(t_verify_SOURCES) $(t_wkspublish_SOURCES)
+ $(t_verify_SOURCES) $(t_wkdlookup_SOURCES) \
+ $(t_wkspublish_SOURCES)
+DIST_SOURCES = $(run_exportjob_SOURCES) $(run_importjob_SOURCES) \
+ $(run_keyformailboxjob_SOURCES) $(run_receivekeysjob_SOURCES) \
+ $(t_addexistingsubkey_SOURCES) $(t_changeexpiryjob_SOURCES) \
+ $(t_config_SOURCES) $(t_encrypt_SOURCES) $(t_import_SOURCES) \
+ $(t_keylist_SOURCES) $(t_keylocate_SOURCES) \
+ $(t_ownertrust_SOURCES) $(t_remarks_SOURCES) \
+ $(t_tofuinfo_SOURCES) $(t_trustsignatures_SOURCES) \
+ $(t_various_SOURCES) $(t_verify_SOURCES) \
+ $(t_wkdlookup_SOURCES) $(t_wkspublish_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -324,6 +373,12 @@ am__tty_colors = { \
std=''; \
fi; \
}
+am__EXEEXT_1 = t-addexistingsubkey$(EXEEXT) t-keylist$(EXEEXT) \
+ t-keylocate$(EXEEXT) t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) \
+ t-encrypt$(EXEEXT) t-verify$(EXEEXT) t-various$(EXEEXT) \
+ t-config$(EXEEXT) t-remarks$(EXEEXT) \
+ t-trustsignatures$(EXEEXT) t-changeexpiryjob$(EXEEXT) \
+ t-wkdlookup$(EXEEXT) t-import$(EXEEXT)
am__DIST_COMMON = $(srcdir)/Makefile.in \
$(top_srcdir)/build-aux/depcomp \
$(top_srcdir)/build-aux/mkinstalldirs
@@ -529,10 +584,19 @@ top_srcdir = @top_srcdir@
GPG = gpg
GNUPGHOME = $(abs_builddir)
TESTS_ENVIRONMENT = GNUPGHOME=$(GNUPGHOME)
-EXTRA_DIST = initial.test
-moc_files = t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
- t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
- t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc
+EXTRA_DIST = initial.test final.test
+the_tests = \
+ t-addexistingsubkey \
+ t-keylist t-keylocate t-ownertrust t-tofuinfo \
+ t-encrypt t-verify t-various t-config t-remarks t-trustsignatures \
+ t-changeexpiryjob t-wkdlookup t-import
+
+moc_files = \
+ t-addexistingsubkey.moc \
+ t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
+ t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
+ t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc \
+ t-changeexpiryjob.moc t-wkdlookup.moc t-import.moc
AM_LDFLAGS = -no-install
LDADD = ../../cpp/src/libgpgmepp.la ../src/libqgpgme.la \
@@ -546,6 +610,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
-DTOP_SRCDIR="$(top_srcdir)"
support_src = t-support.h t-support.cpp
+t_addexistingsubkey_SOURCES = t-addexistingsubkey.cpp $(support_src)
t_keylist_SOURCES = t-keylist.cpp $(support_src)
t_keylocate_SOURCES = t-keylocate.cpp $(support_src)
t_ownertrust_SOURCES = t-ownertrust.cpp $(support_src)
@@ -557,7 +622,13 @@ t_various_SOURCES = t-various.cpp $(support_src)
t_config_SOURCES = t-config.cpp $(support_src)
t_remarks_SOURCES = t-remarks.cpp $(support_src)
t_trustsignatures_SOURCES = t-trustsignatures.cpp $(support_src)
+t_changeexpiryjob_SOURCES = t-changeexpiryjob.cpp $(support_src)
+t_wkdlookup_SOURCES = t-wkdlookup.cpp $(support_src)
+t_import_SOURCES = t-import.cpp $(support_src)
+run_exportjob_SOURCES = run-exportjob.cpp
+run_importjob_SOURCES = run-importjob.cpp
run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
+run_receivekeysjob_SOURCES = run-receivekeysjob.cpp
nodist_t_keylist_SOURCES = $(moc_files)
BUILT_SOURCES = $(moc_files) pubring-stamp
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
@@ -609,10 +680,30 @@ clean-noinstPROGRAMS:
echo " rm -f" $$list; \
rm -f $$list
+run-exportjob$(EXEEXT): $(run_exportjob_OBJECTS) $(run_exportjob_DEPENDENCIES) $(EXTRA_run_exportjob_DEPENDENCIES)
+ @rm -f run-exportjob$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(run_exportjob_OBJECTS) $(run_exportjob_LDADD) $(LIBS)
+
+run-importjob$(EXEEXT): $(run_importjob_OBJECTS) $(run_importjob_DEPENDENCIES) $(EXTRA_run_importjob_DEPENDENCIES)
+ @rm -f run-importjob$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(run_importjob_OBJECTS) $(run_importjob_LDADD) $(LIBS)
+
run-keyformailboxjob$(EXEEXT): $(run_keyformailboxjob_OBJECTS) $(run_keyformailboxjob_DEPENDENCIES) $(EXTRA_run_keyformailboxjob_DEPENDENCIES)
@rm -f run-keyformailboxjob$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(run_keyformailboxjob_OBJECTS) $(run_keyformailboxjob_LDADD) $(LIBS)
+run-receivekeysjob$(EXEEXT): $(run_receivekeysjob_OBJECTS) $(run_receivekeysjob_DEPENDENCIES) $(EXTRA_run_receivekeysjob_DEPENDENCIES)
+ @rm -f run-receivekeysjob$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(run_receivekeysjob_OBJECTS) $(run_receivekeysjob_LDADD) $(LIBS)
+
+t-addexistingsubkey$(EXEEXT): $(t_addexistingsubkey_OBJECTS) $(t_addexistingsubkey_DEPENDENCIES) $(EXTRA_t_addexistingsubkey_DEPENDENCIES)
+ @rm -f t-addexistingsubkey$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_addexistingsubkey_OBJECTS) $(t_addexistingsubkey_LDADD) $(LIBS)
+
+t-changeexpiryjob$(EXEEXT): $(t_changeexpiryjob_OBJECTS) $(t_changeexpiryjob_DEPENDENCIES) $(EXTRA_t_changeexpiryjob_DEPENDENCIES)
+ @rm -f t-changeexpiryjob$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_changeexpiryjob_OBJECTS) $(t_changeexpiryjob_LDADD) $(LIBS)
+
t-config$(EXEEXT): $(t_config_OBJECTS) $(t_config_DEPENDENCIES) $(EXTRA_t_config_DEPENDENCIES)
@rm -f t-config$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_config_OBJECTS) $(t_config_LDADD) $(LIBS)
@@ -621,6 +712,10 @@ t-encrypt$(EXEEXT): $(t_encrypt_OBJECTS) $(t_encrypt_DEPENDENCIES) $(EXTRA_t_enc
@rm -f t-encrypt$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_encrypt_OBJECTS) $(t_encrypt_LDADD) $(LIBS)
+t-import$(EXEEXT): $(t_import_OBJECTS) $(t_import_DEPENDENCIES) $(EXTRA_t_import_DEPENDENCIES)
+ @rm -f t-import$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_import_OBJECTS) $(t_import_LDADD) $(LIBS)
+
t-keylist$(EXEEXT): $(t_keylist_OBJECTS) $(t_keylist_DEPENDENCIES) $(EXTRA_t_keylist_DEPENDENCIES)
@rm -f t-keylist$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_keylist_OBJECTS) $(t_keylist_LDADD) $(LIBS)
@@ -653,6 +748,10 @@ t-verify$(EXEEXT): $(t_verify_OBJECTS) $(t_verify_DEPENDENCIES) $(EXTRA_t_verify
@rm -f t-verify$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_verify_OBJECTS) $(t_verify_LDADD) $(LIBS)
+t-wkdlookup$(EXEEXT): $(t_wkdlookup_OBJECTS) $(t_wkdlookup_DEPENDENCIES) $(EXTRA_t_wkdlookup_DEPENDENCIES)
+ @rm -f t-wkdlookup$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_wkdlookup_OBJECTS) $(t_wkdlookup_LDADD) $(LIBS)
+
t-wkspublish$(EXEEXT): $(t_wkspublish_OBJECTS) $(t_wkspublish_DEPENDENCIES) $(EXTRA_t_wkspublish_DEPENDENCIES)
@rm -f t-wkspublish$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_wkspublish_OBJECTS) $(t_wkspublish_LDADD) $(LIBS)
@@ -663,9 +762,15 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-exportjob.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-importjob.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-keyformailboxjob.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-receivekeysjob.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-addexistingsubkey.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-changeexpiryjob.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-config.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-encrypt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-import.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-keylist.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-keylocate.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-ownertrust.Po@am__quote@ # am--include-marker
@@ -675,6 +780,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-trustsignatures.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-various.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-verify.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-wkdlookup.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-wkspublish.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@@ -934,9 +1040,15 @@ clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \
mostlyclean-am
distclean: distclean-am
- -rm -f ./$(DEPDIR)/run-keyformailboxjob.Po
+ -rm -f ./$(DEPDIR)/run-exportjob.Po
+ -rm -f ./$(DEPDIR)/run-importjob.Po
+ -rm -f ./$(DEPDIR)/run-keyformailboxjob.Po
+ -rm -f ./$(DEPDIR)/run-receivekeysjob.Po
+ -rm -f ./$(DEPDIR)/t-addexistingsubkey.Po
+ -rm -f ./$(DEPDIR)/t-changeexpiryjob.Po
-rm -f ./$(DEPDIR)/t-config.Po
-rm -f ./$(DEPDIR)/t-encrypt.Po
+ -rm -f ./$(DEPDIR)/t-import.Po
-rm -f ./$(DEPDIR)/t-keylist.Po
-rm -f ./$(DEPDIR)/t-keylocate.Po
-rm -f ./$(DEPDIR)/t-ownertrust.Po
@@ -946,6 +1058,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/t-trustsignatures.Po
-rm -f ./$(DEPDIR)/t-various.Po
-rm -f ./$(DEPDIR)/t-verify.Po
+ -rm -f ./$(DEPDIR)/t-wkdlookup.Po
-rm -f ./$(DEPDIR)/t-wkspublish.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
@@ -992,9 +1105,15 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -f ./$(DEPDIR)/run-keyformailboxjob.Po
+ -rm -f ./$(DEPDIR)/run-exportjob.Po
+ -rm -f ./$(DEPDIR)/run-importjob.Po
+ -rm -f ./$(DEPDIR)/run-keyformailboxjob.Po
+ -rm -f ./$(DEPDIR)/run-receivekeysjob.Po
+ -rm -f ./$(DEPDIR)/t-addexistingsubkey.Po
+ -rm -f ./$(DEPDIR)/t-changeexpiryjob.Po
-rm -f ./$(DEPDIR)/t-config.Po
-rm -f ./$(DEPDIR)/t-encrypt.Po
+ -rm -f ./$(DEPDIR)/t-import.Po
-rm -f ./$(DEPDIR)/t-keylist.Po
-rm -f ./$(DEPDIR)/t-keylocate.Po
-rm -f ./$(DEPDIR)/t-ownertrust.Po
@@ -1004,6 +1123,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/t-trustsignatures.Po
-rm -f ./$(DEPDIR)/t-various.Po
-rm -f ./$(DEPDIR)/t-verify.Po
+ -rm -f ./$(DEPDIR)/t-wkdlookup.Po
-rm -f ./$(DEPDIR)/t-wkspublish.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/lang/qt/tests/final.test b/lang/qt/tests/final.test
new file mode 100755
index 0000000..f28aaa4
--- /dev/null
+++ b/lang/qt/tests/final.test
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# stop the dirmngr that may have been started
+gpgconf --kill dirmngr
+
+exit 0
diff --git a/lang/qt/tests/run-exportjob.cpp b/lang/qt/tests/run-exportjob.cpp
new file mode 100644
index 0000000..0f8fd8f
--- /dev/null
+++ b/lang/qt/tests/run-exportjob.cpp
@@ -0,0 +1,119 @@
+/*
+ run-exportjob.cpp
+
+ This file is part of QGpgME's test suite.
+ Copyright (c) 2022 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <exportjob.h>
+#include <protocol.h>
+
+#include <context.h>
+
+#include <QCoreApplication>
+
+#include <iostream>
+
+using namespace GpgME;
+using std::cout;
+using std::cerr;
+
+static void showUsageAndExitWithCode(int exitCode)
+{
+ cerr << "Usage: run-exportjob [OPTION]... [PATTERN]...\n"
+ "Options:\n"
+ " --secret export secret keys instead of public keys\n"
+ " --secret-subkey export secret subkeys instead of public keys\n";
+
+ exit(exitCode);
+}
+
+static auto createExportJob(unsigned int mode)
+{
+ if (mode & Context::ExportSecretSubkey) {
+ return QGpgME::openpgp()->secretSubkeyExportJob(/*armor=*/true);
+ } else if (mode & Context::ExportSecret) {
+ return QGpgME::openpgp()->secretKeyExportJob(/*armor=*/true);
+ }
+ return QGpgME::openpgp()->publicKeyExportJob(/*armor=*/true);
+}
+
+int main(int argc, char *argv[])
+{
+ GpgME::initializeLibrary();
+
+ QCoreApplication app{argc, argv};
+
+ unsigned int exportMode = 0;
+
+ auto arguments = app.arguments();
+ if (!arguments.isEmpty()) {
+ arguments.pop_front(); // remove program name
+ }
+ while (!arguments.isEmpty()) {
+ const auto &arg = arguments.front();
+ if (!arg.startsWith(QLatin1String{"--"})) {
+ break;
+ }
+ if (arg == QLatin1String{"--"}) {
+ arguments.pop_front();
+ break;
+ }
+ if (arg == QLatin1String{"--help"}) {
+ showUsageAndExitWithCode(0);
+ } else if (arg == QLatin1String{"--secret"}) {
+ exportMode = Context::ExportSecret;
+ arguments.pop_front();
+ } else if (arg == QLatin1String{"--secret-subkey"}) {
+ exportMode = Context::ExportSecretSubkey;
+ arguments.pop_front();
+ } else {
+ cerr << "Error: Invalid option " << arg.toStdString() << std::endl;
+ showUsageAndExitWithCode(1);
+ }
+ }
+
+ auto job = createExportJob(exportMode);
+ QObject::connect(job, &QGpgME::ExportJob::result,
+ &app, [&app] (const GpgME::Error &err, const QByteArray &keyData, const QString &, const GpgME::Error &) {
+ if (err) {
+ cerr << "The ChangeExpiryJob failed with" << err.asString() << ".";
+ app.exit(1);
+ return;
+ }
+ cout << "Begin Result:\n" << keyData.toStdString() << "End Result:\n";
+ app.exit();
+ });
+ job->start(arguments);
+
+ return app.exec();
+}
diff --git a/lang/qt/tests/run-importjob.cpp b/lang/qt/tests/run-importjob.cpp
new file mode 100644
index 0000000..b1814fa
--- /dev/null
+++ b/lang/qt/tests/run-importjob.cpp
@@ -0,0 +1,99 @@
+/*
+ run-importjob.cpp
+
+ This file is part of QGpgME's test suite.
+ Copyright (c) 2021 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <importjob.h>
+#include <importresult.h>
+#include <protocol.h>
+
+#include <QFile>
+#include <QFileInfo>
+
+#include <QDebug>
+
+#include <set>
+#include <sstream>
+
+GpgME::Protocol guessProtocol(const QString &filename)
+{
+ static const std::set<QString> cmsExtensions = {"cer", "crt", "der", "p12", "p7c", "pem", "pfx"};
+ static const std::set<QString> pgpExtensions = {"asc", "gpg", "pgp"};
+
+ const auto extension = QFileInfo{filename}.suffix();
+ if (cmsExtensions.find(extension) != cmsExtensions.end()) {
+ return GpgME::CMS;
+ } else if (pgpExtensions.find(extension) != pgpExtensions.end()) {
+ return GpgME::OpenPGP;
+ }
+ qDebug() << "Unknown file name extension" << extension;
+ return GpgME::UnknownProtocol;
+}
+
+int main(int argc, char **argv)
+{
+ GpgME::initializeLibrary();
+
+ if (argc != 2) {
+ qInfo().noquote() << "Usage:" << argv[0] << "<certificate file>";
+ return 1;
+ }
+ const auto filename = QString::fromLocal8Bit(argv[1]);
+
+ QFile f{filename};
+ if (!f.exists()) {
+ qWarning() << "Error: File not found" << filename;
+ return 1;
+ }
+ const auto protocol = guessProtocol(filename);
+ if (protocol == GpgME::UnknownProtocol) {
+ qWarning() << "Error: Unknown file type";
+ return 1;
+ }
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning() << "Error: Failed to open file" << filename << "for reading.";
+ return 1;
+ }
+
+ const auto keyData = f.readAll();
+ auto job = (protocol == GpgME::CMS ? QGpgME::smime() : QGpgME::openpgp())->importJob();
+ const auto result = job->exec(keyData);
+ qDebug() << "Result error:" << result.error().asString();
+ std::ostringstream ostr;
+ ostr << result;
+ for (const auto &line : QString::fromStdString(ostr.str()).split('\n')) {
+ qDebug().noquote() << line;
+ }
+ return 0;
+}
diff --git a/lang/qt/tests/run-receivekeysjob.cpp b/lang/qt/tests/run-receivekeysjob.cpp
new file mode 100644
index 0000000..0dc1575
--- /dev/null
+++ b/lang/qt/tests/run-receivekeysjob.cpp
@@ -0,0 +1,65 @@
+/*
+ run-receivekeysjob.cpp
+
+ This file is part of QGpgME's test suite.
+ Copyright (c) 2022 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <importresult.h>
+#include <protocol.h>
+#include <receivekeysjob.h>
+
+#include <QCoreApplication>
+#include <QDebug>
+
+#include <iostream>
+
+int main(int argc, char **argv)
+{
+ GpgME::initializeLibrary();
+
+ if (argc < 2) {
+ std::cerr << "Usage: " << argv[0] << " KEYID..." << std::endl;
+ return 1;
+ }
+
+ QCoreApplication app(argc, argv);
+ const QStringList keyIds = qApp->arguments().mid(1);
+
+ auto job = QGpgME::openpgp()->receiveKeysJob();
+ const auto result = job->exec(keyIds);
+
+ std::cout << "Result: " << result.error().asString() << std::endl;
+ std::cout << "Details:\n" << result << std::endl;
+
+ return 0;
+}
diff --git a/lang/qt/tests/t-addexistingsubkey.cpp b/lang/qt/tests/t-addexistingsubkey.cpp
new file mode 100644
index 0000000..589c90b
--- /dev/null
+++ b/lang/qt/tests/t-addexistingsubkey.cpp
@@ -0,0 +1,260 @@
+/* t-addexistingsubkey.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "t-support.h"
+
+#include "addexistingsubkeyjob.h"
+#include "protocol.h"
+
+#include <QSignalSpy>
+#include <QTest>
+
+#include "context.h"
+#include "data.h"
+#include "engineinfo.h"
+
+#include <algorithm>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+static const char *requiredVersion = "2.3.5";
+
+/* Test keys
+ sec# ed25519 2022-01-13 [SC]
+ 1CB8C6A0317AA83F44FE009932392C82B814C8E0
+ uid [ unknown] source-key@example.net
+ ssb cv25519 2022-01-13 [E]
+ ssb cv25519 2022-01-13 [E] [expires: 2100-01-01]
+
+ sec ed25519 2022-01-13 [SC]
+ C3C87F0A3920B01F9E4450EA2B79F21D4DD10BFC
+ uid [ unknown] target-key@example.net
+ ssb cv25519 2022-01-13 [E]
+ * generated with
+export GNUPGHOME=$(mktemp -d)
+gpg -K
+gpg --batch --pinentry-mode loopback --passphrase abc --quick-gen-key source-key@example.net default default never
+fpr=$(gpg -k --with-colons source-key@example.net | grep ^fpr | head -1 | cut -d ':' -f 10)
+gpg --batch --pinentry-mode loopback --passphrase abc --quick-add-key ${fpr} default default 21000101T120000
+gpg --batch --pinentry-mode loopback --passphrase abc --quick-gen-key target-key@example.net default default never
+gpg -K
+gpg --export-secret-subkeys --armor --batch --pinentry-mode loopback --passphrase abc --comment source-key@example.net source-key@example.net | sed 's/\(.*\)/ "\1\\n"/'
+gpg --export-secret-keys --armor --batch --pinentry-mode loopback --passphrase abc --comment target-key@example.net target-key@example.net | sed 's/\(.*\)/ "\1\\n"/'
+#rm -rf ${GNUPGHOME}
+unset GNUPGHOME
+*/
+static const char *testKeyData =
+ "-----BEGIN PGP PRIVATE KEY BLOCK-----\n"
+ "Comment: source-key@example.net\n"
+ "\n"
+ "lDsEYd/ujBYJKwYBBAHaRw8BAQdAwiZPINTcrpgmu6ZWSaPZlcRSd4nDuofVMhe7\n"
+ "c2XrFyT/AGUAR05VAbQWc291cmNlLWtleUBleGFtcGxlLm5ldIiUBBMWCgA8FiEE\n"
+ "HLjGoDF6qD9E/gCZMjksgrgUyOAFAmHf7owCGwMFCwkIBwIDIgIBBhUKCQgLAgQW\n"
+ "AgMBAh4HAheAAAoJEDI5LIK4FMjgupIA/Au2YEAT9dYdJd0eJCJerG5YAeoB+uBs\n"
+ "mBkgr6xXE0bIAP43b6u1Jtvf/Wm3BhRbLd5Tg67Ba4CIZ8ZLGng73FBoBpyLBGHf\n"
+ "7owSCisGAQQBl1UBBQEBB0Cpg8Qof/WShxROZZtmPnw24vTk0R8nIAF1CZJ0bG/C\n"
+ "SwMBCAf+BwMCtzxziVxQEor8w/VVzHp4/hVSCUyrpiX7Djf04cIMs2bFPduZLgxb\n"
+ "c1SXhlgiqU0YBNntbGGNdKjTP6FMbYWq1+NwQm6ZXtC76LPG7syM94h4BBgWCgAg\n"
+ "FiEEHLjGoDF6qD9E/gCZMjksgrgUyOAFAmHf7owCGwwACgkQMjksgrgUyOCI0wEA\n"
+ "+f56fkvDDUwMOMw7n4+GKpfJXpWhVL08ttccbBOa/9IA/2HYA/78ZaD8E5EyqAEK\n"
+ "Aj9Au+2oJu9V5qo92QEoqwYHnIsEYd/vgxIKKwYBBAGXVQEFAQEHQBa9FxJkm/9D\n"
+ "xABildkaYMrbJbu8BPk6uv9V8aLmv9FnAwEIB/4HAwIPhcbN8s6OzPz8/g78TrCh\n"
+ "xqQb2kygCEj+OQ4/XXU3lus2b5xS5h44LGt99Wisqx+wVPDXmPDJOaxjhHXDmJxd\n"
+ "/LplIEhykojSm3uUDxERiH4EGBYKACYWIQQcuMagMXqoP0T+AJkyOSyCuBTI4AUC\n"
+ "Yd/vgwIbDAUJkqcQPQAKCRAyOSyCuBTI4IUjAP9BTfOD+jy6lLmzNO9pquRSAxi/\n"
+ "PQuglGtpS0LQEJMEOwD+PFnsMe2EtQ+WVSDBeB7O0m61EXeY+RhpuhNtsNXVuwc=\n"
+ "=wIPU\n"
+ "-----END PGP PRIVATE KEY BLOCK-----\n"
+ "-----BEGIN PGP PRIVATE KEY BLOCK-----\n"
+ "Comment: target-key@example.net\n"
+ "\n"
+ "lIYEYd/v/RYJKwYBBAHaRw8BAQdAKoILWXG3yaLb2EniNKQLUjwsrvy5vgAN299J\n"
+ "W5cFbrz+BwMC/uKbCq3sK5H8QVtEQ/IxGmjWNBpy6c8EDlOG4APi4o4VE+bEYD8w\n"
+ "J3Kk/lzSm6ZT5vC6DDASks797omjXD+J7zZ0vtTPvheYi/nsVz2UebQWdGFyZ2V0\n"
+ "LWtleUBleGFtcGxlLm5ldIiUBBMWCgA8FiEEw8h/CjkgsB+eRFDqK3nyHU3RC/wF\n"
+ "AmHf7/0CGwMFCwkIBwIDIgIBBhUKCQgLAgQWAgMBAh4HAheAAAoJECt58h1N0Qv8\n"
+ "rXcBAPxnkXqpp4IY3iTKV5XAdo7Uys7U/joUD73rj2XEvgI1AQDhKK4PLxPhf3ki\n"
+ "FKU0RA7itxzOH+F8bQ5BdYS49jDPCpyLBGHf7/0SCisGAQQBl1UBBQEBB0Dq9rwA\n"
+ "hAA2UFJShFsLFp7+g4uhWDfuDa3VjeIQRM+9QgMBCAf+BwMCMfCTl0LNqsn836t5\n"
+ "f2ZHBuMcNs4JWYmdLAIVaewEHq7zhOsX3iB+/yxwu9g2mXc4XUJ1iQzXLOYwgGov\n"
+ "8jIovrr01hDkSg4rvM9JKMWdd4h4BBgWCgAgFiEEw8h/CjkgsB+eRFDqK3nyHU3R\n"
+ "C/wFAmHf7/0CGwwACgkQK3nyHU3RC/xyfAEAqnMdSv6FTAwAWrYvJqJtSVoEhjMn\n"
+ "3c2qMsu34Bk86/MBAKHbLFmdyePvHaxKeO8CkQDoJzK8rYzw3RAmq/5JsQkL\n"
+ "=rOVf\n"
+ "-----END PGP PRIVATE KEY BLOCK-----\n";
+
+class AddExistingSubkeyJobTest : public QGpgMETest
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void initTestCase()
+ {
+ QGpgMETest::initTestCase();
+
+ // set up the test fixture for this test
+ qputenv("GNUPGHOME", mGnupgHomeTestFixture.path().toUtf8());
+ QVERIFY(importSecretKeys(testKeyData, 2));
+ }
+
+ void init()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
+ QSKIP("gpg does not yet support adding an existing subkey to another key via the command API");
+ }
+
+ // set up a copy of the test fixture for each test function
+ mGnupgHomeTestCopy.reset(new QTemporaryDir{});
+ QVERIFY(copyKeyrings(mGnupgHomeTestFixture.path(), mGnupgHomeTestCopy->path()));
+ qputenv("GNUPGHOME", mGnupgHomeTestCopy->path().toUtf8());
+ }
+
+ void testAddExistingSubkeyAsync()
+ {
+ // Get the key the subkey should be added to
+ auto key = getTestKey("target-key@example.net");
+ QVERIFY(!key.isNull());
+
+ // Get the key with the subkey to add
+ auto sourceKey = getTestKey("source-key@example.net", 3);
+ QVERIFY(!sourceKey.isNull());
+
+ auto job = std::unique_ptr<AddExistingSubkeyJob>{openpgp()->addExistingSubkeyJob()};
+ hookUpPassphraseProvider(job.get());
+
+ Error result;
+ connect(job.get(), &AddExistingSubkeyJob::result,
+ job.get(), [this, &result](const Error &result_) {
+ result = result_;
+ Q_EMIT asyncDone();
+ });
+ QVERIFY(!job->start(key, sourceKey.subkey(1)));
+ job.release(); // after the job has been started it's on its own
+
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ QVERIFY(result.code() == GPG_ERR_NO_ERROR);
+ key.update();
+ QCOMPARE(key.numSubkeys(), 3u);
+ }
+
+ void testAddExistingSubkeySync()
+ {
+ // Get the key the subkey should be added to
+ auto key = getTestKey("target-key@example.net");
+ QVERIFY(!key.isNull());
+
+ // Get the key with the subkey to add
+ auto sourceKey = getTestKey("source-key@example.net", 3);
+ QVERIFY(!sourceKey.isNull());
+ auto sourceSubkey = sourceKey.subkey(1);
+ QVERIFY(sourceSubkey.expirationTime() == 0);
+
+ auto job = std::unique_ptr<AddExistingSubkeyJob>{openpgp()->addExistingSubkeyJob()};
+ hookUpPassphraseProvider(job.get());
+
+ const auto result = job->exec(key, sourceSubkey);
+
+ QVERIFY(result.code() == GPG_ERR_NO_ERROR);
+ key.update();
+ QCOMPARE(key.numSubkeys(), 3u);
+ QCOMPARE(key.subkey(2).expirationTime(), 0);
+ }
+
+ void testAddExistingSubkeyWithExpiration()
+ {
+ // Get the key the subkey should be added to
+ auto key = getTestKey("target-key@example.net");
+ QVERIFY(!key.isNull());
+
+ // Get the key with the subkey to add
+ auto sourceKey = getTestKey("source-key@example.net", 3);
+ QVERIFY(!sourceKey.isNull());
+ auto sourceSubkey = sourceKey.subkey(2);
+ QVERIFY(sourceSubkey.expirationTime() != 0);
+
+ auto job = std::unique_ptr<AddExistingSubkeyJob>{openpgp()->addExistingSubkeyJob()};
+ hookUpPassphraseProvider(job.get());
+
+ const auto result = job->exec(key, sourceSubkey);
+
+ QVERIFY(result.code() == GPG_ERR_NO_ERROR);
+ key.update();
+ QCOMPARE(key.numSubkeys(), 3u);
+
+ // allow 1 second different expiration because gpg calculates with
+ // expiration as difference to current time and takes current time
+ // several times
+ const auto allowedDeltaTSeconds = 1;
+ const auto expectedExpirationRange = std::make_pair(
+ sourceSubkey.expirationTime() - allowedDeltaTSeconds,
+ sourceSubkey.expirationTime() + allowedDeltaTSeconds);
+ const auto actualExpiration = key.subkey(2).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+
+private:
+ Key getTestKey(const char *pattern, unsigned int expectedSubkeys = 2)
+ {
+ auto ctx = Context::create(OpenPGP);
+ VERIFY_OR_OBJECT(ctx);
+
+ Error err;
+ auto key = ctx->key(pattern, err, /*secret=*/true);
+ VERIFY_OR_OBJECT(!err);
+ VERIFY_OR_OBJECT(!key.isNull());
+ COMPARE_OR_OBJECT(key.numSubkeys(), expectedSubkeys);
+ for (unsigned int i = 0; i < key.numSubkeys(); ++i) {
+ VERIFY_OR_OBJECT(!key.subkey(i).isNull());
+ }
+ return key;
+ }
+
+private:
+ QTemporaryDir mGnupgHomeTestFixture;
+ std::unique_ptr<QTemporaryDir> mGnupgHomeTestCopy;
+};
+
+QTEST_MAIN(AddExistingSubkeyJobTest)
+
+#include "t-addexistingsubkey.moc"
diff --git a/lang/qt/tests/t-changeexpiryjob.cpp b/lang/qt/tests/t-changeexpiryjob.cpp
new file mode 100644
index 0000000..090002f
--- /dev/null
+++ b/lang/qt/tests/t-changeexpiryjob.cpp
@@ -0,0 +1,396 @@
+/* t-changeexpiryjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "t-support.h"
+
+#include "changeexpiryjob.h"
+#include "context.h"
+#include "engineinfo.h"
+#include "protocol.h"
+
+#include <QSignalSpy>
+#include <QTemporaryDir>
+#include <QTest>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class TestChangeExpiryJob: public QGpgMETest
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void test_change_expiration_default_without_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+ const auto subkeyExpiration = key.subkey(1).expirationTime();
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Use defaults of job
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(1);
+ job->start(key, newExpirationDate);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(1).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QCOMPARE(actualExpiration, subkeyExpiration); // unchanged
+ }
+ }
+ }
+
+ void test_change_expiration_default_with_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+ const auto primaryKeyExpiration = key.subkey(0).expirationTime();
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Use defaults of job
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(2);
+ job->start(key, newExpirationDate, {key.subkey(1)});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(2).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QCOMPARE(actualExpiration, primaryKeyExpiration); // unchanged
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ }
+ }
+
+ void test_change_expiration_update_primary_key_without_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+ const auto subkeyExpiration = key.subkey(1).expirationTime();
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Set up the job
+ job->setOptions(ChangeExpiryJob::UpdatePrimaryKey);
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(3);
+ job->start(key, newExpirationDate, {});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(3).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QCOMPARE(actualExpiration, subkeyExpiration); // unchanged
+ }
+ }
+ }
+
+ void test_change_expiration_update_primary_key_with_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Set up the job
+ job->setOptions(ChangeExpiryJob::UpdatePrimaryKey);
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(4);
+ job->start(key, newExpirationDate, {key.subkey(1)});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(4).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ }
+ }
+
+ void test_change_expiration_update_primary_key_and_all_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Set up the job
+ job->setOptions(ChangeExpiryJob::UpdatePrimaryKey | ChangeExpiryJob::UpdateAllSubkeys);
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(5);
+ job->start(key, newExpirationDate);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(5).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ }
+ }
+
+ void initTestCase()
+ {
+ QGpgMETest::initTestCase();
+ const QString gpgHome = qgetenv("GNUPGHOME");
+ QVERIFY(copyKeyrings(gpgHome, mDir.path()));
+ qputenv("GNUPGHOME", mDir.path().toUtf8());
+ }
+
+private:
+ QTemporaryDir mDir;
+};
+
+QTEST_MAIN(TestChangeExpiryJob)
+
+#include "t-changeexpiryjob.moc"
diff --git a/lang/qt/tests/t-config.cpp b/lang/qt/tests/t-config.cpp
index 9ec9566..b84dbfd 100644
--- a/lang/qt/tests/t-config.cpp
+++ b/lang/qt/tests/t-config.cpp
@@ -57,27 +57,24 @@ private Q_SLOTS:
// be unsupported in older versions.
return;
}
- // First set compliance to de-vs
auto conf = cryptoConfig();
QVERIFY(conf);
- auto entry = conf->entry(QStringLiteral("gpg"),
- QStringLiteral("Configuration"),
- QStringLiteral("compliance"));
+ auto entry = conf->entry(QStringLiteral("gpg"), QStringLiteral("compliance"));
QVERIFY(entry);
+ const auto defaultValue = entry->defaultValue().toString();
+ QCOMPARE(defaultValue, QStringLiteral("gnupg"));
+
entry->setStringValue("de-vs");
conf->sync(true);
conf->clear();
- entry = conf->entry(QStringLiteral("gpg"),
- QStringLiteral("Configuration"),
- QStringLiteral("compliance"));
+ entry = conf->entry(QStringLiteral("gpg"), QStringLiteral("compliance"));
QCOMPARE(entry->stringValue(), QStringLiteral("de-vs"));
+
entry->resetToDefault();
conf->sync(true);
conf->clear();
- entry = conf->entry(QStringLiteral("gpg"),
- QStringLiteral("Configuration"),
- QStringLiteral("compliance"));
- QCOMPARE(entry->stringValue(), QStringLiteral("gnupg"));
+ entry = conf->entry(QStringLiteral("gpg"), QStringLiteral("compliance"));
+ QCOMPARE(entry->stringValue(), defaultValue);
}
void initTestCase()
diff --git a/lang/qt/tests/t-encrypt.cpp b/lang/qt/tests/t-encrypt.cpp
index 9ad1033..6a4c68e 100644
--- a/lang/qt/tests/t-encrypt.cpp
+++ b/lang/qt/tests/t-encrypt.cpp
@@ -63,9 +63,6 @@ class EncryptionTest : public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testSimpleEncryptDecrypt()
@@ -92,10 +89,7 @@ private Q_SLOTS:
return;
}
auto decJob = openpgp()->decryptJob();
- auto ctx = Job::context(decJob);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(decJob);
QByteArray plainText;
auto decResult = decJob->exec(cipherText, plainText);
QVERIFY(!decResult.error());
@@ -163,10 +157,8 @@ private Q_SLOTS:
return;
}
auto job = openpgp()->encryptJob();
+ hookUpPassphraseProvider(job);
auto ctx = Job::context(job);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
ctx->setArmor(true);
ctx->setTextMode(true);
QByteArray cipherText;
@@ -179,9 +171,7 @@ private Q_SLOTS:
killAgent(mDir.path());
auto decJob = openpgp()->decryptJob();
- auto ctx2 = Job::context(decJob);
- ctx2->setPassphraseProvider(&provider);
- ctx2->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(decJob);
QByteArray plainText;
auto decResult = decJob->exec(cipherText, plainText);
QVERIFY(!result.error());
@@ -204,13 +194,9 @@ private Q_SLOTS:
delete listjob;
auto job = openpgp()->signEncryptJob(/*ASCII Armor */true, /* Textmode */ true);
-
- auto encSignCtx = Job::context(job);
- TestPassphraseProvider provider1;
- encSignCtx->setPassphraseProvider(&provider1);
- encSignCtx->setPinentryMode(Context::PinentryLoopback);
-
QVERIFY(job);
+ hookUpPassphraseProvider(job);
+
QByteArray cipherText;
auto result = job->exec(keys, keys, QStringLiteral("Hello World").toUtf8(), Context::AlwaysTrust, cipherText);
delete job;
@@ -225,10 +211,8 @@ private Q_SLOTS:
}
auto decJob = openpgp()->decryptJob();
+ hookUpPassphraseProvider(decJob);
auto ctx = Job::context(decJob);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
ctx->setDecryptionFlags(Context::DecryptUnwrap);
QByteArray plainText;
@@ -269,9 +253,8 @@ private:
delete listjob;
auto job = openpgp()->encryptJob();
+ hookUpPassphraseProvider(job);
auto ctx = Job::context(job);
- ctx->setPassphraseProvider(new TestPassphraseProvider);
- ctx->setPinentryMode(Context::PinentryLoopback);
ctx->setArmor(true);
ctx->setTextMode(true);
QByteArray cipherText;
@@ -297,9 +280,8 @@ private:
agentConf.close();
auto decJob = openpgp()->decryptJob();
+ hookUpPassphraseProvider(decJob);
auto ctx2 = Job::context(decJob);
- ctx2->setPassphraseProvider(new TestPassphraseProvider);
- ctx2->setPinentryMode(Context::PinentryLoopback);
ctx2->setTextMode(true);
QByteArray plainText;
auto decResult = decJob->exec(cipherText, plainText);
diff --git a/lang/qt/tests/t-import.cpp b/lang/qt/tests/t-import.cpp
new file mode 100644
index 0000000..33e242f
--- /dev/null
+++ b/lang/qt/tests/t-import.cpp
@@ -0,0 +1,169 @@
+/* t-import.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "t-support.h"
+
+#include "context.h"
+#include "engineinfo.h"
+#include "protocol.h"
+#include "importjob.h"
+
+#include <importresult.h>
+
+#include <QDebug>
+#include <QSignalSpy>
+#include <QTemporaryDir>
+#include <QTest>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class ImportTest : public QGpgMETest
+{
+ Q_OBJECT
+
+private:
+ QTemporaryDir tempGpgHome;
+
+private Q_SLOTS:
+ void initTestCase()
+ {
+ QGpgMETest::initTestCase();
+ QVERIFY2(tempGpgHome.isValid(), "Failed to create temporary GNUPGHOME");
+ qputenv("GNUPGHOME", tempGpgHome.path().toLocal8Bit());
+ }
+
+ void testImportWithImportFilter()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.14") {
+ QSKIP("gpg does not yet support the --import-filter option");
+ }
+
+ // pub ed25519 2021-12-15 [SC]
+ // E7A0841292ACC9465D3142652FB3A6F51FBF28A2
+ // uid [ultimate] importWithImportFilter@example.com
+ // uid [ultimate] importWithImportFilter@example.net
+ // sub cv25519 2021-12-15 [E]
+ static const char keyFpr[] = "E7A0841292ACC9465D3142652FB3A6F51FBF28A2";
+ static const char keyData[] =
+ "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
+ "\n"
+ "mDMEYbm2PhYJKwYBBAHaRw8BAQdACzxBWtNNsmJ6rzpZkjh1yBe+Ajsk9NR8umEu\n"
+ "Da3HLgG0ImltcG9ydFdpdGhJbXBvcnRGaWx0ZXJAZXhhbXBsZS5uZXSIlAQTFgoA\n"
+ "PBYhBOeghBKSrMlGXTFCZS+zpvUfvyiiBQJhubY+AhsDBQsJCAcCAyICAQYVCgkI\n"
+ "CwIEFgIDAQIeBwIXgAAKCRAvs6b1H78oosRgAQCc/ke6q076nvzIE2UzT83JK/B6\n"
+ "lxSV7Fb8bKltOMpvsAD+Phap3EzA8jdMyKoO0FM926bw5lX7QROfeZ/JBYqyPwC0\n"
+ "ImltcG9ydFdpdGhJbXBvcnRGaWx0ZXJAZXhhbXBsZS5jb22IlAQTFgoAPBYhBOeg\n"
+ "hBKSrMlGXTFCZS+zpvUfvyiiBQJhubZlAhsDBQsJCAcCAyICAQYVCgkICwIEFgID\n"
+ "AQIeBwIXgAAKCRAvs6b1H78oohPWAQC/u9UXzkxRkrB2huaTZCsyimWEGZIMmxWd\n"
+ "tE+vN9/IvQD/Yzia+xRS6yca3Yz6iW8xS844ZqRxvkUEHjtJXSOzagm4OARhubY+\n"
+ "EgorBgEEAZdVAQUBAQdANQFjmDctY3N0/ELPZtj9tapwFs4vrmTVpx/SCfZmihkD\n"
+ "AQgHiHgEGBYKACAWIQTnoIQSkqzJRl0xQmUvs6b1H78oogUCYbm2PgIbDAAKCRAv\n"
+ "s6b1H78oovGyAP41ySzvvDpV7XDJBOAFxvWLmywa5IcO7Lrg7y1efoWj0AD+Kk/B\n"
+ "s7jGLdoG51h670h50MMoYCANB6MwAdSP+qZUlQg=\n"
+ "=/3O0\n"
+ "-----END PGP PUBLIC KEY BLOCK-----\n";
+
+ auto *job = openpgp()->importJob();
+ job->setImportFilter(QLatin1String{"keep-uid=mbox = importWithImportFilter@example.net"});
+ connect(job, &ImportJob::result, this,
+ [this](ImportResult result, QString, Error)
+ {
+ QVERIFY(!result.error());
+ QVERIFY(!result.imports().empty());
+ QVERIFY(result.numImported());
+ Q_EMIT asyncDone();
+ });
+ job->start(QByteArray{keyData});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait());
+
+ auto ctx = Context::createForProtocol(GpgME::OpenPGP);
+ GpgME::Error err;
+ const auto key = ctx->key(keyFpr, err, false);
+ QVERIFY(!key.isNull());
+ QCOMPARE(key.numUserIDs(), 1);
+ QCOMPARE(key.userID(0).id(), "importWithImportFilter@example.net");
+ }
+
+ void testImportWithKeyOrigin()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.22") {
+ QSKIP("gpg does not yet support the --key-origin option");
+ }
+
+ static const char keyFpr[] = "5C5C428FABCC20F6913464BCCA6FB442887289B3";
+ static const char keyData[] =
+ "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
+ "\n"
+ "mDMEYbhuixYJKwYBBAHaRw8BAQdAulOM3IksCjdOJluEVlwalD8oZ5oa6wCw3EgW\n"
+ "NswXXb60H2ltcG9ydFdpdGhLZXlPcmlnaW5AZXhhbXBsZS5uZXSIlAQTFgoAPBYh\n"
+ "BFxcQo+rzCD2kTRkvMpvtEKIcomzBQJhuG6LAhsDBQsJCAcCAyICAQYVCgkICwIE\n"
+ "FgIDAQIeBwIXgAAKCRDKb7RCiHKJs+cIAQDaeoOw1OCAGpZQb8xJmLJHul5dLLzU\n"
+ "RBdHauMx9NROmQEA23QUVedc7walQjNKFzyIJA/YqRdbAKPiLonRBmxk9Ay4OARh\n"
+ "uG6LEgorBgEEAZdVAQUBAQdAMVdO9mNWIP/q8PtNOnBGlPyhx/vs07sF5sXk50A+\n"
+ "61QDAQgHiHgEGBYKACAWIQRcXEKPq8wg9pE0ZLzKb7RCiHKJswUCYbhuiwIbDAAK\n"
+ "CRDKb7RCiHKJs/x6AP0SEbZqW4iLCz2i1JntQghK5qpSZOVqsBTcARd6pcJ/cwEA\n"
+ "mrwskWazuS9+GVbHT5RATWOXnGaj+AICSDPE6qHtGgA=\n"
+ "=putz\n"
+ "-----END PGP PUBLIC KEY BLOCK-----\n";
+
+ auto *job = openpgp()->importJob();
+ job->setKeyOrigin(GpgME::Key::OriginWKD, "https://example.net");
+ connect(job, &ImportJob::result, this,
+ [this](ImportResult result, QString, Error)
+ {
+ QVERIFY(!result.error());
+ QVERIFY(!result.imports().empty());
+ QVERIFY(result.numImported());
+ Q_EMIT asyncDone();
+ });
+ job->start(QByteArray{keyData});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait());
+
+ auto ctx = Context::createForProtocol(GpgME::OpenPGP);
+ GpgME::Error err;
+ const auto key = ctx->key(keyFpr, err, false);
+ QVERIFY(!key.isNull());
+ QVERIFY(key.origin() == Key::OriginWKD);
+ // the origin URL is currently not available in GpgME
+ }
+};
+
+QTEST_MAIN(ImportTest)
+
+#include "t-import.moc"
diff --git a/lang/qt/tests/t-keylist.cpp b/lang/qt/tests/t-keylist.cpp
index 5875dfb..e481dfe 100644
--- a/lang/qt/tests/t-keylist.cpp
+++ b/lang/qt/tests/t-keylist.cpp
@@ -57,9 +57,6 @@ class KeyListTest : public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testSingleKeyListSync()
{
@@ -151,7 +148,7 @@ private Q_SLOTS:
delete job;
QVERIFY(!result.error());
- QCOMPARE(secKeys.size(), 2u);
+ QCOMPARE(secKeys.size(), static_cast<decltype(secKeys.size())>(2));
std::vector<std::string> secKeyFingerprints = std::accumulate(secKeys.begin(), secKeys.end(), std::vector<std::string>(), accumulateFingerprints);
QCOMPARE(secKeyFingerprints, std::vector<std::string>({
"23FD347A419429BACCD5E72D6BC4778054ACD246",
@@ -162,7 +159,7 @@ private Q_SLOTS:
QVERIFY(secKeys[0].subkeys()[0].keyGrip());
}
- QCOMPARE(pubKeys.size(), 26u);
+ QCOMPARE(pubKeys.size(), static_cast<decltype(pubKeys.size())>(26));
std::vector<std::string> pubKeyFingerprints = std::accumulate(pubKeys.begin(), pubKeys.end(), std::vector<std::string>(), accumulateFingerprints);
QCOMPARE(pubKeyFingerprints, std::vector<std::string>({
"045B2334ADD69FC221076841A5E67F7FA3AE3EA1",
diff --git a/lang/qt/tests/t-keylocate.cpp b/lang/qt/tests/t-keylocate.cpp
index 6d00da3..d84249c 100644
--- a/lang/qt/tests/t-keylocate.cpp
+++ b/lang/qt/tests/t-keylocate.cpp
@@ -51,9 +51,6 @@ class KeyLocateTest : public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
#ifdef DO_ONLINE_TESTS
diff --git a/lang/qt/tests/t-ownertrust.cpp b/lang/qt/tests/t-ownertrust.cpp
index 093c21e..31d2247 100644
--- a/lang/qt/tests/t-ownertrust.cpp
+++ b/lang/qt/tests/t-ownertrust.cpp
@@ -51,9 +51,6 @@ class ChangeOwnerTrustTest: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testChangeOwnerTrust()
diff --git a/lang/qt/tests/t-remarks.cpp b/lang/qt/tests/t-remarks.cpp
index c1880a7..f9a901a 100644
--- a/lang/qt/tests/t-remarks.cpp
+++ b/lang/qt/tests/t-remarks.cpp
@@ -54,9 +54,6 @@ class TestRemarks: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
public:
// This test is disabled (no slot) because the behavior
// is not clearly defined. Better to prevent that
@@ -77,12 +74,7 @@ public:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(false);
@@ -133,12 +125,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -170,11 +157,7 @@ private Q_SLOTS:
// Now replace the remark
auto job3 = openpgp()->signKeyJob();
QVERIFY (job3);
-
- // Hack in the passphrase provider
- auto jobCtx3 = Job::context(job3);
- jobCtx3->setPassphraseProvider(&provider);
- jobCtx3->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job3);
// Setup the job
job3->setExportable(false);
@@ -229,12 +212,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the first job
job->setExportable(false);
@@ -257,11 +235,7 @@ private Q_SLOTS:
// Now another remark from zulu
auto job3 = openpgp()->signKeyJob();
QVERIFY (job3);
-
- // Hack in the passphrase provider
- auto jobCtx3 = Job::context(job3);
- jobCtx3->setPassphraseProvider(&provider);
- jobCtx3->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job3);
// Setup the job
job3->setExportable(false);
@@ -315,12 +289,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(false);
@@ -352,11 +321,7 @@ private Q_SLOTS:
// Now replace the remark
auto job3 = openpgp()->signKeyJob();
QVERIFY (job3);
-
- // Hack in the passphrase provider
- auto jobCtx3 = Job::context(job3);
- jobCtx3->setPassphraseProvider(&provider);
- jobCtx3->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job3);
// Setup the job
job3->setExportable(false);
@@ -405,12 +370,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(false);
@@ -441,11 +401,7 @@ private Q_SLOTS:
// Try to replace it without dupeOK
auto job2 = openpgp()->signKeyJob();
QVERIFY (job2);
-
- // Hack in the passphrase provider
- auto jobCtx2 = Job::context(job2);
- jobCtx2->setPassphraseProvider(&provider);
- jobCtx2->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job2);
// Setup the job
job2->setExportable(false);
@@ -466,11 +422,7 @@ private Q_SLOTS:
// Now replace the remark
auto job3 = openpgp()->signKeyJob();
QVERIFY (job3);
-
- // Hack in the passphrase provider
- auto jobCtx3 = Job::context(job3);
- jobCtx3->setPassphraseProvider(&provider);
- jobCtx3->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job3);
// Setup the job
job3->setExportable(false);
diff --git a/lang/qt/tests/t-support.cpp b/lang/qt/tests/t-support.cpp
index 7b16ccc..6db082f 100644
--- a/lang/qt/tests/t-support.cpp
+++ b/lang/qt/tests/t-support.cpp
@@ -35,7 +35,10 @@
#endif
#include "t-support.h"
-#include "context.h"
+
+#include "importjob.h"
+#include "job.h"
+#include "protocol.h"
#include <QTest>
@@ -43,8 +46,14 @@
#include <QCoreApplication>
#include <QObject>
#include <QDir>
+#include <QSignalSpy>
+#include "context.h"
#include "engineinfo.h"
+#include "importresult.h"
+
+using namespace GpgME;
+using namespace QGpgME;
void QGpgMETest::initTestCase()
{
@@ -59,6 +68,12 @@ void QGpgMETest::cleanupTestCase()
killAgent();
}
+// static
+bool QGpgMETest::doOnlineTests()
+{
+ return !qgetenv("DO_ONLINE_TESTS").isEmpty();
+}
+
bool QGpgMETest::copyKeyrings(const QString &src, const QString &dest)
{
bool is21dir = QFileInfo(src + QDir::separator() + QStringLiteral("pubring.kbx")).exists();
@@ -86,6 +101,41 @@ bool QGpgMETest::copyKeyrings(const QString &src, const QString &dest)
return true;
}
+bool QGpgMETest::importSecretKeys(const char *keyData, int expectedKeys)
+{
+ auto job = std::unique_ptr<ImportJob>{openpgp()->importJob()};
+ VERIFY_OR_FALSE(job);
+ hookUpPassphraseProvider(job.get());
+
+ ImportResult result;
+ connect(job.get(), &ImportJob::result,
+ this, [this, &result](const ImportResult &result_) {
+ result = result_;
+ Q_EMIT asyncDone();
+ });
+ VERIFY_OR_FALSE(!job->start(keyData));
+ job.release(); // after the job has been started it's on its own
+
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ VERIFY_OR_FALSE(spy.wait(QSIGNALSPY_TIMEOUT));
+ VERIFY_OR_FALSE(!result.error());
+ VERIFY_OR_FALSE(!result.imports().empty());
+ COMPARE_OR_FALSE(result.numSecretKeysImported(), expectedKeys);
+
+ return true;
+}
+
+void QGpgMETest::hookUpPassphraseProvider(GpgME::Context *context)
+{
+ context->setPassphraseProvider(&mPassphraseProvider);
+ context->setPinentryMode(Context::PinentryLoopback);
+}
+
+void QGpgMETest::hookUpPassphraseProvider(QGpgME::Job *job)
+{
+ hookUpPassphraseProvider(Job::context(job));
+}
+
void killAgent(const QString& dir)
{
QProcess proc;
diff --git a/lang/qt/tests/t-support.h b/lang/qt/tests/t-support.h
index 77bef56..ecafe2f 100644
--- a/lang/qt/tests/t-support.h
+++ b/lang/qt/tests/t-support.h
@@ -34,11 +34,57 @@
#include "interfaces/passphraseprovider.h"
#include <QObject>
+#include <QTest>
#include <gpg-error.h>
namespace GpgME
{
+class Context;
+}
+
+namespace QGpgME
+{
+class Job;
+}
+
+/// generic variant of QVERIFY returning \a returnValue on failure
+#define VERIFY_OR_RETURN_VALUE(statement, returnValue) \
+do {\
+ if (!QTest::qVerify(static_cast<bool>(statement), #statement, "", __FILE__, __LINE__))\
+ return returnValue;\
+} while (false)
+
+/// generic variant of QCOMPARE returning \a returnValue on failure
+#define COMPARE_OR_RETURN_VALUE(actual, expected, returnValue) \
+do {\
+ if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__))\
+ return returnValue;\
+} while (false)
+
+/// variant of QVERIFY returning a default constructed object on failure
+#define VERIFY_OR_OBJECT(statement) VERIFY_OR_RETURN_VALUE(statement, {})
+
+/// variant of QCOMPARE returning a default constructed object on failure
+#define COMPARE_OR_OBJECT(actual, expected) COMPARE_OR_RETURN_VALUE(actual, expected, {})
+
+/// variant of QVERIFY returning \c false on failure
+#define VERIFY_OR_FALSE(statement) VERIFY_OR_RETURN_VALUE(statement, false)
+
+/// variant of QCOMPARE returning \c false on failure
+#define COMPARE_OR_FALSE(actual, expected) COMPARE_OR_RETURN_VALUE(actual, expected, false)
+
+namespace QTest
+{
+template <>
+inline char *toString(const std::string &s)
+{
+ return QTest::toString(s.c_str());
+}
+}
+
+namespace GpgME
+{
class TestPassphraseProvider : public PassphraseProvider
{
public:
@@ -59,12 +105,26 @@ bool loopbackSupported();
class QGpgMETest : public QObject
{
Q_OBJECT
+
+Q_SIGNALS:
+ void asyncDone();
+
protected:
+ static bool doOnlineTests();
+
bool copyKeyrings(const QString &from, const QString& to);
+ bool importSecretKeys(const char *keyData, int expectedKeys = 1);
+
+ void hookUpPassphraseProvider(GpgME::Context *context);
+ void hookUpPassphraseProvider(QGpgME::Job *job);
+
public Q_SLOTS:
void initTestCase();
void cleanupTestCase();
+
+private:
+ GpgME::TestPassphraseProvider mPassphraseProvider;
};
/* Timeout, in milliseconds, for use with QSignalSpy to wait on
diff --git a/lang/qt/tests/t-tofuinfo.cpp b/lang/qt/tests/t-tofuinfo.cpp
index 2d88106..a1871c4 100644
--- a/lang/qt/tests/t-tofuinfo.cpp
+++ b/lang/qt/tests/t-tofuinfo.cpp
@@ -116,8 +116,6 @@ static const char conflictMsg2[] = "-----BEGIN PGP MESSAGE-----\n"
class TofuInfoTest: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
private:
bool testSupported()
@@ -155,10 +153,7 @@ private:
void signAndVerify(const QString &what, const GpgME::Key &key, int expected)
{
auto job = openpgp()->signJob();
- auto ctx = Job::context(job);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
std::vector<Key> keys;
keys.push_back(key);
diff --git a/lang/qt/tests/t-trustsignatures.cpp b/lang/qt/tests/t-trustsignatures.cpp
index d392b2f..6f7ad82 100644
--- a/lang/qt/tests/t-trustsignatures.cpp
+++ b/lang/qt/tests/t-trustsignatures.cpp
@@ -1,4 +1,4 @@
-/* t-remarks.cpp
+/* t-trustsignatures.cpp
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2021 g10 Code GmbH
@@ -52,9 +52,6 @@ class TestTrustSignatures: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void test_tsign_single_uid_key_and_then_tsign_it_again()
{
@@ -83,12 +80,7 @@ private Q_SLOTS:
// Create the job
auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job.get());
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job.get());
// Setup the job
job->setExportable(true);
@@ -131,12 +123,7 @@ private Q_SLOTS:
// Create the job
auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job.get());
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job.get());
// Setup the job
job->setExportable(true);
@@ -204,12 +191,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -252,12 +234,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -325,12 +302,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -374,12 +346,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -447,12 +414,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -495,12 +457,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
diff --git a/lang/qt/tests/t-various.cpp b/lang/qt/tests/t-various.cpp
index 8563b68..b630350 100644
--- a/lang/qt/tests/t-various.cpp
+++ b/lang/qt/tests/t-various.cpp
@@ -71,9 +71,6 @@ class TestVarious: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testDN()
{
@@ -137,9 +134,7 @@ private Q_SLOTS:
auto ctx = Context::createForProtocol(key.protocol());
QVERIFY (ctx);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(ctx);
QVERIFY(!ctx->addUid(key, uid));
delete ctx;
@@ -190,9 +185,7 @@ private Q_SLOTS:
auto ctx = Context::createForProtocol(key.protocol());
QVERIFY (ctx);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(ctx);
// change expiration of the main key
QVERIFY(!ctx->setExpire(key, 1000));
@@ -230,7 +223,7 @@ private Q_SLOTS:
std::vector<Subkey> primaryKey;
primaryKey.push_back(key.subkey(0));
const auto err = ctx->setExpire(key, 3000, primaryKey);
- QCOMPARE(err.code(), GPG_ERR_NOT_FOUND);
+ QCOMPARE(err.code(), static_cast<int>(GPG_ERR_NOT_FOUND));
delete ctx;
}
@@ -259,12 +252,7 @@ private Q_SLOTS:
// Create the job
auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job.get());
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job.get());
// Setup the job
job->setExportable(true);
@@ -319,12 +307,7 @@ private Q_SLOTS:
// Create the job
auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job.get());
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job.get());
// Setup the job
job->setExportable(true);
@@ -355,7 +338,7 @@ private Q_SLOTS:
target.update();
const auto keySignature = target.userID(0).signature(target.userID(0).numSignatures() - 1);
QVERIFY(!keySignature.neverExpires());
- const auto expirationDate = QDateTime::fromSecsSinceEpoch(keySignature.expirationTime()).date();
+ const auto expirationDate = QDateTime::fromSecsSinceEpoch(uint_least32_t(keySignature.expirationTime())).date();
QCOMPARE(expirationDate, QDate(2106, 2, 6)); // expiration date is capped at 2106-02-06
}
diff --git a/lang/qt/tests/t-wkdlookup.cpp b/lang/qt/tests/t-wkdlookup.cpp
new file mode 100644
index 0000000..5c2816c
--- /dev/null
+++ b/lang/qt/tests/t-wkdlookup.cpp
@@ -0,0 +1,155 @@
+/* t-wkdlookup.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "t-support.h"
+
+#include "data.h"
+#include "engineinfo.h"
+#include "protocol.h"
+#include "wkdlookupjob.h"
+#include "wkdlookupresult.h"
+
+#include <QDebug>
+#include <QSignalSpy>
+#include <QTest>
+
+#include <algorithm>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+static const char *requiredVersion = "2.1.12";
+
+namespace
+{
+bool keyHasUserIDWithMatchingEmailAddress(const Key &key, const QString &expectedEmailAddress)
+{
+ const auto email = expectedEmailAddress.toLower();
+ const auto userIds = key.userIDs();
+ return std::any_of(
+ std::begin(userIds), std::end(userIds),
+ [email](const UserID &uid) {
+ return email == QString::fromUtf8(uid.email()).toLower();
+ });
+}
+}
+
+class WKDLookupTest : public QGpgMETest
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void testWKDLookupAsync()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
+ QSKIP("dirmngr does not yet support WKD lookup");
+ }
+ if (!doOnlineTests()) {
+ QSKIP("Set DO_ONLINE_TESTS environment variable to run this test.");
+ }
+ const QString email = QLatin1String{"wk@gnupg.org"};
+
+ WKDLookupResult result;
+ auto *job = openpgp()->wkdLookupJob();
+ connect(job, &WKDLookupJob::result, job, [this, &result](const WKDLookupResult &result_, const QString &, const Error &)
+ {
+ result = result_;
+ Q_EMIT asyncDone();
+ });
+ job->start(email);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ QVERIFY(result.error().code() == GPG_ERR_NO_ERROR);
+ QCOMPARE(result.pattern(), "wk@gnupg.org");
+ QCOMPARE(result.source(), "https://openpgpkey.gnupg.org");
+ const auto keys = result.keyData().toKeys(GpgME::OpenPGP);
+ QVERIFY(keys.size() == 1);
+ QVERIFY(keyHasUserIDWithMatchingEmailAddress(keys.front(), email));
+ }
+
+ void testWKDLookupSync()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
+ QSKIP("dirmngr does not yet support WKD lookup");
+ }
+ if (!doOnlineTests()) {
+ QSKIP("Set DO_ONLINE_TESTS environment variable to run this test.");
+ }
+ const QString email = QLatin1String{"wk@gnupg.org"};
+
+ auto *job = openpgp()->wkdLookupJob();
+ const auto result = job->exec(email);
+
+ QVERIFY(result.error().code() == GPG_ERR_NO_ERROR);
+ QCOMPARE(result.pattern(), "wk@gnupg.org");
+ QCOMPARE(result.source(), "https://openpgpkey.gnupg.org");
+ const auto keys = result.keyData().toKeys(GpgME::OpenPGP);
+ QVERIFY(keys.size() == 1);
+ QVERIFY(keyHasUserIDWithMatchingEmailAddress(keys.front(), email));
+ }
+
+ void testLookupWithNoResultAsync()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
+ QSKIP("dirmngr does not yet support WKD lookup");
+ }
+ if (!doOnlineTests()) {
+ QSKIP("Set DO_ONLINE_TESTS environment variable to run this test.");
+ }
+ const QString email = QLatin1String{"alfa@example.net"};
+
+ WKDLookupResult result;
+ auto *job = openpgp()->wkdLookupJob();
+ connect(job, &WKDLookupJob::result, job, [this, &result](const WKDLookupResult &result_, const QString &, const Error &)
+ {
+ result = result_;
+ Q_EMIT asyncDone();
+ });
+ job->start(email);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ QVERIFY(result.error().code() == GPG_ERR_NO_ERROR);
+ QCOMPARE(result.pattern(), "alfa@example.net");
+ QCOMPARE(result.source(), "");
+ QVERIFY(result.keyData().isNull());
+ }
+};
+
+QTEST_MAIN(WKDLookupTest)
+
+#include "t-wkdlookup.moc"
diff --git a/lang/qt/tests/t-wkspublish.cpp b/lang/qt/tests/t-wkspublish.cpp
index b389194..618f0b4 100644
--- a/lang/qt/tests/t-wkspublish.cpp
+++ b/lang/qt/tests/t-wkspublish.cpp
@@ -118,9 +118,6 @@ class WKSPublishTest : public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testUnsupported()
{