001/*
002 * Copyright (C) 2022 - 2023, 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  public StackTraceElementAssert(@Nullable StackTraceElement actual) {
047    super(actual, StackTraceElementAssert.class);
048  }
049
050  /**
051   * Get assertions for the filename of the stack trace frame.
052   *
053   * @return the assertions for the file name.
054   * @throws AssertionError if the stack trace element is null.
055   */
056  public AbstractStringAssert<?> fileName() {
057    isNotNull();
058
059    return assertThat(actual.getFileName())
060        .as("file name");
061  }
062
063  /**
064   * Get assertions for the line number of the stack trace frame.
065   *
066   * <p>The line number may be non-positive if the method is a
067   * {@link #nativeMethod() native method}.
068   *
069   * @return the assertions for the line number.
070   * @throws AssertionError if the stack trace element is null.
071   */
072  public AbstractIntegerAssert<?> lineNumber() {
073    isNotNull();
074
075    return assertThat(actual.getLineNumber())
076        .as("line number");
077  }
078
079  /**
080   * Get assertions for the module name of the stack trace frame.
081   *
082   * <p>The value may be null if not present.
083   *
084   * @return the assertions for the module name.
085   * @throws AssertionError if the stack trace element is null.
086   */
087  public AbstractStringAssert<?> moduleName() {
088    isNotNull();
089
090    return assertThat(actual.getModuleName())
091        .as("module name");
092  }
093
094  /**
095   * Get assertions for the module version of the stack trace frame.
096   *
097   * <p>The value may be null if not present.
098   *
099   * @return the assertions for the module version.
100   * @throws AssertionError if the stack trace element is null.
101   */
102  public AbstractStringAssert<?> moduleVersion() {
103    isNotNull();
104
105    return assertThat(actual.getModuleVersion())
106        .as("module version");
107  }
108
109  /**
110   * Get assertions for the name of the classloader of the class in the stack trace frame.
111   *
112   * @return the assertions for the classloader name.
113   * @throws AssertionError if the stack trace element is null.
114   */
115  public AbstractStringAssert<?> classLoaderName() {
116    isNotNull();
117
118    return assertThat(actual.getClassLoaderName())
119        .as("class loader name");
120  }
121
122  /**
123   * Get assertions for the class name of the stack trace frame.
124   *
125   * @return the assertions for the class name.
126   * @throws AssertionError if the stack trace element is null.
127   */
128  public AbstractStringAssert<?> className() {
129    isNotNull();
130
131    return assertThat(actual.getClassName())
132        .as("class name");
133  }
134
135  /**
136   * Get assertions for the method name of the stack trace frame.
137   *
138   * @return the assertions for the method name.
139   * @throws AssertionError if the stack trace element is null.
140   */
141  public AbstractStringAssert<?> methodName() {
142    isNotNull();
143
144    return assertThat(actual.getMethodName())
145        .as("method name");
146  }
147
148  /**
149   * Get assertions for whether the frame is for a native (JNI) method or not.
150   *
151   * @return the assertions for the method nativity.
152   * @throws AssertionError if the stack trace element is null.
153   */
154  public AbstractBooleanAssert<?> nativeMethod() {
155    isNotNull();
156
157    return assertThat(actual.isNativeMethod())
158        .as("native method");
159  }
160}