Home / Class/ BufferingApplicationStartupTests Class — spring-boot Architecture

BufferingApplicationStartupTests Class — spring-boot Architecture

Architecture documentation for the BufferingApplicationStartupTests class in BufferingApplicationStartupTests.java from the spring-boot codebase.

Entity Profile

Source Code

core/spring-boot/src/test/java/org/springframework/boot/context/metrics/buffering/BufferingApplicationStartupTests.java lines 39–160

class BufferingApplicationStartupTests {

	@Test
	void shouldNotRecordEventsWhenOverCapacity() {
		BufferingApplicationStartup applicationStartup = new BufferingApplicationStartup(2);
		applicationStartup.start("first").end();
		applicationStartup.start("second").end();
		applicationStartup.start("third").end();
		assertThat(applicationStartup.getBufferedTimeline().getEvents()).hasSize(2);
	}

	@Test
	void shouldNotRecordEventsWhenFiltered() {
		BufferingApplicationStartup applicationStartup = new BufferingApplicationStartup(5);
		applicationStartup.addFilter((step) -> step.getName().startsWith("spring"));
		applicationStartup.start("spring.first").end();
		StartupStep filtered = applicationStartup.start("filtered.second");
		applicationStartup.start("spring.third").end();
		filtered.end();
		List<TimelineEvent> events = applicationStartup.getBufferedTimeline().getEvents();
		assertThat(events).hasSize(2);
		StartupTimeline.TimelineEvent firstEvent = events.get(0);
		assertThat(firstEvent.getStartupStep().getId()).isZero();
		assertThat(firstEvent.getStartupStep().getParentId()).isNull();
		StartupTimeline.TimelineEvent secondEvent = events.get(1);
		assertThat(secondEvent.getStartupStep().getId()).isEqualTo(2);
		assertThat(secondEvent.getStartupStep().getParentId()).isOne();
	}

	@Test
	void bufferShouldNotBeEmptyWhenGettingSnapshot() {
		BufferingApplicationStartup applicationStartup = new BufferingApplicationStartup(2);
		applicationStartup.start("first").end();
		applicationStartup.start("second").end();
		assertThat(applicationStartup.getBufferedTimeline().getEvents()).hasSize(2);
		assertThat(applicationStartup.getBufferedTimeline().getEvents()).hasSize(2);
	}

	@Test
	void bufferShouldBeEmptyWhenDraining() {
		BufferingApplicationStartup applicationStartup = new BufferingApplicationStartup(2);
		applicationStartup.start("first").end();
		applicationStartup.start("second").end();
		assertThat(applicationStartup.drainBufferedTimeline().getEvents()).hasSize(2);
		assertThat(applicationStartup.getBufferedTimeline().getEvents()).isEmpty();
	}

	@Test
	void startRecordingShouldFailIfEventsWereRecorded() {
		BufferingApplicationStartup applicationStartup = new BufferingApplicationStartup(2);
		applicationStartup.start("first").end();
		assertThatIllegalStateException().isThrownBy(applicationStartup::startRecording)
			.withMessage("Cannot restart recording once steps have been buffered");
	}

	@Test
	@SuppressWarnings("resource")
	void taggingShouldFailWhenEventAlreadyRecorded() {
		BufferingApplicationStartup applicationStartup = new BufferingApplicationStartup(2);
		StartupStep step = applicationStartup.start("first");
		step.end();
		assertThatIllegalStateException().isThrownBy(() -> step.tag("name", "value"))
			.withMessage("StartupStep has already ended.");
	}

	@Test
	void taggingShouldFailWhenRemovingEntry() {
		BufferingApplicationStartup applicationStartup = new BufferingApplicationStartup(2);
		StartupStep step = applicationStartup.start("first");
		step.tag("name", "value");
		assertThatExceptionOfType(UnsupportedOperationException.class)
			.isThrownBy(() -> step.getTags().iterator().remove());
	}

	@Test // gh-25792
	void outOfOrderWithMultipleEndCallsShouldNotFail() {
		BufferingApplicationStartup applicationStartup = new BufferingApplicationStartup(200);
		StartupStep one = applicationStartup.start("one");
		StartupStep two = applicationStartup.start("two");
		StartupStep three = applicationStartup.start("three");
		two.end();
		two.end();
		two.end();
		StartupStep four = applicationStartup.start("four");
		four.end();
		three.end();
		one.end();
	}

	@Test // gh-25792
	void multiThreadedAccessShouldWork() throws InterruptedException {
		BufferingApplicationStartup applicationStartup = new BufferingApplicationStartup(5000);
		Queue<Exception> errors = new ConcurrentLinkedQueue<>();
		List<Thread> threads = new ArrayList<>();
		for (int thread = 0; thread < 20; thread++) {
			String prefix = "thread-" + thread + "-";
			threads.add(new Thread(() -> {
				try {
					for (int i = 0; i < 100; i++) {
						StartupStep step = applicationStartup.start(prefix + i);
						try {
							Thread.sleep(1);
						}
						catch (InterruptedException ex) {
							// Ignore
						}
						step.end();
					}
				}
				catch (Exception ex) {
					errors.add(ex);
				}
			}));
		}
		threads.forEach(Thread::start);
		for (Thread thread : threads) {
			thread.join();
		}
		assertThat(errors).isEmpty();
	}

}

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free