summaryrefslogtreecommitdiff
path: root/dev-java/junit/junit-5.10.2.ebuild
blob: 6e794beca25880954084cfb41e6ec6530c5c3617 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
# Copyright 1999-2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=8

# Declare the 'doc' USE flag in IUSE -- not JAVA_PKG_IUSE -- to
# prevent java-pkg-simple.eclass from handling Javadoc; instead,
# let this ebuild handle Javadoc generation and installation itself.
# This ebuild invokes java-pkg-simple.eclass's phase functions
# multiple times to build multiple modules, but the eclass always
# installs each module's Javadoc to the same directory, which would
# trigger an error when the second module's Javadoc is installed.
JAVA_PKG_IUSE="source test"

inherit java-pkg-2 java-pkg-simple

DESCRIPTION="Simple framework to write repeatable tests"
HOMEPAGE="https://junit.org/junit5/"
DEB="5.10.1-1"
SRC_URI="https://github.com/junit-team/junit5/archive/r${PV}.tar.gz -> ${P}.tar.gz
	https://sources.debian.org/data/main/j/junit5/${DEB}/debian/patches/18-java-compatibility.patch \
	-> junit5-java18-compatibility.patch"
S="${WORKDIR}/junit5-r${PV}"

LICENSE="EPL-2.0"
SLOT="5"
KEYWORDS="~amd64 ~arm ~arm64"
IUSE="doc migration-support suite vintage"

CP_DEPEND="
	dev-java/apiguardian-api:0
	dev-java/opentest4j:0
	dev-java/open-test-reporting-events:0
	dev-java/picocli:0
	dev-java/univocity-parsers:0
"

# java-utils-2.eclass does not support
# USE-conditional dependencies in CP_DEPEND
COND_DEPEND="
	migration-support? ( dev-java/junit:4 )
	vintage? ( dev-java/junit:4 )
"

# Limiting JDK version to >=11 for module-info.java in this package
# https://bugs.gentoo.org/796875#c3
DEPEND="
	>=virtual/jdk-11:*
	${CP_DEPEND}
	${COND_DEPEND}
	test? ( dev-java/jimfs:0 )
"

RDEPEND="
	>=virtual/jre-1.8:*
	${CP_DEPEND}
	${COND_DEPEND}
"

PATCHES=(
	"${DISTDIR}/junit5-java18-compatibility.patch"
)

src_prepare() {
	default #780585
	java-pkg-2_src_prepare
}

src_configure() {
	# Please make sure to declare a module's dependencies before the module itself.
	# Useful upstream documentation regarding modules and dependencies:
	# https://junit.org/junit5/docs/current/user-guide/index.html#dependency-metadata
	# https://junit.org/junit5/docs/current/user-guide/index.html#dependency-diagram
	JUNIT5_MODULES=(
		junit-platform-commons
		junit-platform-engine
		junit-platform-launcher
		junit-platform-reporting
		junit-platform-console # For launching tests from CLI;
		# an eclass would need it to support running tests using JUnit 5

		$(use suite && echo \
			junit-platform-suite-api \
			junit-platform-suite-commons \
			junit-platform-suite-engine \
		)

		junit-jupiter-api
		junit-jupiter-engine # For JUnit Jupiter tests -- the so-called
		# "JUnit 5 tests", which cannot run on earlier JUnit versions
		junit-jupiter-params # For parameterized tests; the junit-jupiter
		# aggregator module includes it, so building it unconditionally
		$(usev migration-support junit-jupiter-migrationsupport)

		$(usev vintage junit-vintage-engine)

		# Modules not included:
		# - junit-bom: Has no sources; solely for helping Maven and Gradle
		#   projects that use JUnit 5 manage dependencies easier
		# - junit-jupiter: Aggregator; does not have 'src/main/java'
		# - junit-platform-console-standalone: Has no sources; solely used
		#   by the upstream to build a fat JAR that bundles everything, so
		#   users can use just this single JAR to run JUnit 5
		# - junit-platform-jfr: For an experimental feature
		# - junit-platform-runner: Deprecated
		# - junit-platform-suite: Aggregator; does not have 'src/main/java'
		# - junit-platform-testkit: Requires >=dev-java/assertj-core-3.14.0
	)
	local cp_packages=()
	(use migration-support || use vintage) && cp_packages+=( junit-4 )
	local save_IFS="${IFS}"
	IFS=',' JAVA_GENTOO_CLASSPATH="${cp_packages[*]}"
	IFS="${save_IFS}"

	JUNIT5_VM_VERSION="$(java-config --get-env PROVIDES_VERSION)"
}

junit5_foreach_module() {
	local module
	for module in "${JUNIT5_MODULES[@]}"; do
		junit5_module_do "${module}" "${@}"
	done
}

