<commit_before>/*
 * Copyright 2020 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

package org.tinylog.core.test;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.tinylog.core.Configuration;
import org.tinylog.core.Framework;
import org.tinylog.core.backend.LoggingBackend;

/**
 * JUnit extension for capturing output log entries.
 *
 * <p>
 *     Use the annotation {@link CaptureLogEntries} to apply this extension.
 * </p>
 */
public class LogCaptureExtension implements ParameterResolver, BeforeEachCallback, AfterEachCallback {

	private static final Namespace NAMESPACE = Namespace.create(LogCaptureExtension.class);

	/** */
	public LogCaptureExtension() {
	}

	@Override
	public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
		Class<?> type = parameterContext.getParameter().getType();
		return type == Framework.class || type == Log.class;
	}

	@Override
	public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
		Class<?> type = parameterContext.getParameter().getType();
		if (type == Framework.class) {
			return getOrCreateFramework(extensionContext);
		} else if (type == Log.class) {
			return getOrCreateLog(extensionContext);
		} else {
			throw new IllegalStateException("Unexpected parameter type: " + type.getName());
		}
	}

	@Override
	public void beforeEach(ExtensionContext context) {
		Framework framework = getOrCreateFramework(context);
		Configuration configuration = framework.getConfiguration();

		context.getTestInstance().ifPresent(object -> {
			CaptureLogEntries annotation = object.getClass().getAnnotation(CaptureLogEntries.class);
			if (annotation != null) {
				for (String entry : annotation.configuration()) {
					int index = entry.indexOf('=');
					if (index >= 0) {
						String key = entry.substring(0, index);
						String value = entry.substring(index + 1);
						configuration.set(key, value);
					}
				}
			}
		});

		framework.startUp();
	}

	@Override
	public void afterEach(ExtensionContext context) {
		try {
			getOrCreateFramework(context).shutDown();
			Assertions<commit_msg>Support nested log capture extensions<commit_after>/*
 * Copyright 2020 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

package org.tinylog.core.test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.tinylog.core.Configuration;
import org.tinylog.core.Framework;
import org.tinylog.core.backend.LoggingBackend;

/**
 * JUnit extension for capturing output log entries.
 *
 * <p>
 *     Use the annotation {@link CaptureLogEntries} to apply this extension.
 * </p>
 */
public class LogCaptureExtension implements ParameterResolver, BeforeEachCallback, AfterEachCallback {

	private static final Namespace NAMESPACE = Namespace.create(LogCaptureExtension.class);

	/** */
	public LogCaptureExtension() {
	}

	@Override
	public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
		Class<?> type = parameterContext.getParameter().getType();
		return type == Framework.class || type == Log.class;
	}

	@Override
	public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
		Class<?> type = parameterContext.getParameter().getType();
		if (type == Framework.class) {
			return getOrCreateFramework(extensionContext);
		} else if (type == Log.class) {
			return getOrCreateLog(extensionContext);
		} else {
			throw new IllegalStateException("Unexpected parameter type: " + type.getName());
		}
	}

	@Override
	public void beforeEach(ExtensionContext context) {
		Framework framework = getOrCreateFramework(context);
		Configuration configuration = framework.getConfiguration();
		List<CaptureLogEntries> annotations = new ArrayList<>();

		context.getTestInstances().ifPresent(instances -> {
			for (Object object : instances.getAllInstances()) {
				CaptureLogEntries annotation = object.getClass().getAnnotation(CaptureLogEntries.class);
				if (annotation != null) {
					annotations.add(annotation);
				}
			}
		});

		context.getTestMethod().ifPresent(method -> {
			CaptureLogEntries annotation = method.getAnnotation(CaptureLogEntries.class);
			if (annotation != null) {
				annotations.add(annotation);
			}
		});

		annotations.stream().flatMap(annotation -> Arrays.stream(annotation.configuration())).forEach(entry -> {
			int index = entry.indexOf('=');
			if (index >= 0) {
				String key = entry.substring(0, index);
				String value = entry.substring(index + 1);
				configuration.set(key, value);
			}
		});

		framework.startUp();
	}

	@Override
	public void afterEach(ExtensionContext context) {
		try {
			getOrCreateFramework(context).shutDown();
			Assertions
{'fraction_non_alphanumeric': 0.10558624923265807, 'fraction_numerical': 0.003376304481276857, 'mean_word_length': 4.787744227353463, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4673064', 'n_tokens_mistral': 1876, 'n_tokens_neox': 1720, 'n_words': 478}