diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk index d0af3f0..8bd1a6d 100755 --- a/app/src/main/jni/Android.mk +++ b/app/src/main/jni/Android.mk @@ -78,20 +78,7 @@ LOCAL_SRC_FILES := httrack/src/htscore.c httrack/src/htsparse.c \ httrack/src/htsconcat.c httrack/src/htsmodules.c \ httrack/src/htscharset.c httrack/src/punycode.c \ httrack/src/htsencoding.c httrack/src/md5.c \ - httrack/src/htssniff.c httrack/src/htsselftest.c \ - httrack/src/htsselftest_util.c \ - httrack/src/htsback_selftest.c httrack/src/htscache_selftest.c \ - httrack/src/htsbundle_selftest.c \ - httrack/src/htscharset_selftest.c httrack/src/htscmdline_selftest.c \ - httrack/src/htscookie_selftest.c \ - httrack/src/htsdns_selftest.c httrack/src/htsfilters_selftest.c \ - httrack/src/htsheader_selftest.c httrack/src/htsio_selftest.c \ - httrack/src/htslib_selftest.c httrack/src/htslines_selftest.c \ - httrack/src/htsmime_selftest.c \ - httrack/src/htsname_selftest.c httrack/src/htsnet_selftest.c \ - httrack/src/htsopt_selftest.c httrack/src/htsparse_selftest.c \ - httrack/src/htstools_selftest.c \ - httrack/src/htswarc_selftest.c httrack/src/htswizard_selftest.c \ + httrack/src/htssniff.c \ httrack/src/htscodec.c httrack/src/htsproxy.c \ httrack/src/htsdate.c httrack/src/htsurlport.c httrack/src/htswarc.c \ httrack/src/htsescape.c \ @@ -99,9 +86,8 @@ LOCAL_SRC_FILES := httrack/src/htscore.c httrack/src/htsparse.c \ httrack/src/htssitemap.c httrack/src/htssinglefile.c \ httrack/src/htschanges.c httrack/src/htscmdline.c \ httrack/src/htslines.c \ - httrack/src/htsfetch.c httrack/src/htsfetch_selftest.c \ + httrack/src/htsfetch.c \ httrack/src/htspsl.c httrack/src/htspsl_data.c \ - httrack/src/htspsl_selftest.c \ httrack/src/htscrashtest.c \ httrack/src/minizip/ioapi.c \ httrack/src/minizip/mztools.c httrack/src/minizip/unzip.c \ @@ -127,6 +113,9 @@ LOCAL_CFLAGS += -O3 -g3 -funwind-tables -fPIC \ -Wno-nested-externs \ -D_REENTRANT -DPIC -DANDROID -D_ANDROID -DHAVE_CONFIG_H -DINET6 -DHTS_INTERNAL_BUILD \ -DLIBHTTRACK_EXPORTS -DZLIB_CONST -DHTS_INTHASH_USES_MD5 -DLIBICONV_PLUG +# The app never asks the engine for a self-test. The sources are gone from +# LOCAL_SRC_FILES above too, because htsselftest_int.h #errors under this macro. +LOCAL_CFLAGS += -DHTS_NO_SELFTEST LOCAL_CPPFLAGS += -pthread include $(BUILD_SHARED_LIBRARY) diff --git a/app/src/test/java/com/httrack/android/CodeqlScopeTest.java b/app/src/test/java/com/httrack/android/CodeqlScopeTest.java index 63f4772..a54b251 100644 --- a/app/src/test/java/com/httrack/android/CodeqlScopeTest.java +++ b/app/src/test/java/com/httrack/android/CodeqlScopeTest.java @@ -19,7 +19,6 @@ */ public class CodeqlScopeTest { private static final String WORKFLOW = ".github/workflows/codeql.yml"; - private static final String ANDROID_MK = "app/src/main/jni/Android.mk"; private static final String UNTRACED = "Build the engine, untraced"; private static final String TRACED = "Recompile the JNI glue, traced"; private static final String INIT = "github/codeql-action/init"; @@ -37,7 +36,7 @@ private static String flattened(final String path) throws IOException { /** Every source the htslibjni module builds, "+=" included, so an appended one is not missed. */ private static Set glueSources() throws IOException { - final String mk = flattened(ANDROID_MK); + final String mk = TestSources.flattenedMakefile(); final Matcher module = Pattern.compile("LOCAL_MODULE\\s*:=\\s*htslibjni\\b").matcher(mk); assertTrue("Android.mk must still define the htslibjni module", module.find()); final String body = mk.substring(module.end()).split("include \\$\\(BUILD")[0]; diff --git a/app/src/test/java/com/httrack/android/EngineSelftestsExcludedTest.java b/app/src/test/java/com/httrack/android/EngineSelftestsExcludedTest.java new file mode 100644 index 0000000..a50d526 --- /dev/null +++ b/app/src/test/java/com/httrack/android/EngineSelftestsExcludedTest.java @@ -0,0 +1,64 @@ +package com.httrack.android; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.Test; + +/** + * The engine refuses to compile a self-test source under HTS_NO_SELFTEST, so re-adding one to + * Android.mk breaks the build. A later engine could add a self-test that does not include that + * header, and then nothing would notice, so hold the engine's own list against ours. + */ +public class EngineSelftestsExcludedTest { + /** The sources the engine builds only when self-tests are wanted, basenames. */ + private static Set engineSelftests() throws IOException { + final String makefile = TestSources.read(TestSources.engineFile("src/Makefile.am")) + .replaceAll("\\\\\n\\s*", " "); + final String block = TestSources.between(makefile, "if SELFTESTS", "endif"); + final Matcher sources = Pattern.compile("_SOURCES\\s*[:+]?=\\s*([^\n]*)").matcher(block); + final Set all = new LinkedHashSet(); + assertTrue("the engine must still gate its self-tests on SELFTESTS", sources.find()); + do { + all.addAll(Arrays.asList(sources.group(1).trim().split("\\s+"))); + } while (sources.find()); + return all; + } + + /** Basenames of the engine sources the libhttrack module builds. */ + private static Set engineSourcesBuilt() throws IOException { + final String mk = TestSources.flattenedMakefile(); + final Matcher module = Pattern.compile("LOCAL_MODULE\\s*:=\\s*libhttrack\\b").matcher(mk); + assertTrue("Android.mk must still define the libhttrack module", module.find()); + final String body = mk.substring(module.end()).split("include \\$\\(BUILD")[0]; + final Matcher sources = Pattern.compile("LOCAL_SRC_FILES\\s*[:+]?=\\s*([^\n]*)").matcher(body); + final Set all = new LinkedHashSet(); + assertTrue("the libhttrack module must still carry a source list", sources.find()); + do { + for (final String path : sources.group(1).trim().split("\\s+")) { + all.add(path.substring(path.lastIndexOf('/') + 1)); + } + } while (sources.find()); + return all; + } + + @Test + public void noEngineSelftestIsBuilt() throws IOException { + final Set selftests = engineSelftests(); + final Set built = engineSourcesBuilt(); + assertFalse("no self-test source parsed, so this test would pass on anything", + selftests.isEmpty()); + // Control: an engine source that must be built, or the list above could be read as empty. + assertTrue("htscore.c must still be built", built.contains("htscore.c")); + final Set both = new LinkedHashSet(built); + both.retainAll(selftests); + assertTrue("the APK must not build the engine self-tests: " + both, both.isEmpty()); + } +} diff --git a/app/src/test/java/com/httrack/android/TestSources.java b/app/src/test/java/com/httrack/android/TestSources.java index 3763635..d1dd14d 100644 --- a/app/src/test/java/com/httrack/android/TestSources.java +++ b/app/src/test/java/com/httrack/android/TestSources.java @@ -57,6 +57,12 @@ static File resFile(final String name) { return new File(dir("src/main/res"), name); } + /** Android.mk, free of CRLF and line continuations, so a wrapped list matches in one line. */ + static String flattenedMakefile() throws IOException { + return read(new File(dir("src/main/jni"), "Android.mk")).replace("\r", "") + .replaceAll("\\\\\n\\s*", " "); + } + static String read(final File file) throws IOException { return new String(Files.readAllBytes(file.toPath()), "UTF-8"); }