001/*
002 * Copyright (C) 2022 - 2024, the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *    http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package io.github.ascopes.jct.assertions;
017
018import static org.assertj.core.api.Assertions.assertThat;
019
020import org.apiguardian.api.API;
021import org.apiguardian.api.API.Status;
022import org.assertj.core.api.AbstractAssert;
023import org.assertj.core.api.AbstractBooleanAssert;
024import org.assertj.core.api.AbstractIntegerAssert;
025import org.assertj.core.api.AbstractStringAssert;
026import org.jspecify.annotations.Nullable;
027
028/**
029 * Assertions to perform on a {@link StackTraceElement stack trace frame}.
030 *
031 * <p>This type is a placeholder and will be replaced when AssertJ releases changes to
032 * support assertions on stack traces.
033 *
034 * @author Ashley Scopes
035 * @since 0.0.1
036 */
037@API(status = Status.EXPERIMENTAL)
038public final class StackTraceElementAssert
039    extends AbstractAssert<StackTraceElementAssert, StackTraceElement> {
040
041  /**
042   * Initialize this assertion object.
043   *
044   * @param actual the stacktrace element to assert upon.
045   */
046  @SuppressWarnings("DataFlowIssue")
047  public StackTraceElementAssert(@Nullable StackTraceElement actual) {
048    super(actual, StackTraceElementAssert.class);
049  }
050
051  /**
052   * Get assertions for the filename of the stack trace frame.
053   *
054   * @return the assertions for the file name.
055   * @throws AssertionError if the stack trace element is null.
056   */
057  public AbstractStringAssert<?> fileName() {
058    isNotNull();
059
060    return assertThat(actual.getFileName())
061        .as("file name");
062  }
063
064  /**
065   * Get assertions for the line number of the stack trace frame.
066   *
067   * <p>The line number may be non-positive if the method is a
068   * {@link #nativeMethod() native method}.
069   *
070   * @return the assertions for the line number.
071   * @throws AssertionError if the stack trace element is null.
072   */
073  public AbstractIntegerAssert<?> lineNumber() {
074    isNotNull();
075
076    return assertThat(actual.getLineNumber())
077        .as("line number");
078  }
079
080  /**
081   * Get assertions for the module name of the stack trace frame.
082   *
083   * <p>The value may be null if not present.
084   *
085   * @return the assertions for the module name.
086   * @throws AssertionError if the stack trace element is null.
087   */
088  public AbstractStringAssert<?> moduleName() {
089    isNotNull();
090
091    return assertThat(actual.getModuleName())
092        .as("module name");
093  }
094
095  /**
096   * Get assertions for the module version of the stack trace frame.
097   *
098   * <p>The value may be null if not present.
099   *
100   * @return the assertions for the module version.
101   * @throws AssertionError if the stack trace element is null.
102   */
103  public AbstractStringAssert<?> moduleVersion() {
104    isNotNull();
105
106    return assertThat(actual.getModuleVersion())
107        .as("module version");
108  }
109
110  /**
111   * Get assertions for the name of the classloader of the class in the stack trace frame.
112   *
113   * @return the assertions for the classloader name.
114   * @throws AssertionError if the stack trace element is null.
115   */
116  public AbstractStringAssert<?> classLoaderName() {
117    isNotNull();
118
119    return assertThat(actual.getClassLoaderName())
120        .as("class loader name");
121  }
122
123  /**
124   * Get assertions for the class name of the stack trace frame.
125   *
126   * @return the assertions for the class name.
127   * @throws AssertionError if the stack trace element is null.
128   */
129  public AbstractStringAssert<?> className() {
130    isNotNull();
131
132    return assertThat(actual.getClassName())
133        .as("class name");
134  }
135
136  /**
137   * Get assertions for the method name of the stack trace frame.
138   *
139   * @return the assertions for the method name.
140   * @throws AssertionError if the stack trace element is null.
141   */
142  public AbstractStringAssert<?> methodName() {
143    isNotNull();
144
145    return assertThat(actual.getMethodName())
146        .as("method name");
147  }
148
149  /**
150   * Get assertions for whether the frame is for a native (JNI) method or not.
151   *
152   * @return the assertions for the method nativity.
153   * @throws AssertionError if the stack trace element is null.
154   */
155  public AbstractBooleanAssert<?> nativeMethod() {
156    isNotNull();
157
158    return assertThat(actual.isNativeMethod())
159        .as("native method");
160  }
161}