junit5_module_do() {
	local module="${1}"
	# Invocation of the passed function will not be guarded by '|| die'.
	# Like the case for multibuild_foreach_variant(), it is recommended
	# that the passed function itself calls 'die'.
	local func=( "${@:2}" )

	einfo "Running '${func[@]}' for ${module} ..."
	pushd "${module}" > /dev/null || die "Failed to enter directory '${module}'"

	# Set up Java eclass variables that are
	# supposed to be set in the ebuild global scope

	local JAVA_JAR_FILENAME="${module}.jar"

	local JAVA_SRC_DIR=(
		src/main/java
		src/module
	)

	local JAVA_RESOURCE_DIRS=()
	local default_resource_dir="src/main/resources"
	[[ -d "${default_resource_dir}" ]] &&
		JAVA_RESOURCE_DIRS+=( "${default_resource_dir}" )

	if [[ "${module}" == junit-platform-console ]]; then
		local JAVA_MAIN_CLASS="org.junit.platform.console.ConsoleLauncher"
		local JAVA_LAUNCHER_FILENAME="${module}"
	fi

	# Invoke the passed function
	"${func[@]}"
	local ret="${?}"

	popd > /dev/null || die "Failed to leave directory '${module}'"
	return "${ret}"
}

junit5_gen_cp() {
	echo "$(java-pkg_getjars --build-only --with-dependencies \
		"${JAVA_GENTOO_CLASSPATH}"):${JAVA_GENTOO_CLASSPATH_EXTRA}"
}

