001package ca.uhn.fhir.test.utilities.server;
002
003/*-
004 * #%L
005 * HAPI FHIR Test Utilities
006 * %%
007 * Copyright (C) 2014 - 2023 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.rest.server.RestfulServer;
024import org.junit.jupiter.api.extension.BeforeEachCallback;
025import org.junit.jupiter.api.extension.ExtensionContext;
026import org.springframework.util.Assert;
027
028import java.util.ArrayList;
029import java.util.List;
030import java.util.function.Consumer;
031import java.util.function.Supplier;
032
033/**
034 * This JUnit extension can be used to perform configuration of the
035 * {@link RestfulServerExtension}, where non-static fields are available. This
036 * is primarily useful for accessing Spring Test beans.
037 */
038public class RestfulServerConfigurerExtension implements BeforeEachCallback {
039
040        private Supplier<RestfulServerExtension> myRestfulServerExtensionSupplier;
041        private RestfulServerExtension myRestfulServerExtension;
042        private final List<Consumer<RestfulServer>> myBeforeAllConsumers = new ArrayList<>();
043        private final List<Consumer<RestfulServer>> myBeforeEachConsumers = new ArrayList<>();
044
045        /**
046         * Constructor
047         */
048        public RestfulServerConfigurerExtension(RestfulServerExtension theRestfulServerExtension) {
049                Assert.notNull(theRestfulServerExtension, "theRestfulServerExtension must not be null");
050                myRestfulServerExtension = theRestfulServerExtension;
051        }
052
053        /**
054         * Constructor - Use this if the server is dependency injected
055         */
056        public RestfulServerConfigurerExtension(Supplier<RestfulServerExtension> theRestfulServerExtension) {
057                Assert.notNull(theRestfulServerExtension, "theRestfulServerExtension must not be null");
058                myRestfulServerExtensionSupplier = theRestfulServerExtension;
059        }
060
061        /**
062         * This callback will be invoked once after the server has started
063         */
064        public RestfulServerConfigurerExtension withServerBeforeAll(Consumer<RestfulServer> theServer) {
065                Assert.notNull(theServer, "theServer must not be null");
066                myBeforeAllConsumers.add(theServer);
067                return this;
068        }
069
070        /**
071         * This callback will be invoked before each test but after the server has started
072         */
073        public RestfulServerConfigurerExtension withServerBeforeEach(Consumer<RestfulServer> theServer) {
074                Assert.notNull(theServer, "theServer must not be null");
075                myBeforeEachConsumers.add(theServer);
076                return this;
077        }
078
079        @Override
080        public void beforeEach(ExtensionContext theExtensionContext) throws Exception {
081                ensureServerIsPresentAndRunning();
082
083                String key = getClass().getName();
084
085                // One time
086                if (!myRestfulServerExtension.getRunningServerUserData().containsKey(key)) {
087                        myRestfulServerExtension.getRunningServerUserData().put(key, key);
088
089                        for (Consumer<RestfulServer> next : myBeforeAllConsumers) {
090                                myRestfulServerExtension.withServer(next::accept);
091                        }
092                }
093
094                // Every time
095                for (Consumer<RestfulServer> next : myBeforeEachConsumers) {
096                        myRestfulServerExtension.withServer(next::accept);
097                }
098        }
099
100        private void ensureServerIsPresentAndRunning() {
101                if (myRestfulServerExtension == null) {
102                        myRestfulServerExtension = myRestfulServerExtensionSupplier.get();
103                }
104                Assert.isTrue(myRestfulServerExtension.isRunning(), "Server is not running");
105        }
106}