blob: ef561a8dc85aef8fdbe46bf98a77b33c10b55ee9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.netbeans.modules.junit;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.openide.ErrorManager;
import org.openide.util.NbBundle;
/**
* Helper class representing reasons for skipping a class in the test
* generation process. The class enumerates known reasons, why a class may
* not be considered testable, allows to combine the reasons and provide
* human-readable representation of them.
*/
final class TestabilityResult {
// bitfield of reasons for skipping a class
private long reason;
// reason constants
public static final TestabilityResult OK = new TestabilityResult(0);
public static final TestabilityResult PACKAGE_PRIVATE_CLASS = new TestabilityResult(1);
public static final TestabilityResult NO_TESTEABLE_METHODS = new TestabilityResult(2);
public static final TestabilityResult TEST_CLASS = new TestabilityResult(4);
public static final TestabilityResult ABSTRACT_CLASS = new TestabilityResult(8);
public static final TestabilityResult NONSTATIC_INNER_CLASS = new TestabilityResult(16);
public static final TestabilityResult EXCEPTION_CLASS = new TestabilityResult(32);
public static final TestabilityResult PRIVATE_CLASS = new TestabilityResult(64);
// bundle keys for reason descriptions
private static final String [] reasonBundleKeys = {
"TestabilityResult_PkgPrivate",
"TestabilityResult_NoTestableMethods",
"TestabilityResult_TestClass",
"TestabilityResult_AbstractClass",
"TestabilityResult_NonstaticInnerClass",
"TestabilityResult_ExceptionClass",
"TestabilityResult_Private"};
private TestabilityResult(long reason) {
this.reason = reason;
}
/**
* Combine two result reasons into a new one.
*
* The combination is the union
* of the failure reasons represented by the two results. Thus,
* if both are success (no failure), the combination is a success. If
* some of them is failed, the result is failed.
*
* @param lhs the first TestabilityResult
* @param rhs the second TestabilityResult
* @return a new TestabilityResult representing the combination of the two
* results
**/
public static TestabilityResult combine(TestabilityResult lhs, TestabilityResult rhs) {
return new TestabilityResult(lhs.reason | rhs.reason);
}
/**
* Removes reasons from result according to the specified {@code mask}
* (bit mask). If a bit in the {@code mask} is 1 then the corresponding
* bit in the returned {@code TestabilityResult} will be set to 0.
*
* @param tr the {@code TestabilityResult} which reasons should be filtered.
* @param mask the filter bit mask.
* @return New {@code TestabilityResult} where some bits are set according to
* the {@code mask}.
*/
public static TestabilityResult filter(TestabilityResult tr, long mask) {
return new TestabilityResult(tr.reason & ~mask);
}
/**
* Returns true if the result is for a testable class.
* @return true or false
*/
public boolean isTestable() {
return reason == 0;
}
/**
* Returns true if the result is for a non-testable class.
* @return true if the result is for a non-testable class.
*/
public boolean isFailed() {
return reason != 0;
}
public long getReasonValue(){
return reason;
}
/**
* Returns a human-readable representation of the reason. If the reason
* is a combination of multiple reasons, they are separated with ",".
* @return String
*/
public String getReason() {
return getReason(", ", ", "); //NOI18N
}
/**
* Returns {@link #getReason()}.
* @return String
*/
@Override
public String toString() {
return getReason(", ", ", "); //NOI18N
}
/**
* Returns a human-readable representation of the reason. If the reason
* is a combination of multiple reasons, they are separated with
* {@code separ} except for the last reason, which is separated
* with {@code terminalSepar}
* <p>
* For example: getReason(", ", " or ") might return
* "abstract, package private or without testable methods".
*
* @return String
*/
public String getReason(String separ, String terminalSepar) {
try {
ResourceBundle bundle = NbBundle.getBundle(TestCreator.class);
if (reason == 0) {
return bundle.getString("TestabilityResult_OK"); //NOI18N
} else {
String str = ""; //NOI18N
boolean lastPrep = true;
for (long i = 0, r = reason; r > 0; r >>= 1, i++) {
if ((r & 1) != 0) {
if (str.length() > 0) {
if (lastPrep) {
str = terminalSepar + str;
lastPrep = false;
} else {
str = separ + str;
}
}
str = bundle.getString(reasonBundleKeys[(int)i]) + str;
}
}
return str;
}
} catch (MissingResourceException ex) {
ErrorManager.getDefault().notify(ex);
return "";
}
}
/**
* Class for holding name of a skipped java class
* together with the reason why it was skipped.
*/
static final class SkippedClass {
final String clsName;
final TestabilityResult reason;
SkippedClass(String clsName,
TestabilityResult reason) {
this.clsName = clsName;
this.reason = reason;
}
}
}