junit5_module_compile() {
	if [[ "${module}" == junit-platform-console ]]; then
		# Unlike other modules that have a src/main/java9 directory, for this
		# module, the upstream puts the class files built from src/main/java9
		# in their JAR's top-level directory instead of META-INF/versions/9
		cp -rv src/main/java9/* src/main/java/ ||
			die "Failed to merge ${module}'s sources for Java 9+"
		# Remove for the [[ -d src/main/java9 ]] test
		# during versioned directory handling
		rm -rv src/main/java9 ||
			die "Failed to remove ${module}'s Java 9+ source directory"
	fi

	java-pkg-simple_src_compile
	local sources="sources.lst"
	local classes="target/classes"

	# Collect a list of all compiler input files for building Javadoc
	local source
	while read source; do
		echo "${module}/${source}" >> "${all_sources}"
	done < "${sources}" ||
		die "Failed to add ${module}'s sources to Javadoc input list"

	# Handle classes that will go into versioned directories.  This will be
	# no longer needed after https://bugs.gentoo.org/900433 is implemented.
	local vm_ver
	for vm_ver in 9 17; do
		local versioned_src="src/main/java${vm_ver}"
		if [[ -d "${versioned_src}" ]]; then
			if ver_test "${JUNIT5_VM_VERSION}" -ge "${vm_ver}"; then
				local versioned_classes="target/${vm_ver}/classes"
				mkdir -p "${versioned_classes}" ||
					die "Failed to create directory for ${module}'s Java ${vm_ver}+ classes"
				ejavac -d "${versioned_classes}" -encoding "${JAVA_ENCODING}" \
					-classpath "${classes}:$(junit5_gen_cp)" ${JAVAC_ARGS} \
					$(find "${versioned_src}" -type f -name '*.java')
				"$(java-config --jar)" -uvf "${JAVA_JAR_FILENAME}" \
					--release "${vm_ver}" -C "${versioned_classes}" . ||
					die "Failed to add ${module}'s Java ${vm_ver}+ classes to JAR"
			else
				# Modules that may hit this branch as of 5.9.2:
				# - junit-platform-console:
				#   src/main/java17/.../ConsoleUtils.java tries to use
				#   java.io.Console.charset() (available since Java 17) to get
				#   the default output charset.  It is fine to not use this
				#   file, even if the built artifacts will be used on JRE 17+,
				#   as src/main/java/.../ConsoleUtils.java still gets the
				#   default from java.nio.charset.Charset.defaultCharset().
				elog "JDK ${JUNIT5_VM_VERSION} used; skipping Java ${vm_ver}-dependent parts in ${module}"
			fi
		fi
	done

	# Add the current module's JAR to classpath
	# for the module's reverse dependencies in this package
	JAVA_GENTOO_CLASSPATH_EXTRA+=":${S}/${module}/${JAVA_JAR_FILENAME}"
}

src_compile() {
	local all_sources="${S}/all-sources.lst"
	junit5_foreach_module junit5_module_compile

	if use doc; then
		einfo "Generating Javadoc for all modules ..."
		local apidoc="target/api"
		mkdir -p "${apidoc}" || die "Failed to create Javadoc directory"
		ejavadoc -d "${apidoc}" \
			-encoding "${JAVA_ENCODING}" -docencoding UTF-8 -charset UTF-8 \
			-classpath "$(junit5_gen_cp)" ${JAVADOC_ARGS:- -quiet} \
			-windowtitle "JUnit ${PV} API" \
			"@${all_sources}"
	fi
}

src_test() {
	# Running the JUnit 5 modules' tests (located in each module's
	# 'src/test/java') has a few obstacles:
	# - Some test sources use text blocks -- a feature introduced in Java 15.
	#   A JDK at a lower version, e.g. 11, cannot compile them.
	# - Some test classes depend on JUnit 5 modules that this ebuild does not
	#   include, like junit-platform-runner and junit-platform-testkit.
	#
	# Therefore, this ebuild uses a simpler approach to test the artifacts just
	# built: it uses the artifacts to run tests in examples under the
	# 'documentation/src' directory.  The test coverage will not be impressive,
	# but at least this approach verifies that the copy of JUnit 5 just built
	# is capable of running some simple tests launched from CLI.

	local JUNIT5_TEST_SRC_DIR="documentation/src/test/java"
	local JUNIT5_TEST_RESOURCE_DIR="documentation/src/test/resources"
	local JUNIT5_TEST_RM=(
		$(usev !migration-support example/IgnoredTestsDemo.java)
		$(use !suite && echo \
			example/DocumentationTestSuite.java \
			example/SuiteDemo.java \
		)
		$(usev !vintage example/JUnit4Tests.java)

		# Need excluded module junit-platform-runner
		example/JUnitPlatformClassDemo.java
		example/JUnitPlatformSuiteDemo.java

		# Need excluded module junit-platform-testkit
		example/testkit/

		# Not necessary for the tests; some files even require extra dependency
		org/junit/api/tools/

		# Needs dev-java/hamcrest; no need to pull in extra dependency
		# as the examples already provide ample tests to run
		example/HamcrestAssertionsDemo.java

		# Makes an HTTP request and expects a certain response
		example/session/HttpTests.java
	)

	pushd "${JUNIT5_TEST_SRC_DIR}" > /dev/null ||
		die "Failed to enter test source directory"
	rm -rv "${JUNIT5_TEST_RM[@]}" ||
		die "Failed to remove unneeded test sources"
	# Test sources expect the working directory to be 'documentation'
	sed -i -e "s|src/test/resources|${JUNIT5_TEST_RESOURCE_DIR}|g" \
		example/ParameterizedTestDemo.java ||
		die "Failed to update file paths in test sources"
	popd > /dev/null || die "Failed to leave test source directory"

	local test_dir="${T}/junit5_src_test"
	local example_classes="${test_dir}/classes"
	local test_classes="${test_dir}/test-classes"
	mkdir -p "${example_classes}" "${test_classes}" ||
		die "Failed to create test directories"

	local example_sources="${test_dir}/sources.lst"
	local test_sources="${test_dir}/test-sources.lst"
	find documentation/src/main/java -type f -name '*.java' > "${example_sources}" ||
		die "Failed to get a list of example sources"
	find documentation/src/test/java -type f -name '*.java' > "${test_sources}" ||
		die "Failed to get a list of test sources"

	ejavac -d "${example_classes}" -encoding "${JAVA_ENCODING}" \
		-classpath "$(junit5_gen_cp)" ${JAVAC_ARGS} \
		"@${example_sources}"

	local test_cp="${example_classes}:${JUNIT5_TEST_RESOURCE_DIR}:$(junit5_gen_cp)"
	test_cp="${test_cp}:$(java-pkg_getjars --build-only --with-dependencies jimfs)"
	ejavac -d "${test_classes}" -encoding "${JAVA_ENCODING}" \
		-classpath "${test_cp}" ${JAVAC_ARGS} \
		"@${test_sources}"

	set -- "$(java-config --java)" -classpath "${test_classes}:${test_cp}" \
		org.junit.platform.console.ConsoleLauncher \
		--disable-ansi-colors --fail-if-no-tests --scan-classpath \
		--include-classname='^(Test.*|.+[.$]Test.*|.*Tests?|.*Demo)$' \
		--exclude-tag="exclude"
	echo "${@}" >&2
	"${@}"
	local status="${?}"
	[[ "${status}" -eq 2 ]] && die "JUnit did not discover any tests"
	[[ "${status}" -eq 0 ]] || die "ConsoleLauncher failed"
}

junit5_module_install() {
	# It is OK to let java-pkg-simple_src_install call einstalldocs for
	# each module as long as each documentation file being installed
	# has a unique filename among _all_ modules; otherwise, some files
	# would overwrite other ones.
	if [[ -f README.md ]]; then
		mv -v README.md "README-${module}.md" ||
			die "Failed to rename ${module}'s README.md"
	fi
	java-pkg-simple_src_install
}

src_install() {
	junit5_foreach_module junit5_module_install
	einstalldocs # For project-global documentation

	if use doc; then
		einfo "Installing Javadoc for all modules ..."
		local apidoc="target/api"
		java-pkg_dojavadoc "${apidoc}"
	fi
}