Merge
This commit is contained in:
commit
586b13cdb6
@ -47,7 +47,7 @@ ifeq ($(HAS_SPEC),)
|
||||
|
||||
# Make control variables, handled by Init.gmk
|
||||
INIT_CONTROL_VARIABLES += LOG CONF CONF_NAME SPEC JOBS TEST_JOBS CONF_CHECK \
|
||||
COMPARE_BUILD JTREG GTEST
|
||||
COMPARE_BUILD JTREG GTEST TEST_OPTS TEST_VM_OPTS
|
||||
|
||||
# All known make control variables
|
||||
MAKE_CONTROL_VARIABLES := $(INIT_CONTROL_VARIABLES) TEST JDK_FILTER
|
||||
|
@ -32,11 +32,42 @@ include FindTests.gmk
|
||||
# We will always run multiple tests serially
|
||||
.NOTPARALLEL:
|
||||
|
||||
################################################################################
|
||||
# Parse global control variables
|
||||
################################################################################
|
||||
|
||||
ifneq ($(TEST_VM_OPTS), )
|
||||
ifneq ($(TEST_OPTS), )
|
||||
TEST_OPTS := $(TEST_OPTS);VM_OPTIONS=$(TEST_VM_OPTS)
|
||||
else
|
||||
TEST_OPTS := VM_OPTIONS=$(TEST_VM_OPTS)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(eval $(call ParseKeywordVariable, TEST_OPTS, \
|
||||
KEYWORDS := JOBS TIMEOUT, \
|
||||
STRING_KEYWORDS := VM_OPTIONS, \
|
||||
))
|
||||
|
||||
# Helper function to propagate TEST_OPTS values.
|
||||
#
|
||||
# Note: No spaces are allowed around the arguments.
|
||||
# Arg $1 The variable in TEST_OPTS to propagate
|
||||
# Arg $2 The control variable to propagate it to
|
||||
define SetTestOpt
|
||||
ifneq ($$(TEST_OPTS_$1), )
|
||||
$2_$1 := $$(TEST_OPTS_$1)
|
||||
endif
|
||||
endef
|
||||
|
||||
################################################################################
|
||||
# Hook to include the corresponding custom file, if present.
|
||||
$(eval $(call IncludeCustomExtension, RunTests.gmk))
|
||||
################################################################################
|
||||
|
||||
TEST_RESULTS_DIR := $(OUTPUTDIR)/test-results
|
||||
TEST_SUPPORT_DIR := $(OUTPUTDIR)/test-support
|
||||
TEST_SUMMARY := $(TEST_RESULTS_DIR)/test-summary.txt
|
||||
|
||||
ifeq ($(CUSTOM_ROOT), )
|
||||
JTREG_TOPDIR := $(TOPDIR)
|
||||
@ -48,6 +79,17 @@ endif
|
||||
# Parse control variables
|
||||
################################################################################
|
||||
|
||||
ifneq ($(TEST_OPTS), )
|
||||
# Inform the user
|
||||
$(info Running tests using TEST_OPTS control variable '$(TEST_OPTS)')
|
||||
|
||||
$(eval $(call SetTestOpt,VM_OPTIONS,JTREG))
|
||||
$(eval $(call SetTestOpt,VM_OPTIONS,GTEST))
|
||||
|
||||
$(eval $(call SetTestOpt,JOBS,JTREG))
|
||||
$(eval $(call SetTestOpt,TIMEOUT,JTREG))
|
||||
endif
|
||||
|
||||
$(eval $(call ParseKeywordVariable, JTREG, \
|
||||
KEYWORDS := JOBS TIMEOUT TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM, \
|
||||
STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS, \
|
||||
@ -60,7 +102,7 @@ endif
|
||||
|
||||
$(eval $(call ParseKeywordVariable, GTEST, \
|
||||
KEYWORDS := REPEAT, \
|
||||
STRING_KEYWORDS := OPTIONS, \
|
||||
STRING_KEYWORDS := OPTIONS VM_OPTIONS, \
|
||||
))
|
||||
|
||||
ifneq ($(GTEST), )
|
||||
@ -280,7 +322,7 @@ define SetupRunGtestTestBody
|
||||
$$(FIXPATH) $$(TEST_IMAGE_DIR)/hotspot/gtest/server/gtestLauncher \
|
||||
-jdk $(JDK_IMAGE_DIR) $$($1_GTEST_FILTER) \
|
||||
--gtest_output=xml:$$($1_TEST_RESULTS_DIR)/gtest.xml \
|
||||
$$($1_GTEST_REPEAT) $$(GTEST_OPTIONS) \
|
||||
$$($1_GTEST_REPEAT) $$(GTEST_OPTIONS) $$(GTEST_VM_OPTIONS) \
|
||||
> >($(TEE) $$($1_TEST_RESULTS_DIR)/gtest.txt) || true )
|
||||
|
||||
$1_RESULT_FILE := $$($1_TEST_RESULTS_DIR)/gtest.txt
|
||||
@ -289,15 +331,24 @@ define SetupRunGtestTestBody
|
||||
$$(call LogWarn, Finished running test '$$($1_TEST)')
|
||||
$$(call LogWarn, Test report is stored in $$(strip \
|
||||
$$(subst $$(TOPDIR)/, , $$($1_TEST_RESULTS_DIR))))
|
||||
$$(eval $1_TOTAL := $$(shell $$(AWK) '/==========.* tests? from .* \
|
||||
test cases? ran/ { print $$$$2 }' $$($1_RESULT_FILE)))
|
||||
$$(eval $1_PASSED := $$(shell $$(AWK) '/\[ PASSED \] .* tests?./ \
|
||||
{ print $$$$4 }' $$($1_RESULT_FILE)))
|
||||
$$(eval $1_FAILED := $$(shell $$(AWK) '/\[ FAILED \] .* tests?, \
|
||||
listed below/ { print $$$$4 }' $$($1_RESULT_FILE)))
|
||||
$$(if $$($1_FAILED), , $$(eval $1_FAILED := 0))
|
||||
$$(eval $1_ERROR := $$(shell \
|
||||
$$(EXPR) $$($1_TOTAL) - $$($1_PASSED) - $$($1_FAILED)))
|
||||
$$(if $$(wildcard $$($1_RESULT_FILE)), \
|
||||
$$(eval $1_TOTAL := $$(shell $$(AWK) '/==========.* tests? from .* \
|
||||
test cases? ran/ { print $$$$2 }' $$($1_RESULT_FILE))) \
|
||||
$$(if $$($1_TOTAL), , $$(eval $1_TOTAL := 0)) \
|
||||
$$(eval $1_PASSED := $$(shell $$(AWK) '/\[ PASSED \] .* tests?./ \
|
||||
{ print $$$$4 }' $$($1_RESULT_FILE))) \
|
||||
$$(if $$($1_PASSED), , $$(eval $1_PASSED := 0)) \
|
||||
$$(eval $1_FAILED := $$(shell $$(AWK) '/\[ FAILED \] .* tests?, \
|
||||
listed below/ { print $$$$4 }' $$($1_RESULT_FILE))) \
|
||||
$$(if $$($1_FAILED), , $$(eval $1_FAILED := 0)) \
|
||||
$$(eval $1_ERROR := $$(shell \
|
||||
$$(EXPR) $$($1_TOTAL) - $$($1_PASSED) - $$($1_FAILED))) \
|
||||
, \
|
||||
$$(eval $1_PASSED := 0) \
|
||||
$$(eval $1_FAILED := 0) \
|
||||
$$(eval $1_ERROR := 1) \
|
||||
$$(eval $1_TOTAL := 1) \
|
||||
)
|
||||
|
||||
$1: run-test-$1 parse-test-$1
|
||||
|
||||
@ -521,42 +572,46 @@ endif
|
||||
TEST_FAILURE := false
|
||||
|
||||
run-test: $(TARGETS)
|
||||
# Print a table of the result of all tests run and their result
|
||||
$(ECHO)
|
||||
$(ECHO) ==============================
|
||||
$(ECHO) Test summary
|
||||
$(ECHO) ==============================
|
||||
$(PRINTF) "%2s %-49s %5s %5s %5s %5s %2s\n" " " TEST \
|
||||
TOTAL PASS FAIL ERROR " "
|
||||
# Create and print a table of the result of all tests run
|
||||
$(RM) $(TEST_SUMMARY).old 2> /dev/null
|
||||
$(MV) $(TEST_SUMMARY) $(TEST_SUMMARY).old 2> /dev/null || true
|
||||
$(ECHO) >> $(TEST_SUMMARY) ==============================
|
||||
$(ECHO) >> $(TEST_SUMMARY) Test summary
|
||||
$(ECHO) >> $(TEST_SUMMARY) ==============================
|
||||
$(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s %5s %5s %5s %5s %2s\n" " " \
|
||||
TEST TOTAL PASS FAIL ERROR " "
|
||||
$(foreach test, $(TESTS_TO_RUN), \
|
||||
$(eval TEST_ID := $(shell $(ECHO) $(strip $(test)) | \
|
||||
$(TR) -cs '[a-z][A-Z][0-9]\n' '_')) \
|
||||
$(eval NAME_PATTERN := $(shell $(ECHO) $(test) | $(TR) -c \\n _)) \
|
||||
$(if $(filter __________________________________________________%, $(NAME_PATTERN)), \
|
||||
$(eval TEST_NAME := ) \
|
||||
$(PRINTF) "%2s %-49s\n" " " "$(test)" $(NEWLINE) \
|
||||
$(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s\n" " " "$(test)" $(NEWLINE) \
|
||||
, \
|
||||
$(eval TEST_NAME := $(test)) \
|
||||
) \
|
||||
$(if $(filter $($(TEST_ID)_PASSED), $($(TEST_ID)_TOTAL)), \
|
||||
$(PRINTF) "%2s %-49s %5d %5d %5d %5d %2s\n" " " "$(TEST_NAME)" \
|
||||
$($(TEST_ID)_TOTAL) $($(TEST_ID)_PASSED) $($(TEST_ID)_FAILED) \
|
||||
$($(TEST_ID)_ERROR) " " $(NEWLINE) \
|
||||
$(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s %5d %5d %5d %5d %2s\n" \
|
||||
" " "$(TEST_NAME)" $($(TEST_ID)_TOTAL) $($(TEST_ID)_PASSED) \
|
||||
$($(TEST_ID)_FAILED) $($(TEST_ID)_ERROR) " " $(NEWLINE) \
|
||||
, \
|
||||
$(PRINTF) "%2s %-49s %5d %5d %5d %5d %2s\n" ">>" "$(TEST_NAME)" \
|
||||
$($(TEST_ID)_TOTAL) $($(TEST_ID)_PASSED) $($(TEST_ID)_FAILED) \
|
||||
$($(TEST_ID)_ERROR) "<<" $(NEWLINE) \
|
||||
$(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s %5d %5d %5d %5d %2s\n" \
|
||||
">>" "$(TEST_NAME)" $($(TEST_ID)_TOTAL) $($(TEST_ID)_PASSED) \
|
||||
$($(TEST_ID)_FAILED) $($(TEST_ID)_ERROR) "<<" $(NEWLINE) \
|
||||
$(eval TEST_FAILURE := true) \
|
||||
) \
|
||||
)
|
||||
$(ECHO) ==============================
|
||||
$(ECHO) >> $(TEST_SUMMARY) ==============================
|
||||
$(if $(filter true, $(TEST_FAILURE)), \
|
||||
$(ECHO) TEST FAILURE $(NEWLINE) \
|
||||
$(ECHO) >> $(TEST_SUMMARY) TEST FAILURE $(NEWLINE) \
|
||||
$(MKDIR) -p $(MAKESUPPORT_OUTPUTDIR) $(NEWLINE) \
|
||||
$(TOUCH) $(MAKESUPPORT_OUTPUTDIR)/exit-with-error \
|
||||
, \
|
||||
$(ECHO) TEST SUCCESS \
|
||||
$(ECHO) >> $(TEST_SUMMARY) TEST SUCCESS \
|
||||
)
|
||||
$(ECHO)
|
||||
$(CAT) $(TEST_SUMMARY)
|
||||
$(ECHO)
|
||||
|
||||
################################################################################
|
||||
|
||||
|
@ -115,11 +115,11 @@
|
||||
</target>
|
||||
|
||||
|
||||
<!-- check minimum ant version required to be 1.8.4 -->
|
||||
<!-- check minimum ant version required to be 1.9.5 -->
|
||||
<target name="check-ant-version">
|
||||
<property name="ant.version.required" value="1.8.4"/>
|
||||
<property name="ant.version.required" value="1.9.5"/>
|
||||
<antversion property="ant.current.version" />
|
||||
<fail message="The current ant version, ${ant.current.version}, is too old. Please use 1.8.4 or above.">
|
||||
<fail message="The current ant version, ${ant.current.version}, is too old. Please use 1.9.5 or above.">
|
||||
<condition>
|
||||
<not>
|
||||
<antversion atleast="${ant.version.required}"/>
|
||||
|
@ -1813,7 +1813,7 @@ public abstract class ClassLoader {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the platform class loader for delegation. All
|
||||
* Returns the platform class loader. All
|
||||
* <a href="#builtinLoaders">platform classes</a> are visible to
|
||||
* the platform class loader.
|
||||
*
|
||||
@ -1843,7 +1843,7 @@ public abstract class ClassLoader {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the system class loader for delegation. This is the default
|
||||
* Returns the system class loader. This is the default
|
||||
* delegation parent for new {@code ClassLoader} instances, and is
|
||||
* typically the class loader used to start the application.
|
||||
*
|
||||
@ -1884,7 +1884,7 @@ public abstract class ClassLoader {
|
||||
* the application module path then the class path defaults to
|
||||
* the current working directory.
|
||||
*
|
||||
* @return The system {@code ClassLoader} for delegation
|
||||
* @return The system {@code ClassLoader}
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If a security manager is present, and the caller's class loader
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,9 +32,12 @@ import java.security.*;
|
||||
*
|
||||
* <p>The {@code initialize} methods may each be called any number
|
||||
* of times. If no {@code initialize} method is called on a
|
||||
* DSAKeyPairGenerator, the default is to generate 1024-bit keys, using
|
||||
* precomputed p, q and g parameters and an instance of SecureRandom as
|
||||
* the random bit source.
|
||||
* DSAKeyPairGenerator, each provider that implements this interface
|
||||
* should supply (and document) a default initialization. Note that
|
||||
* defaults may vary across different providers. Additionally, the default
|
||||
* value for a provider may change in a future version. Therefore, it is
|
||||
* recommended to explicitly initialize the DSAKeyPairGenerator instead
|
||||
* of relying on provider-specific defaults.
|
||||
*
|
||||
* <p>Users wishing to indicate DSA-specific parameters, and to generate a key
|
||||
* pair suitable for use with the DSA algorithm typically
|
||||
@ -45,12 +48,13 @@ import java.security.*;
|
||||
* KeyPairGenerator {@code getInstance} method with "DSA"
|
||||
* as its argument.
|
||||
*
|
||||
* <li>Initialize the generator by casting the result to a DSAKeyPairGenerator
|
||||
* and calling one of the
|
||||
* {@code initialize} methods from this DSAKeyPairGenerator interface.
|
||||
* <li>Check if the returned key pair generator is an instance of
|
||||
* DSAKeyPairGenerator before casting the result to a DSAKeyPairGenerator
|
||||
* and calling one of the {@code initialize} methods from this
|
||||
* DSAKeyPairGenerator interface.
|
||||
*
|
||||
* <li>Generate a key pair by calling the {@code generateKeyPair}
|
||||
* method from the KeyPairGenerator class.
|
||||
* method of the KeyPairGenerator class.
|
||||
*
|
||||
* </ol>
|
||||
*
|
||||
@ -63,7 +67,7 @@ import java.security.*;
|
||||
* parameters.
|
||||
*
|
||||
* <p>Note: Some earlier implementations of this interface may not support
|
||||
* larger sizes of DSA parameters such as 2048 and 3072-bit.
|
||||
* larger values of DSA parameters such as 3072-bit.
|
||||
*
|
||||
* @since 1.1
|
||||
* @see java.security.KeyPairGenerator
|
||||
@ -97,8 +101,7 @@ public interface DSAKeyPairGenerator {
|
||||
* p, q and g parameters. If it is false, the method uses precomputed
|
||||
* parameters for the modulus length requested. If there are no
|
||||
* precomputed parameters for that modulus length, an exception will be
|
||||
* thrown. It is guaranteed that there will always be
|
||||
* default parameters for modulus lengths of 512 and 1024 bits.
|
||||
* thrown.
|
||||
*
|
||||
* @param modlen the modulus length in bits. Valid values are any
|
||||
* multiple of 64 between 512 and 1024, inclusive, 2048, and 3072.
|
||||
|
@ -257,7 +257,7 @@ public class TypeKindVisitor6<R, P> extends SimpleTypeVisitor6<R, P> {
|
||||
*
|
||||
* @implSpec This implementation dispatches to the visit method for
|
||||
* the specific {@linkplain TypeKind kind} of pseudo-type:
|
||||
* {@code VOID}, {@code PACKAGE}, or {@code NONE}.
|
||||
* {@code VOID}, {@code PACKAGE}, {@code MODULE}, or {@code NONE}.
|
||||
*
|
||||
* @param t {@inheritDoc}
|
||||
* @param p {@inheritDoc}
|
||||
@ -273,6 +273,9 @@ public class TypeKindVisitor6<R, P> extends SimpleTypeVisitor6<R, P> {
|
||||
case PACKAGE:
|
||||
return visitNoTypeAsPackage(t, p);
|
||||
|
||||
case MODULE:
|
||||
return visitNoTypeAsModule(t, p);
|
||||
|
||||
case NONE:
|
||||
return visitNoTypeAsNone(t, p);
|
||||
|
||||
@ -307,6 +310,21 @@ public class TypeKindVisitor6<R, P> extends SimpleTypeVisitor6<R, P> {
|
||||
return defaultAction(t, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a {@link TypeKind#MODULE MODULE} pseudo-type.
|
||||
*
|
||||
* @implSpec This implementation calls {@code visitUnknown}.
|
||||
*
|
||||
* @param t the type to visit
|
||||
* @param p a visitor-specified parameter
|
||||
* @return the result of {@code visitUnknown}
|
||||
*
|
||||
* @since 10
|
||||
*/
|
||||
public R visitNoTypeAsModule(NoType t, P p) {
|
||||
return visitUnknown(t, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a {@link TypeKind#NONE NONE} pseudo-type.
|
||||
*
|
||||
|
@ -93,4 +93,20 @@ public class TypeKindVisitor9<R, P> extends TypeKindVisitor8<R, P> {
|
||||
protected TypeKindVisitor9(R defaultValue) {
|
||||
super(defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec This implementation calls {@code defaultAction}.
|
||||
*
|
||||
* @param t {@inheritDoc}
|
||||
* @param p {@inheritDoc}
|
||||
* @return the result of {@code defaultAction}
|
||||
*
|
||||
* @since 10
|
||||
*/
|
||||
@Override
|
||||
public R visitNoTypeAsModule(NoType t, P p) {
|
||||
return defaultAction(t, p);
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.ListBuffer;
|
||||
import com.sun.tools.javac.util.Log;
|
||||
import com.sun.tools.javac.util.Options;
|
||||
import com.sun.tools.javac.util.Position;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
@ -305,7 +306,7 @@ public class Analyzer {
|
||||
JCMethodDecl md = (JCMethodDecl)decls(oldTree.def).head;
|
||||
List<JCVariableDecl> params = md.params;
|
||||
JCBlock body = md.body;
|
||||
JCLambda newTree = make.Lambda(params, body);
|
||||
JCLambda newTree = make.at(oldTree).Lambda(params, body);
|
||||
return List.of(newTree);
|
||||
}
|
||||
|
||||
@ -418,7 +419,7 @@ public class Analyzer {
|
||||
List<JCEnhancedForLoop> rewrite(JCEnhancedForLoop oldTree) {
|
||||
JCEnhancedForLoop newTree = copier.copy(oldTree);
|
||||
newTree.var = rewriteVarType(oldTree.var);
|
||||
newTree.body = make.Block(0, List.nil());
|
||||
newTree.body = make.at(oldTree.body).Block(0, List.nil());
|
||||
return List.of(newTree);
|
||||
}
|
||||
@Override
|
||||
@ -551,7 +552,8 @@ public class Analyzer {
|
||||
JCStatement treeToAnalyze = (JCStatement)rewriting.originalTree;
|
||||
if (rewriting.env.info.scope.owner.kind == Kind.TYP) {
|
||||
//add a block to hoist potential dangling variable declarations
|
||||
treeToAnalyze = make.Block(Flags.SYNTHETIC, List.of((JCStatement)rewriting.originalTree));
|
||||
treeToAnalyze = make.at(Position.NOPOS)
|
||||
.Block(Flags.SYNTHETIC, List.of((JCStatement)rewriting.originalTree));
|
||||
}
|
||||
|
||||
//TODO: to further refine the analysis, try all rewriting combinations
|
||||
|
@ -57,6 +57,7 @@ import com.sun.tools.javac.tree.TreeInfo;
|
||||
import com.sun.tools.javac.util.Assert;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.util.DiagnosticSource;
|
||||
import com.sun.tools.javac.util.JCDiagnostic;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.ListBuffer;
|
||||
@ -98,6 +99,7 @@ public class ArgumentAttr extends JCTree.Visitor {
|
||||
protected static final Context.Key<ArgumentAttr> methodAttrKey = new Context.Key<>();
|
||||
|
||||
private final DeferredAttr deferredAttr;
|
||||
private final JCDiagnostic.Factory diags;
|
||||
private final Attr attr;
|
||||
private final Symtab syms;
|
||||
private final Log log;
|
||||
@ -121,6 +123,7 @@ public class ArgumentAttr extends JCTree.Visitor {
|
||||
protected ArgumentAttr(Context context) {
|
||||
context.put(methodAttrKey, this);
|
||||
deferredAttr = DeferredAttr.instance(context);
|
||||
diags = JCDiagnostic.Factory.instance(context);
|
||||
attr = Attr.instance(context);
|
||||
syms = Symtab.instance(context);
|
||||
log = Log.instance(context);
|
||||
@ -482,18 +485,14 @@ public class ArgumentAttr extends JCTree.Visitor {
|
||||
List<JCReturn> returnExpressions() {
|
||||
return returnExpressions.orElseGet(() -> {
|
||||
final List<JCReturn> res;
|
||||
if (speculativeTree.getBodyKind() == BodyKind.EXPRESSION) {
|
||||
res = List.of(attr.make.Return((JCExpression)speculativeTree.body));
|
||||
} else {
|
||||
ListBuffer<JCReturn> returnExpressions = new ListBuffer<>();
|
||||
new LambdaReturnScanner() {
|
||||
@Override
|
||||
public void visitReturn(JCReturn tree) {
|
||||
returnExpressions.add(tree);
|
||||
}
|
||||
}.scan(speculativeTree.body);
|
||||
res = returnExpressions.toList();
|
||||
}
|
||||
ListBuffer<JCReturn> buf = new ListBuffer<>();
|
||||
new LambdaReturnScanner() {
|
||||
@Override
|
||||
public void visitReturn(JCReturn tree) {
|
||||
buf.add(tree);
|
||||
}
|
||||
}.scan(speculativeTree.body);
|
||||
res = buf.toList();
|
||||
returnExpressions = Optional.of(res);
|
||||
return res;
|
||||
});
|
||||
@ -519,16 +518,38 @@ public class ArgumentAttr extends JCTree.Visitor {
|
||||
private void checkLambdaCompatible(Type descriptor, ResultInfo resultInfo) {
|
||||
CheckContext checkContext = resultInfo.checkContext;
|
||||
ResultInfo bodyResultInfo = attr.lambdaBodyResult(speculativeTree, descriptor, resultInfo);
|
||||
for (JCReturn ret : returnExpressions()) {
|
||||
Type t = getReturnType(ret);
|
||||
if (speculativeTree.getBodyKind() == BodyKind.EXPRESSION || !t.hasTag(VOID)) {
|
||||
checkSpeculative(ret.expr, t, bodyResultInfo);
|
||||
}
|
||||
switch (speculativeTree.getBodyKind()) {
|
||||
case EXPRESSION:
|
||||
checkSpeculative(speculativeTree.body, speculativeTree.body.type, bodyResultInfo);
|
||||
break;
|
||||
case STATEMENT:
|
||||
for (JCReturn ret : returnExpressions()) {
|
||||
checkReturnInStatementLambda(ret, bodyResultInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
attr.checkLambdaCompatible(speculativeTree, descriptor, checkContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an inlined version of {@link Attr#visitReturn(JCReturn)}.
|
||||
*/
|
||||
void checkReturnInStatementLambda(JCReturn ret, ResultInfo resultInfo) {
|
||||
if (resultInfo.pt.hasTag(VOID) && ret.expr != null) {
|
||||
//fail - if the function type's result is void, the lambda body must be a void-compatible block.
|
||||
resultInfo.checkContext.report(speculativeTree.pos(),
|
||||
diags.fragment("unexpected.ret.val"));
|
||||
} else if (!resultInfo.pt.hasTag(VOID)) {
|
||||
if (ret.expr == null) {
|
||||
//fail - if the function type's result is non-void, the lambda body must be a value-compatible block.
|
||||
resultInfo.checkContext.report(speculativeTree.pos(),
|
||||
diags.fragment("missing.ret.val"));
|
||||
}
|
||||
checkSpeculative(ret.expr, ret.expr.type, resultInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the type associated with given return expression. */
|
||||
Type getReturnType(JCReturn ret) {
|
||||
if (ret.expr == null) {
|
||||
|
@ -3557,18 +3557,19 @@ public class Check {
|
||||
Scope staticallyImportedSoFar, Scope topLevelScope,
|
||||
Symbol sym, boolean staticImport) {
|
||||
Filter<Symbol> duplicates = candidate -> candidate != sym && !candidate.type.isErroneous();
|
||||
Symbol clashing = ordinallyImportedSoFar.findFirst(sym.name, duplicates);
|
||||
if (clashing == null && !staticImport) {
|
||||
clashing = staticallyImportedSoFar.findFirst(sym.name, duplicates);
|
||||
Symbol ordinaryClashing = ordinallyImportedSoFar.findFirst(sym.name, duplicates);
|
||||
Symbol staticClashing = null;
|
||||
if (ordinaryClashing == null && !staticImport) {
|
||||
staticClashing = staticallyImportedSoFar.findFirst(sym.name, duplicates);
|
||||
}
|
||||
if (clashing != null) {
|
||||
if (staticImport)
|
||||
log.error(pos, Errors.AlreadyDefinedStaticSingleImport(clashing));
|
||||
if (ordinaryClashing != null || staticClashing != null) {
|
||||
if (ordinaryClashing != null)
|
||||
log.error(pos, Errors.AlreadyDefinedSingleImport(ordinaryClashing));
|
||||
else
|
||||
log.error(pos, Errors.AlreadyDefinedSingleImport(clashing));
|
||||
log.error(pos, Errors.AlreadyDefinedStaticSingleImport(staticClashing));
|
||||
return false;
|
||||
}
|
||||
clashing = topLevelScope.findFirst(sym.name, duplicates);
|
||||
Symbol clashing = topLevelScope.findFirst(sym.name, duplicates);
|
||||
if (clashing != null) {
|
||||
log.error(pos, Errors.AlreadyDefinedThisUnit(clashing));
|
||||
return false;
|
||||
|
@ -91,6 +91,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import jdk.dynalink.CallSiteDescriptor;
|
||||
import jdk.dynalink.Namespace;
|
||||
import jdk.dynalink.Operation;
|
||||
@ -189,85 +190,126 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
|
||||
assertParameterCount(callSiteDescriptor, isFixedKey ? 1 : 2);
|
||||
final LinkerServices linkerServices = req.linkerServices;
|
||||
final MethodType callSiteType = callSiteDescriptor.getMethodType();
|
||||
final Class<?> declaredType = callSiteType.parameterType(0);
|
||||
final GuardedInvocationComponent nextComponent = getNextComponent(req);
|
||||
|
||||
final GuardedInvocationComponentAndCollectionType gicact = guardedInvocationComponentAndCollectionType(
|
||||
callSiteType, linkerServices, MethodHandles::arrayElementGetter, GET_LIST_ELEMENT, GET_MAP_ELEMENT);
|
||||
|
||||
if (gicact == null) {
|
||||
// Can't retrieve elements for objects that are neither arrays, nor list, nor maps.
|
||||
return nextComponent;
|
||||
}
|
||||
|
||||
final Object typedName = getTypedName(name, gicact.collectionType == CollectionType.MAP, linkerServices);
|
||||
if (typedName == INVALID_NAME) {
|
||||
return nextComponent;
|
||||
}
|
||||
|
||||
return guardComponentWithRangeCheck(gicact, linkerServices,
|
||||
callSiteDescriptor, nextComponent, new Binder(linkerServices, callSiteType, typedName),
|
||||
isFixedKey ? NULL_GETTER_1 : NULL_GETTER_2);
|
||||
}
|
||||
|
||||
private static class GuardedInvocationComponentAndCollectionType {
|
||||
final GuardedInvocationComponent gic;
|
||||
final CollectionType collectionType;
|
||||
|
||||
GuardedInvocationComponentAndCollectionType(final GuardedInvocationComponent gic, final CollectionType collectionType) {
|
||||
this.gic = gic;
|
||||
this.collectionType = collectionType;
|
||||
}
|
||||
}
|
||||
|
||||
private GuardedInvocationComponentAndCollectionType guardedInvocationComponentAndCollectionType(
|
||||
final MethodType callSiteType, final LinkerServices linkerServices,
|
||||
final Function<Class<?>, MethodHandle> arrayMethod, final MethodHandle listMethod, final MethodHandle mapMethod) {
|
||||
final Class<?> declaredType = callSiteType.parameterType(0);
|
||||
// If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
|
||||
// is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
|
||||
// dealing with an array, or a list or map, but hey...
|
||||
// Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
|
||||
// in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
|
||||
final GuardedInvocationComponent gic;
|
||||
final CollectionType collectionType;
|
||||
if(declaredType.isArray()) {
|
||||
gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType), linkerServices);
|
||||
collectionType = CollectionType.ARRAY;
|
||||
return new GuardedInvocationComponentAndCollectionType(
|
||||
createInternalFilteredGuardedInvocationComponent(arrayMethod.apply(declaredType), linkerServices),
|
||||
CollectionType.ARRAY);
|
||||
} else if(List.class.isAssignableFrom(declaredType)) {
|
||||
gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, linkerServices);
|
||||
collectionType = CollectionType.LIST;
|
||||
return new GuardedInvocationComponentAndCollectionType(
|
||||
createInternalFilteredGuardedInvocationComponent(listMethod, linkerServices),
|
||||
CollectionType.LIST);
|
||||
} else if(Map.class.isAssignableFrom(declaredType)) {
|
||||
gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, linkerServices);
|
||||
collectionType = CollectionType.MAP;
|
||||
return new GuardedInvocationComponentAndCollectionType(
|
||||
createInternalFilteredGuardedInvocationComponent(mapMethod, linkerServices),
|
||||
CollectionType.MAP);
|
||||
} else if(clazz.isArray()) {
|
||||
gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(MethodHandles.arrayElementGetter(clazz)), callSiteType);
|
||||
collectionType = CollectionType.ARRAY;
|
||||
return new GuardedInvocationComponentAndCollectionType(
|
||||
getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(arrayMethod.apply(clazz)), callSiteType),
|
||||
CollectionType.ARRAY);
|
||||
} else if(List.class.isAssignableFrom(clazz)) {
|
||||
gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
|
||||
linkerServices);
|
||||
collectionType = CollectionType.LIST;
|
||||
return new GuardedInvocationComponentAndCollectionType(
|
||||
createInternalFilteredGuardedInvocationComponent(listMethod, Guards.asType(LIST_GUARD, callSiteType),
|
||||
List.class, ValidationType.INSTANCE_OF, linkerServices),
|
||||
CollectionType.LIST);
|
||||
} else if(Map.class.isAssignableFrom(clazz)) {
|
||||
gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class, ValidationType.INSTANCE_OF,
|
||||
linkerServices);
|
||||
collectionType = CollectionType.MAP;
|
||||
} else {
|
||||
// Can't retrieve elements for objects that are neither arrays, nor list, nor maps.
|
||||
return nextComponent;
|
||||
return new GuardedInvocationComponentAndCollectionType(
|
||||
createInternalFilteredGuardedInvocationComponent(mapMethod, Guards.asType(MAP_GUARD, callSiteType),
|
||||
Map.class, ValidationType.INSTANCE_OF, linkerServices),
|
||||
CollectionType.MAP);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final Object INVALID_NAME = new Object();
|
||||
|
||||
private static Object getTypedName(final Object name, final boolean isMap, final LinkerServices linkerServices) throws Exception {
|
||||
// Convert the key to a number if we're working with a list or array
|
||||
final Object typedName;
|
||||
if (collectionType != CollectionType.MAP && isFixedKey) {
|
||||
if (!isMap && name != null) {
|
||||
final Integer integer = convertKeyToInteger(name, linkerServices);
|
||||
if (integer == null || integer.intValue() < 0) {
|
||||
// key is not a non-negative integer, it can never address an
|
||||
// array or list element
|
||||
return nextComponent;
|
||||
return INVALID_NAME;
|
||||
}
|
||||
typedName = integer;
|
||||
} else {
|
||||
typedName = name;
|
||||
return integer;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
final GuardedInvocation gi = gic.getGuardedInvocation();
|
||||
final Binder binder = new Binder(linkerServices, callSiteType, typedName);
|
||||
final MethodHandle invocation = gi.getInvocation();
|
||||
private static GuardedInvocationComponent guardComponentWithRangeCheck(
|
||||
final GuardedInvocationComponentAndCollectionType gicact, final LinkerServices linkerServices,
|
||||
final CallSiteDescriptor callSiteDescriptor, final GuardedInvocationComponent nextComponent, final Binder binder,
|
||||
final MethodHandle noOp) {
|
||||
final MethodType callSiteType = callSiteDescriptor.getMethodType();
|
||||
|
||||
final MethodHandle checkGuard;
|
||||
switch(collectionType) {
|
||||
case LIST:
|
||||
checkGuard = convertArgToNumber(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
|
||||
break;
|
||||
case MAP:
|
||||
checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP);
|
||||
break;
|
||||
case ARRAY:
|
||||
checkGuard = convertArgToNumber(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
switch(gicact.collectionType) {
|
||||
case LIST:
|
||||
checkGuard = convertArgToNumber(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
|
||||
break;
|
||||
case MAP:
|
||||
checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP);
|
||||
break;
|
||||
case ARRAY:
|
||||
checkGuard = convertArgToNumber(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
// If there's no next component, produce a fixed null-returning one
|
||||
// If there's no next component, produce a fixed no-op one
|
||||
final GuardedInvocationComponent finalNextComponent;
|
||||
if (nextComponent != null) {
|
||||
finalNextComponent = nextComponent;
|
||||
} else {
|
||||
final MethodHandle nullGetterHandle = isFixedKey ? NULL_GETTER_1 : NULL_GETTER_2;
|
||||
finalNextComponent = createGuardedInvocationComponentAsType(nullGetterHandle, callSiteType, linkerServices);
|
||||
finalNextComponent = createGuardedInvocationComponentAsType(noOp, callSiteType, linkerServices);
|
||||
}
|
||||
|
||||
final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
|
||||
final GuardedInvocationComponent gic = gicact.gic;
|
||||
final GuardedInvocation gi = gic.getGuardedInvocation();
|
||||
|
||||
final MethodPair matchedInvocations = matchReturnTypes(binder.bind(gi.getInvocation()),
|
||||
finalNextComponent.getGuardedInvocation().getInvocation());
|
||||
|
||||
return finalNextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
|
||||
gic.getValidatorClass(), gic.getValidationType());
|
||||
}
|
||||
@ -435,90 +477,37 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
|
||||
assertParameterCount(callSiteDescriptor, isFixedKey ? 2 : 3);
|
||||
final LinkerServices linkerServices = req.linkerServices;
|
||||
final MethodType callSiteType = callSiteDescriptor.getMethodType();
|
||||
final Class<?> declaredType = callSiteType.parameterType(0);
|
||||
|
||||
final GuardedInvocationComponent gic;
|
||||
// If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
|
||||
// is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
|
||||
// dealing with an array, or a list or map, but hey...
|
||||
// Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
|
||||
// in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
|
||||
final CollectionType collectionType;
|
||||
if(declaredType.isArray()) {
|
||||
gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementSetter(declaredType), linkerServices);
|
||||
collectionType = CollectionType.ARRAY;
|
||||
} else if(List.class.isAssignableFrom(declaredType)) {
|
||||
gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, linkerServices);
|
||||
collectionType = CollectionType.LIST;
|
||||
} else if(Map.class.isAssignableFrom(declaredType)) {
|
||||
gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, linkerServices);
|
||||
collectionType = CollectionType.MAP;
|
||||
} else if(clazz.isArray()) {
|
||||
gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(
|
||||
MethodHandles.arrayElementSetter(clazz)), callSiteType);
|
||||
collectionType = CollectionType.ARRAY;
|
||||
} else if(List.class.isAssignableFrom(clazz)) {
|
||||
gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
|
||||
linkerServices);
|
||||
collectionType = CollectionType.LIST;
|
||||
} else if(Map.class.isAssignableFrom(clazz)) {
|
||||
gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType),
|
||||
Map.class, ValidationType.INSTANCE_OF, linkerServices);
|
||||
collectionType = CollectionType.MAP;
|
||||
} else {
|
||||
// Can't set elements for objects that are neither arrays, nor list, nor maps.
|
||||
gic = null;
|
||||
collectionType = null;
|
||||
final GuardedInvocationComponentAndCollectionType gicact = guardedInvocationComponentAndCollectionType(
|
||||
callSiteType, linkerServices, MethodHandles::arrayElementSetter, SET_LIST_ELEMENT, PUT_MAP_ELEMENT);
|
||||
|
||||
if(gicact == null) {
|
||||
return getNextComponent(req);
|
||||
}
|
||||
|
||||
final boolean isMap = gicact.collectionType == CollectionType.MAP;
|
||||
|
||||
// In contrast to, say, getElementGetter, we only compute the nextComponent if the target object is not a map,
|
||||
// as maps will always succeed in setting the element and will never need to fall back to the next component
|
||||
// operation.
|
||||
final GuardedInvocationComponent nextComponent = collectionType == CollectionType.MAP ? null : getNextComponent(req);
|
||||
if(gic == null) {
|
||||
final GuardedInvocationComponent nextComponent = isMap ? null : getNextComponent(req);
|
||||
|
||||
final Object typedName = getTypedName(name, isMap, linkerServices);
|
||||
if (typedName == INVALID_NAME) {
|
||||
return nextComponent;
|
||||
}
|
||||
|
||||
// Convert the key to a number if we're working with a list or array
|
||||
final Object typedName;
|
||||
if (collectionType != CollectionType.MAP && isFixedKey) {
|
||||
final Integer integer = convertKeyToInteger(name, linkerServices);
|
||||
if (integer == null || integer.intValue() < 0) {
|
||||
// key is not a non-negative integer, it can never address an
|
||||
// array or list element
|
||||
return nextComponent;
|
||||
}
|
||||
typedName = integer;
|
||||
} else {
|
||||
typedName = name;
|
||||
}
|
||||
|
||||
final GuardedInvocationComponent gic = gicact.gic;
|
||||
final GuardedInvocation gi = gic.getGuardedInvocation();
|
||||
final Binder binder = new Binder(linkerServices, callSiteType, typedName);
|
||||
final MethodHandle invocation = gi.getInvocation();
|
||||
|
||||
if (collectionType == CollectionType.MAP) {
|
||||
assert nextComponent == null;
|
||||
if (isMap) {
|
||||
return gic.replaceInvocation(binder.bind(invocation));
|
||||
}
|
||||
|
||||
assert collectionType == CollectionType.LIST || collectionType == CollectionType.ARRAY;
|
||||
final MethodHandle checkGuard = convertArgToNumber(collectionType == CollectionType.LIST ? RANGE_CHECK_LIST :
|
||||
RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
|
||||
|
||||
// If there's no next component, produce a no-op one.
|
||||
final GuardedInvocationComponent finalNextComponent;
|
||||
if (nextComponent != null) {
|
||||
finalNextComponent = nextComponent;
|
||||
} else {
|
||||
final MethodHandle noOpSetterHandle = isFixedKey ? NO_OP_SETTER_2 : NO_OP_SETTER_3;
|
||||
finalNextComponent = createGuardedInvocationComponentAsType(noOpSetterHandle, callSiteType, linkerServices);
|
||||
}
|
||||
|
||||
final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
|
||||
finalNextComponent.getGuardedInvocation().getInvocation());
|
||||
return finalNextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
|
||||
gic.getValidatorClass(), gic.getValidationType());
|
||||
return guardComponentWithRangeCheck(gicact, linkerServices, callSiteDescriptor,
|
||||
nextComponent, binder, isFixedKey ? NO_OP_SETTER_2 : NO_OP_SETTER_3);
|
||||
}
|
||||
|
||||
private static final MethodHandle GET_COLLECTION_LENGTH = Lookup.PUBLIC.findVirtual(Collection.class, "size",
|
||||
|
@ -1,10 +1,16 @@
|
||||
/* Javadoc style sheet */
|
||||
/*
|
||||
Overall document style
|
||||
*/
|
||||
/*
|
||||
* Javadoc style sheet
|
||||
*/
|
||||
|
||||
@import url('resources/fonts/dejavu.css');
|
||||
|
||||
/*
|
||||
* Styles for individual HTML elements.
|
||||
*
|
||||
* These are styles that are specific to individual HTML elements. Changing them affects the style of a particular
|
||||
* HTML element throughout the page.
|
||||
*/
|
||||
|
||||
body {
|
||||
background-color:#ffffff;
|
||||
color:#353833;
|
||||
@ -41,9 +47,6 @@ a[name]:before, a[name]:target, a[id]:before, a[id]:target {
|
||||
padding-top:129px;
|
||||
margin-top:-129px;
|
||||
}
|
||||
.searchTagResult:before, .searchTagResult:target {
|
||||
color:red;
|
||||
}
|
||||
pre {
|
||||
font-family:'DejaVu Sans Mono', monospace;
|
||||
font-size:14px;
|
||||
@ -91,9 +94,16 @@ table tr td dt code {
|
||||
sup {
|
||||
font-size:8px;
|
||||
}
|
||||
|
||||
/*
|
||||
Document title and Copyright styles
|
||||
*/
|
||||
* Styles for HTML generated by javadoc.
|
||||
*
|
||||
* These are style classes that are used by the standard doclet to generate HTML documentation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Styles for document title and copyright.
|
||||
*/
|
||||
.clear {
|
||||
clear:both;
|
||||
height:0px;
|
||||
@ -124,8 +134,8 @@ Document title and Copyright styles
|
||||
font-weight:bold;
|
||||
}
|
||||
/*
|
||||
Navigation bar styles
|
||||
*/
|
||||
* Styles for navigation bar.
|
||||
*/
|
||||
.bar {
|
||||
background-color:#4D7A97;
|
||||
color:#FFFFFF;
|
||||
@ -233,8 +243,8 @@ ul.subNavList li {
|
||||
overflow:hidden;
|
||||
}
|
||||
/*
|
||||
Page header and footer styles
|
||||
*/
|
||||
* Styles for page header and footer.
|
||||
*/
|
||||
.header, .footer {
|
||||
clear:both;
|
||||
margin:0 20px;
|
||||
@ -277,8 +287,8 @@ Page header and footer styles
|
||||
font-size:13px;
|
||||
}
|
||||
/*
|
||||
Heading styles
|
||||
*/
|
||||
* Styles for headings.
|
||||
*/
|
||||
div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 {
|
||||
background-color:#dee3e9;
|
||||
border:1px solid #d0d9e0;
|
||||
@ -299,8 +309,8 @@ ul.blockList li.blockList h2 {
|
||||
padding:0px 0 20px 0;
|
||||
}
|
||||
/*
|
||||
Page layout container styles
|
||||
*/
|
||||
* Styles for page layout containers.
|
||||
*/
|
||||
.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer {
|
||||
clear:both;
|
||||
padding:10px 20px;
|
||||
@ -346,8 +356,8 @@ Page layout container styles
|
||||
display:inline;
|
||||
}
|
||||
/*
|
||||
List styles
|
||||
*/
|
||||
* Styles for lists.
|
||||
*/
|
||||
li.circle {
|
||||
list-style:circle;
|
||||
}
|
||||
@ -403,8 +413,8 @@ table tr td dl, table tr td dl dt, table tr td dl dd {
|
||||
margin-bottom:1px;
|
||||
}
|
||||
/*
|
||||
Table styles
|
||||
*/
|
||||
* Styles for tables.
|
||||
*/
|
||||
.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary,
|
||||
.requiresSummary, .packagesSummary, .providesSummary, .usesSummary {
|
||||
width:100%;
|
||||
@ -529,7 +539,6 @@ Table styles
|
||||
position:relative;
|
||||
background-color:#4D7A97;
|
||||
float:left;
|
||||
|
||||
}
|
||||
.rowColor th, .altColor th {
|
||||
font-weight:normal;
|
||||
@ -601,8 +610,8 @@ th.colDeprecatedItemName a:link, th.colDeprecatedItemName a:visited,
|
||||
background-color:#EEEEEF;
|
||||
}
|
||||
/*
|
||||
Content styles
|
||||
*/
|
||||
* Styles for contents.
|
||||
*/
|
||||
.description pre {
|
||||
margin-top:0;
|
||||
}
|
||||
@ -613,27 +622,22 @@ Content styles
|
||||
.docSummary {
|
||||
padding:0;
|
||||
}
|
||||
|
||||
ul.blockList ul.blockList ul.blockList li.blockList h3 {
|
||||
font-style:normal;
|
||||
}
|
||||
|
||||
div.block {
|
||||
font-size:14px;
|
||||
font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif;
|
||||
}
|
||||
|
||||
td.colLast div {
|
||||
padding-top:0px;
|
||||
}
|
||||
|
||||
|
||||
td.colLast a {
|
||||
padding-bottom:3px;
|
||||
}
|
||||
/*
|
||||
Formatting effect styles
|
||||
*/
|
||||
* Styles for formatting effect.
|
||||
*/
|
||||
.sourceLineNo {
|
||||
color:green;
|
||||
padding:0 30px 0 0;
|
||||
@ -668,18 +672,16 @@ h1.hidden {
|
||||
margin-right:10px;
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
div.block div.deprecationComment, div.block div.block span.emphasizedPhrase,
|
||||
div.block div.block span.interfaceName {
|
||||
font-style:normal;
|
||||
}
|
||||
|
||||
div.contentContainer ul.blockList li.blockList h2 {
|
||||
padding-bottom:0px;
|
||||
}
|
||||
/*
|
||||
IFRAME specific styles
|
||||
*/
|
||||
* Styles for IFRAME.
|
||||
*/
|
||||
.mainContainer {
|
||||
margin:0 auto;
|
||||
padding:0;
|
||||
@ -733,11 +735,14 @@ IFRAME specific styles
|
||||
margin-bottom:30px;
|
||||
}
|
||||
/*
|
||||
HTML5 specific styles
|
||||
*/
|
||||
* Styles specific to HTML5 elements.
|
||||
*/
|
||||
main, nav, header, footer, section {
|
||||
display:block;
|
||||
}
|
||||
/*
|
||||
* Styles for javadoc search.
|
||||
*/
|
||||
.ui-autocomplete-category {
|
||||
font-weight:bold;
|
||||
font-size:15px;
|
||||
@ -802,7 +807,9 @@ ul.ui-autocomplete li {
|
||||
font-style:italic;
|
||||
font-size:12px;
|
||||
}
|
||||
|
||||
.searchTagResult:before, .searchTagResult:target {
|
||||
color:red;
|
||||
}
|
||||
.moduleGraph span {
|
||||
display:none;
|
||||
position:absolute;
|
||||
@ -838,20 +845,17 @@ table.striped {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
table.borderless > caption,
|
||||
table.plain > caption,
|
||||
table.striped > caption {
|
||||
font-weight: bold;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
table.borderless th, table.borderless td,
|
||||
table.plain th, table.plain td,
|
||||
table.striped th, table.striped td {
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
table.borderless,
|
||||
table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th,
|
||||
table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td {
|
||||
@ -860,7 +864,6 @@ table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.bo
|
||||
table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
table.plain {
|
||||
border-collapse: collapse;
|
||||
border: 1px solid black;
|
||||
@ -872,7 +875,6 @@ table.plain > thead > tr > th, table.plain > tbody > tr > th, table.plain > tr >
|
||||
table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td {
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
table.striped {
|
||||
border-collapse: collapse;
|
||||
border: 1px solid black;
|
||||
|
@ -306,10 +306,10 @@ final class SplitIntoFunctions extends NodeVisitor<BlockLexicalContext> {
|
||||
|
||||
@Override
|
||||
public boolean enterVarNode(final VarNode varNode) {
|
||||
if (!inSplitNode()) {
|
||||
// ES6 block scoped declarations are already placed at their proper position by splitter
|
||||
if (!inSplitNode() || varNode.isBlockScoped()) {
|
||||
return super.enterVarNode(varNode);
|
||||
}
|
||||
assert !varNode.isBlockScoped(); //TODO: we must handle these too, but we currently don't
|
||||
|
||||
final Expression init = varNode.getInit();
|
||||
|
||||
|
@ -41,6 +41,7 @@ import jdk.nashorn.internal.ir.PropertyNode;
|
||||
import jdk.nashorn.internal.ir.SplitNode;
|
||||
import jdk.nashorn.internal.ir.Splittable;
|
||||
import jdk.nashorn.internal.ir.Statement;
|
||||
import jdk.nashorn.internal.ir.VarNode;
|
||||
import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
|
||||
import jdk.nashorn.internal.runtime.Context;
|
||||
import jdk.nashorn.internal.runtime.logging.DebugLogger;
|
||||
@ -201,8 +202,9 @@ final class Splitter extends SimpleNodeVisitor implements Loggable {
|
||||
|
||||
for (final Statement statement : block.getStatements()) {
|
||||
final long weight = WeighNodes.weigh(statement, weightCache);
|
||||
final boolean isBlockScopedVarNode = isBlockScopedVarNode(statement);
|
||||
|
||||
if (statementsWeight + weight >= SPLIT_THRESHOLD || statement.isTerminal()) {
|
||||
if (statementsWeight + weight >= SPLIT_THRESHOLD || statement.isTerminal() || isBlockScopedVarNode) {
|
||||
if (!statements.isEmpty()) {
|
||||
splits.add(createBlockSplitNode(block, function, statements, statementsWeight));
|
||||
statements = new ArrayList<>();
|
||||
@ -210,7 +212,7 @@ final class Splitter extends SimpleNodeVisitor implements Loggable {
|
||||
}
|
||||
}
|
||||
|
||||
if (statement.isTerminal()) {
|
||||
if (statement.isTerminal() || isBlockScopedVarNode) {
|
||||
splits.add(statement);
|
||||
} else {
|
||||
statements.add(statement);
|
||||
@ -243,6 +245,10 @@ final class Splitter extends SimpleNodeVisitor implements Loggable {
|
||||
return new SplitNode(name, newBlock, compiler.findUnit(weight + WeighNodes.FUNCTION_WEIGHT));
|
||||
}
|
||||
|
||||
private boolean isBlockScopedVarNode(final Statement statement) {
|
||||
return statement instanceof VarNode && ((VarNode) statement).isBlockScoped();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enterBlock(final Block block) {
|
||||
if (block.isCatchBlock()) {
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package jdk.nashorn.internal.ir;
|
||||
|
||||
import jdk.nashorn.internal.ir.annotations.Ignore;
|
||||
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
|
||||
|
||||
/**
|
||||
@ -37,6 +38,7 @@ public final class SplitReturn extends Statement {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** The sole instance of this AST node. */
|
||||
@Ignore
|
||||
public static final SplitReturn INSTANCE = new SplitReturn();
|
||||
|
||||
private SplitReturn() {
|
||||
|
265
test/jdk/javax/net/ssl/compatibility/Cert.java
Normal file
265
test/jdk/javax/net/ssl/compatibility/Cert.java
Normal file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The certificates and corresponding private keys used by the test.
|
||||
* All of certificates uses relative weak key size and hash algorithm, then
|
||||
* all JDK releases can load them. Accordingly, a custom java.security file is
|
||||
* provided to make sure such weak key sizes and algorithms are not blocked by
|
||||
* any JDK build.
|
||||
*/
|
||||
public enum Cert {
|
||||
|
||||
// This certificate is generated by the below command:
|
||||
// openssl req -x509 -newkey rsa:1024 -days 7300 \
|
||||
// -subj "/CN=RSA_SHA1_1024" -sha1 \
|
||||
// -keyout key.pem -out cert.pem
|
||||
RSA_SHA1_1024(
|
||||
SignatureAlgorithm.RSA,
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIB/jCCAWegAwIBAgIJANPuKkD7/jxkMA0GCSqGSIb3DQEBBQUAMBgxFjAUBgNV\n" +
|
||||
"BAMMDVJTQV9TSEExXzEwMjQwHhcNMTcwOTA3MDIwNTM0WhcNMzcwOTAyMDIwNTM0\n" +
|
||||
"WjAYMRYwFAYDVQQDDA1SU0FfU0hBMV8xMDI0MIGfMA0GCSqGSIb3DQEBAQUAA4GN\n" +
|
||||
"ADCBiQKBgQC3v7UeIxD5bdv4mqwcpah7sNxpI3IxUFzI2ao1g1jVzDPZt9Zawa3K\n" +
|
||||
"H+m9al1Fg2X1dyNeRlbiXavcIZOQwZqNj08zJEwAdICP8iOnXQ2HUv5cpzArOPTu\n" +
|
||||
"GY3flhf39xgiWsSdfb+cP0QsWNagNU8EtebbHndv8W+2K5JEdlpwQQIDAQABo1Aw\n" +
|
||||
"TjAdBgNVHQ4EFgQU32KqdiGyzg39chNt/OwQzGOlUyAwHwYDVR0jBBgwFoAU32Kq\n" +
|
||||
"diGyzg39chNt/OwQzGOlUyAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOB\n" +
|
||||
"gQAWx8y45IIWWhy44cuQs0qcSDQihIvhXB3pvlpCNdfsSrVoaaH8lrOVjTC718ip\n" +
|
||||
"fE1sF8I9niLHUg8WrAzdQRDsKyUhDUhEEJ7w1ffxwf8bcI9+NgWwEix0Dazzkub8\n" +
|
||||
"2IRXuZ3dGwzoI54XtxvKMFH86nJEj4M/XQGrc9bnlhcn4g==\n" +
|
||||
"-----END CERTIFICATE-----",
|
||||
"30820278020100300d06092a864886f70d0101010500048202623082025e0201" +
|
||||
"0002818100b7bfb51e2310f96ddbf89aac1ca5a87bb0dc69237231505cc8d9aa" +
|
||||
"358358d5cc33d9b7d65ac1adca1fe9bd6a5d458365f577235e4656e25dabdc21" +
|
||||
"9390c19a8d8f4f33244c0074808ff223a75d0d8752fe5ca7302b38f4ee198ddf" +
|
||||
"9617f7f718225ac49d7dbf9c3f442c58d6a0354f04b5e6db1e776ff16fb62b92" +
|
||||
"44765a7041020301000102818100b2c5afdf5c5a9d72c73b7eb0c9465b3fcc79" +
|
||||
"0549d946255bc0861555ef2eb503f1c67757f400cfa7019996123020fb906d5b" +
|
||||
"b66b789ffba90b16270cbd1fbfcf285a821dcdc78fd8f17f399eb231ce9724db" +
|
||||
"af60f9dd20f3e57bb4c0f9fdc9069589b82d442dd868d48c031eb782e27f9e70" +
|
||||
"8469f9b3d5b1b23cee5bf1b41781024100dec184ea77c2126c6bc0c01ba727b4" +
|
||||
"642587d63811240932334dc80c7976e0f715f156e52b352a25e5c52542af2b5f" +
|
||||
"68a29a9b68858f313c4375cc78ec03d859024100d32be8375f52cbe904002321" +
|
||||
"6977aee83fa88bf536d4052d2ed578727d7b7e5aeef91fc52b34c1b6638c00f0" +
|
||||
"4c6985fdaaa2d6e72adbcc7d10ed8bafff69da29024100ae8210acd6f13519b7" +
|
||||
"38a3c7862636ce1610daa3c5d9e3526e9acad3eafc54b57d7d3a44029b7dcf7e" +
|
||||
"b7f9beca1842806892929949b8aa2bb9f5b9202a55c0d1024100887dc0c2c9a2" +
|
||||
"429a823374818c2207b3a631d304d443867505e884c9bbc1ae9228146e2c8b18" +
|
||||
"b67ca52b411010d3c3ff89e366f454076dcd08bc01a5e8790ac102402321988a" +
|
||||
"2003e19c878791d402a7c0acdd1b6dd27203ed88f86a0e3a390ee57c0cd277f3" +
|
||||
"ea5df6440dbc8bdb4c8b3c28fc77e6991bc4ed3f4dc0619a5b953e8e"),
|
||||
|
||||
// This certificate is generated by the below command:
|
||||
// openssl req -x509 -newkey rsa:1024 -days 7300 \
|
||||
// -subj "/CN=www.example.com" -sha1 \
|
||||
// -keyout key.pem -out cert.pem
|
||||
RSA_EXAMPLE_SHA1_1024(
|
||||
SignatureAlgorithm.RSA,
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIICAjCCAWugAwIBAgIJAK6TC9eDtZg4MA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV\n" +
|
||||
"BAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNzExMDIwNTA5NDRaFw0zNzEwMjgwNTA5\n" +
|
||||
"NDRaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEF\n" +
|
||||
"AAOBjQAwgYkCgYEAtt5kxFTzJuoxJR2UgeXUxCw7TfL3FeK3lCrU3vruBe3XKKvF\n" +
|
||||
"oyCxf/B5ucm22gzMfOvJBWRg6KrNTrXGI1LtlmAYNDM5J0lK2N/neKOm3Qxe0d1W\n" +
|
||||
"AZ1lwgrMNirsWu+r4UPNMq5UohL5nqVU9WwVa12t0GF3er3k32tMTBqSclcCAwEA\n" +
|
||||
"AaNQME4wHQYDVR0OBBYEFNc8tKGfZdFyaY0ZslwGLt1kpRYAMB8GA1UdIwQYMBaA\n" +
|
||||
"FNc8tKGfZdFyaY0ZslwGLt1kpRYAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF\n" +
|
||||
"BQADgYEAc71ZO83YEw9WvhxDEng9tMYUhJnNZJss6+gfWjZ487aiEGnS+VgKsHWz\n" +
|
||||
"DBLBrYe9Ag5L9f1HtPNheUbnhhBbQ607jOG/wfmpi4VoU3myB5uxOfeAZdXDOB5x\n" +
|
||||
"bv3t7KcEhgmPjB/e123jrBK8qnAYmDlQVlkZScctB3I1OuA2Po4=\n" +
|
||||
"-----END CERTIFICATE-----",
|
||||
"30820277020100300d06092a864886f70d0101010500048202613082025d0201" +
|
||||
"0002818100b6de64c454f326ea31251d9481e5d4c42c3b4df2f715e2b7942ad4" +
|
||||
"defaee05edd728abc5a320b17ff079b9c9b6da0ccc7cebc9056460e8aacd4eb5" +
|
||||
"c62352ed96601834333927494ad8dfe778a3a6dd0c5ed1dd56019d65c20acc36" +
|
||||
"2aec5aefabe143cd32ae54a212f99ea554f56c156b5dadd061777abde4df6b4c" +
|
||||
"4c1a927257020301000102818048af52bc1acbdededd13d4930fa28b9441c47c" +
|
||||
"b222f5c6fc92df07676db3a815a61c9b51de0a03a347b10a609bd6459a0dd926" +
|
||||
"38877261686a5c6bb1ca9e8ea2373870af7685e7d6cebd66faba65af2ef04bd9" +
|
||||
"1244ae56900fcd6ce11207d8c4040176e4ba9fef3d563741a1027b229134cfe1" +
|
||||
"c0a90d9c8eba9ce6349835e769024100e82494b6f777c784ffc29298d033e11d" +
|
||||
"af46f0d464c4dbd950d46bcd697d0f0b49a77699f0111d408e8748f2b461ab8f" +
|
||||
"210071c9c20d8ecee3ae229cb9c3954b024100c9a976f0011fcdc0ca7fb2f679" +
|
||||
"974fa85d420c604ca7ff64fe4667a44f73088eef290d22195474039760e99325" +
|
||||
"3ca45ee444588b150467d14451d3c45dab0ba5024019df39d3ca70c703c39d63" +
|
||||
"c9342b1403c2ed1d1a0ec101df8e6a9e391e7099a4a068d187068261c8381a4b" +
|
||||
"bf00eb81bb49ea4ac439a4592e25a1daa9acea67510241008c4640007497bdd4" +
|
||||
"94473da26b33d06a29ecae9531dd4e2edf1cf42cfc42e53a1fac2b8183a3164c" +
|
||||
"053999600c6fe15a4c682a3b1cb482ceb33a4416fc9ce52d024100e4f08cd10a" +
|
||||
"5c8face0b20db86443d0a42e34dfdde236dae4f042a06dd3aff7ca159f8aa3b7" +
|
||||
"854df41d510148096155204f2bf46c4a96e271747a4126a66ade6c"),
|
||||
|
||||
// This certificate is generated by the below commands:
|
||||
// openssl dsaparam -genkey 1024 -out key.pem
|
||||
// openssl req -x509 -new -key key.pem -days 7300 \
|
||||
// -subj "/CN=DSA_SHA1_1024" -sha1 -out cert.pem
|
||||
DSA_SHA1_1024(
|
||||
SignatureAlgorithm.DSA,
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIICuzCCAnugAwIBAgIJAMAMLRrhQWQFMAkGByqGSM44BAMwGDEWMBQGA1UEAwwN\n" +
|
||||
"RFNBX1NIQTFfMTAyNDAeFw0xNzExMDIwNjA4MDRaFw0zNzEwMjgwNjA4MDRaMBgx\n" +
|
||||
"FjAUBgNVBAMMDURTQV9TSEExXzEwMjQwggG2MIIBKwYHKoZIzjgEATCCAR4CgYEA\n" +
|
||||
"8CspE1sE84pJ4YxzVHFEDNJvBaIxsbax03pDwNHr/ogP9PVwF9z1jT6hpC5WluHG\n" +
|
||||
"g5n5gqpF2XpBhX2fKm1qqZWRxNvHKo0+zzAhUqMrvRJqcjlL4ijXndHldt67/VKS\n" +
|
||||
"0eTKi9m64c+yJx80YYphCO5b93d2sTM29z8QZOlrbD8CFQCmttKnPAOk4uz8Z8cV\n" +
|
||||
"uPGeGOMB9wKBgCItgPpAjW0srIwCaDysDNpydX6hB+1NTy1gFYl24n8edLGbR0mZ\n" +
|
||||
"isteBd6LjMtgicRmtKZzKxW7igxoVvR3WHpTucFjms5NRNjPaj5wt3DxoXn4hyWk\n" +
|
||||
"LzMvDeBvi+jKJiO0jnQ3+1NDOlAQy6ukeH59/gxZ3UmcNxDlAQ/IYHcpA4GEAAKB\n" +
|
||||
"gEgvi72gL+zax7Y2hg4PL1PqZx2jFp0XlTIugiTrcsGytrAnn+/s2+3xVyVyvVMn\n" +
|
||||
"0z5yL5eP9cdGA7qV1+7n6KJ8jNAhLCBSiC6x5ekd88aTlqnmt5lstk4w0Q0zSa58\n" +
|
||||
"Hp6dCFg2Irk6Z9ERKaXJJBBS6reaFeATVROhN/LEEzzvo1AwTjAdBgNVHQ4EFgQU\n" +
|
||||
"jb+HHABclGNR4lpf19nHFZpfwPQwHwYDVR0jBBgwFoAUjb+HHABclGNR4lpf19nH\n" +
|
||||
"FZpfwPQwDAYDVR0TBAUwAwEB/zAJBgcqhkjOOAQDAy8AMCwCFDB3F/m6jsZdHaoy\n" +
|
||||
"1xTp2U8uHBO+AhQYzeJuJd8/qRSDVLs8mesE8TQg2g==\n" +
|
||||
"-----END CERTIFICATE-----",
|
||||
"3082014a0201003082012b06072a8648ce3804013082011e02818100f02b2913" +
|
||||
"5b04f38a49e18c735471440cd26f05a231b1b6b1d37a43c0d1ebfe880ff4f570" +
|
||||
"17dcf58d3ea1a42e5696e1c68399f982aa45d97a41857d9f2a6d6aa99591c4db" +
|
||||
"c72a8d3ecf302152a32bbd126a72394be228d79dd1e576debbfd5292d1e4ca8b" +
|
||||
"d9bae1cfb2271f34618a6108ee5bf77776b13336f73f1064e96b6c3f021500a6" +
|
||||
"b6d2a73c03a4e2ecfc67c715b8f19e18e301f7028180222d80fa408d6d2cac8c" +
|
||||
"02683cac0cda72757ea107ed4d4f2d60158976e27f1e74b19b4749998acb5e05" +
|
||||
"de8b8ccb6089c466b4a6732b15bb8a0c6856f477587a53b9c1639ace4d44d8cf" +
|
||||
"6a3e70b770f1a179f88725a42f332f0de06f8be8ca2623b48e7437fb53433a50" +
|
||||
"10cbaba4787e7dfe0c59dd499c3710e5010fc8607729041602146ef9db36045f" +
|
||||
"bcd8c7fd82ba29c5c5057ed11c7f"),
|
||||
|
||||
// This certificate is generated by the below commands:
|
||||
// openssl dsaparam -genkey 1024 -out key.pem
|
||||
// openssl req -x509 -new -key key.pem -days 7300 \
|
||||
// -subj "/CN=www.example.com" -sha1 -out cert.pem
|
||||
DSA_EXAMPLE_SHA1_1024(
|
||||
SignatureAlgorithm.DSA,
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIICwDCCAoCgAwIBAgIJAI5mKbdK5ZqyMAkGByqGSM44BAMwGjEYMBYGA1UEAwwP\n" +
|
||||
"d3d3LmV4YW1wbGUuY29tMB4XDTE3MTEwMjA1NDczOVoXDTM3MTAyODA1NDczOVow\n" +
|
||||
"GjEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tMIIBtzCCASwGByqGSM44BAEwggEf\n" +
|
||||
"AoGBANVGWRSlxVZQKlVrTDcU/6Mr8QFlR3kGKmkvdbTHH1EhcP7YlZ7CJ30VBDbN\n" +
|
||||
"LS2HvN3HHNooJ7hHBheL5Yz8EZIUa95TzPukZ1TmCo9fufR5i9HWj9Z8jLhyqx3l\n" +
|
||||
"iUZOYN9H0MSn4ftK6dr5oTz2ZGYDblXDCq6R8qZfuw1URFqrAhUArx0nmGEI/1S/\n" +
|
||||
"qyxnV4I6ItOntxMCgYEAxZKIZ/7aOGfzaQG2wRFdD/viHBZkkcxCsgmPUroQVUIw\n" +
|
||||
"dqmUnfYk8cb02LCevhhSwcjfocQsA3y1jufIUdWaHuIB9W3EsFJQNd/Byh9j/pRD\n" +
|
||||
"7zH/8lnBzJh2S7y10Vg840STVo5+ekZb4E+W7KK5gUaEQ6kAtUIIB0xjNz7RWs4D\n" +
|
||||
"gYQAAoGAPVQKWqJSlMrbU4XEsx50Ur8P84CwMnS7WcQNLnih1ScaK2BijgVj5Fny\n" +
|
||||
"9JZxITwj7XD7FWriq3kTjbydi3iAvrgVWij79x5Z7fTRCuoBVmtnAFkVGalwbGr2\n" +
|
||||
"ghz70y6hep2Evb1pRCrHjRkMaJFE5Y2CA7VbpKoat+j47/LkXJ2jUDBOMB0GA1Ud\n" +
|
||||
"DgQWBBSVjWy3SpaDfnFo+37mZJqX2aybzTAfBgNVHSMEGDAWgBSVjWy3SpaDfnFo\n" +
|
||||
"+37mZJqX2aybzTAMBgNVHRMEBTADAQH/MAkGByqGSM44BAMDLwAwLAIUd5NOlcfX\n" +
|
||||
"5rakT9H8UzlFcFQLr0MCFGrEYvlFUf/HJOH4FwXS2jEholBB\n" +
|
||||
"-----END CERTIFICATE-----",
|
||||
"3082014c0201003082012c06072a8648ce3804013082011f02818100d5465914" +
|
||||
"a5c556502a556b4c3714ffa32bf101654779062a692f75b4c71f512170fed895" +
|
||||
"9ec2277d150436cd2d2d87bcddc71cda2827b84706178be58cfc1192146bde53" +
|
||||
"ccfba46754e60a8f5fb9f4798bd1d68fd67c8cb872ab1de589464e60df47d0c4" +
|
||||
"a7e1fb4ae9daf9a13cf66466036e55c30aae91f2a65fbb0d54445aab021500af" +
|
||||
"1d27986108ff54bfab2c6757823a22d3a7b71302818100c5928867feda3867f3" +
|
||||
"6901b6c1115d0ffbe21c166491cc42b2098f52ba1055423076a9949df624f1c6" +
|
||||
"f4d8b09ebe1852c1c8dfa1c42c037cb58ee7c851d59a1ee201f56dc4b0525035" +
|
||||
"dfc1ca1f63fe9443ef31fff259c1cc98764bbcb5d1583ce34493568e7e7a465b" +
|
||||
"e04f96eca2b981468443a900b54208074c63373ed15ace0417021500abf47692" +
|
||||
"88c6ac41e2802e7eb7addba367339318"),
|
||||
|
||||
// This certificate is generated by the below commands:
|
||||
// openssl ecparam -name prime256v1 -genkey -out key.pem
|
||||
// openssl req -new -key key.pem -x509 -nodes -days 7300 \
|
||||
// -subj "/CN=ECDSA_SHA1_prime256v1" -sha1 -out cert.pem
|
||||
ECDSA_SHA1_PRIME256V1(
|
||||
SignatureAlgorithm.ECDSA,
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIBhDCCASygAwIBAgIJAKW4wuujp9JbMAkGByqGSM49BAEwIDEeMBwGA1UEAwwV\n" +
|
||||
"RUNEU0FfU0hBMV9wcmltZTI1NnYxMB4XDTE3MDkwNzAyMTA0MVoXDTM3MDkwMjAy\n" +
|
||||
"MTA0MVowIDEeMBwGA1UEAwwVRUNEU0FfU0hBMV9wcmltZTI1NnYxMFkwEwYHKoZI\n" +
|
||||
"zj0CAQYIKoZIzj0DAQcDQgAEdbE+AMwsFBf73YXRVwsvsx2dMt1xgDxj/4pN+BfY\n" +
|
||||
"LWnO94beeZcrCJ1/N8CHmDOce7KRDR6/9kpi20wFAVXZ3KNQME4wHQYDVR0OBBYE\n" +
|
||||
"FA/hB2ODDNdz1JF08u2uhknhlsVoMB8GA1UdIwQYMBaAFA/hB2ODDNdz1JF08u2u\n" +
|
||||
"hknhlsVoMAwGA1UdEwQFMAMBAf8wCQYHKoZIzj0EAQNHADBEAiBNxv2L2FW+6+w/\n" +
|
||||
"QtDe+YSUNRj3F8QrpLkfGk7rVaOiHQIgVF2pWJ5ytg0pbCuO8Bh+UZ7zfZUD03s8\n" +
|
||||
"ZuIYW7RtMe0=\n" +
|
||||
"-----END CERTIFICATE-----",
|
||||
"308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02" +
|
||||
"010104204d901d5efd0e3def78d5307788a4c760115effce4b9e2c31ae5860b6" +
|
||||
"c11915aca1440342000475b13e00cc2c1417fbdd85d1570b2fb31d9d32dd7180" +
|
||||
"3c63ff8a4df817d82d69cef786de79972b089d7f37c08798339c7bb2910d1ebf" +
|
||||
"f64a62db4c050155d9dc"),
|
||||
|
||||
// This certificate is generated by the below commands:
|
||||
// openssl ecparam -name prime256v1 -genkey -out key.pem
|
||||
// openssl req -new -key key.pem -x509 -nodes -days 7300 \
|
||||
// -subj "/CN=www.example.com" -sha1 -out cert.pem
|
||||
ECDSA_EXAMPLE_SHA1_PRIME256V1(
|
||||
SignatureAlgorithm.ECDSA,
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIBeDCCASCgAwIBAgIJAMxOXBpiJ5mDMAkGByqGSM49BAEwGjEYMBYGA1UEAwwP\n" +
|
||||
"d3d3LmV4YW1wbGUuY29tMB4XDTE3MTEwMjA1MTg0MVoXDTM3MTAyODA1MTg0MVow\n" +
|
||||
"GjEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D\n" +
|
||||
"AQcDQgAER9IyuwyrJ7X9DmIqGC3YNTlWBt4Fo/Y3RnlcxhTVxb/ZAYVNhqe4MbSM\n" +
|
||||
"2nsVnYMjjXXDav1plNKvmgGDf9s/saNQME4wHQYDVR0OBBYEFHNUTaIIEA89uNKH\n" +
|
||||
"OOUgJ981Qj5HMB8GA1UdIwQYMBaAFHNUTaIIEA89uNKHOOUgJ981Qj5HMAwGA1Ud\n" +
|
||||
"EwQFMAMBAf8wCQYHKoZIzj0EAQNHADBEAiBCW59S1nE15j8euO6/q9bM6J9Ci5xJ\n" +
|
||||
"WWAVznGGxnS/HgIgFaFKC31uxTXoBN7QN0yW/umQgJ0nsjwj7Pnxc0wNyw8=\n" +
|
||||
"-----END CERTIFICATE-----",
|
||||
"308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02" +
|
||||
"010104209aa3784cd0c1fe0553e59b3c7b8f08c8fdaffd94f34e2c1683243a79" +
|
||||
"7b64b673a1440342000447d232bb0cab27b5fd0e622a182dd835395606de05a3" +
|
||||
"f63746795cc614d5c5bfd901854d86a7b831b48cda7b159d83238d75c36afd69" +
|
||||
"94d2af9a01837fdb3fb1");
|
||||
|
||||
public final SignatureAlgorithm signatureAlgorithm;
|
||||
public final String certMaterials;
|
||||
public final String privKeyMaterials;
|
||||
|
||||
private Cert(
|
||||
SignatureAlgorithm signatureAlgorithm,
|
||||
String certMaterials,
|
||||
String privKeyMaterials) {
|
||||
this.signatureAlgorithm = signatureAlgorithm;
|
||||
this.certMaterials = certMaterials;
|
||||
this.privKeyMaterials = privKeyMaterials;
|
||||
}
|
||||
|
||||
// Two certificates (mainCert and exampleCert) are selected to respect the
|
||||
// specified cipher suite. SNI-associated cases specify exampleCert as desired.
|
||||
public static Cert[] getCerts(String cipherSuite) {
|
||||
Cert mainCert = Cert.DSA_SHA1_1024;
|
||||
Cert exampleCert = Cert.DSA_EXAMPLE_SHA1_1024;
|
||||
if (cipherSuite.contains("_ECDHE_RSA_")) {
|
||||
mainCert = Cert.RSA_SHA1_1024;
|
||||
exampleCert = Cert.RSA_EXAMPLE_SHA1_1024;
|
||||
} else if (cipherSuite.contains("_EC")) {
|
||||
mainCert = Cert.ECDSA_SHA1_PRIME256V1;
|
||||
exampleCert = Cert.ECDSA_EXAMPLE_SHA1_PRIME256V1;
|
||||
} else if (cipherSuite.contains("_RSA")) {
|
||||
mainCert = Cert.RSA_SHA1_1024;
|
||||
exampleCert = Cert.RSA_EXAMPLE_SHA1_1024;
|
||||
}
|
||||
System.out.printf("mainCert=%s, exampleCert=%s%n",
|
||||
mainCert, exampleCert);
|
||||
return new Cert[] { mainCert, exampleCert };
|
||||
}
|
||||
}
|
||||
|
||||
enum SignatureAlgorithm {
|
||||
|
||||
RSA, DSA, ECDSA;
|
||||
}
|
206
test/jdk/javax/net/ssl/compatibility/Client.java
Normal file
206
test/jdk/javax/net/ssl/compatibility/Client.java
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
/*
|
||||
* A simple SSL socket client.
|
||||
*/
|
||||
public class Client {
|
||||
|
||||
private final SSLSocket socket;
|
||||
|
||||
public Client(SSLContext context) throws Exception {
|
||||
SSLSocketFactory socketFactory = context.getSocketFactory();
|
||||
socket = (SSLSocket) socketFactory.createSocket();
|
||||
socket.setSoTimeout(Utils.TIMEOUT);
|
||||
}
|
||||
|
||||
public Client(Cert... certs) throws Exception {
|
||||
this(Utils.createSSLContext(certs));
|
||||
}
|
||||
|
||||
private SSLSession getSession() {
|
||||
return socket.getSession();
|
||||
}
|
||||
|
||||
private void setEnabledCipherSuites(String... cipherSuites) {
|
||||
socket.setEnabledCipherSuites(cipherSuites);
|
||||
}
|
||||
|
||||
private void setEnabledProtocols(String... protocols) {
|
||||
socket.setEnabledProtocols(protocols);
|
||||
}
|
||||
|
||||
@SuppressWarnings(value = { "unchecked", "rawtypes" })
|
||||
private void setServerName(String hostname) {
|
||||
List serverNames = new ArrayList();
|
||||
serverNames.add(createSNIHostName(hostname));
|
||||
SSLParameters params = socket.getSSLParameters();
|
||||
params.setServerNames(serverNames);
|
||||
socket.setSSLParameters(params);
|
||||
}
|
||||
|
||||
// Create SNIHostName via reflection due to pre-8 JDK builds don't support
|
||||
// SNI. Those JDK builds cannot find classes SNIServerName and SNIHostName.
|
||||
private Object createSNIHostName(String hostname) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName("javax.net.ssl.SNIHostName");
|
||||
return clazz.getConstructor(String.class).newInstance(hostname);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Creates SNIHostName failed!", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setApplicationProtocols(String... protocols) {
|
||||
SSLParameters params = socket.getSSLParameters();
|
||||
params.setApplicationProtocols(protocols);
|
||||
socket.setSSLParameters(params);
|
||||
}
|
||||
|
||||
private String getNegotiatedApplicationProtocol() {
|
||||
return socket.getApplicationProtocol();
|
||||
}
|
||||
|
||||
private void oneTimeConnect(String host, int port) throws IOException {
|
||||
socket.connect(new InetSocketAddress(host, port));
|
||||
|
||||
OutputStream out = socket.getOutputStream();
|
||||
out.write('C');
|
||||
out.flush();
|
||||
|
||||
InputStream in = socket.getInputStream();
|
||||
in.read();
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
socket.close();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
System.out.println("----- Client start -----");
|
||||
int port = Integer.valueOf(System.getProperty(Utils.PROP_PORT));
|
||||
|
||||
String protocol = System.getProperty(Utils.PROP_PROTOCOL);
|
||||
String cipherSuite = System.getProperty(Utils.PROP_CIPHER_SUITE);
|
||||
String serverName = System.getProperty(Utils.PROP_SERVER_NAME);
|
||||
String appProtocols = System.getProperty(Utils.PROP_APP_PROTOCOLS);
|
||||
boolean supportsSNIOnServer
|
||||
= Utils.getBoolProperty(Utils.PROP_SUPPORTS_SNI_ON_SERVER);
|
||||
boolean supportsSNIOnClient
|
||||
= Utils.getBoolProperty(Utils.PROP_SUPPORTS_SNI_ON_CLIENT);
|
||||
boolean supportsALPNOnServer
|
||||
= Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_SERVER);
|
||||
boolean supportsALPNOnClient
|
||||
= Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_CLIENT);
|
||||
boolean negativeCase
|
||||
= Utils.getBoolProperty(Utils.PROP_NEGATIVE_CASE_ON_CLIENT);
|
||||
System.out.println(Utils.join(Utils.PARAM_DELIMITER,
|
||||
"ClientJDK=" + System.getProperty(Utils.PROP_CLIENT_JDK),
|
||||
"Protocol=" + protocol,
|
||||
"CipherSuite=" + cipherSuite,
|
||||
"ServerName=" + serverName,
|
||||
"AppProtocols=" + appProtocols));
|
||||
|
||||
Status status = Status.SUCCESS;
|
||||
Client client = null;
|
||||
try {
|
||||
client = new Client(Cert.getCerts(cipherSuite));
|
||||
client.setEnabledProtocols(protocol);
|
||||
client.setEnabledCipherSuites(cipherSuite);
|
||||
|
||||
if (serverName != null) {
|
||||
if (supportsSNIOnClient) {
|
||||
client.setServerName(serverName);
|
||||
} else {
|
||||
System.out.println(
|
||||
"Ignored due to client doesn't support SNI.");
|
||||
}
|
||||
}
|
||||
|
||||
if (appProtocols != null) {
|
||||
if (supportsALPNOnClient) {
|
||||
client.setApplicationProtocols(
|
||||
Utils.split(appProtocols, Utils.VALUE_DELIMITER));
|
||||
} else {
|
||||
System.out.println(
|
||||
"Ignored due to client doesn't support ALPN.");
|
||||
}
|
||||
}
|
||||
|
||||
client.oneTimeConnect("localhost", port);
|
||||
|
||||
if (serverName != null && supportsSNIOnServer
|
||||
&& supportsSNIOnClient) {
|
||||
X509Certificate cert
|
||||
= (X509Certificate) client.getSession().getPeerCertificates()[0];
|
||||
String subject
|
||||
= cert.getSubjectX500Principal().getName();
|
||||
if (!subject.contains(serverName)) {
|
||||
System.out.println("Unexpected server: " + subject);
|
||||
status = Status.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (appProtocols != null && supportsALPNOnServer
|
||||
&& supportsALPNOnClient) {
|
||||
String negoAppProtocol
|
||||
= client.getNegotiatedApplicationProtocol();
|
||||
String expectedNegoAppProtocol
|
||||
= System.getProperty(Utils.PROP_NEGO_APP_PROTOCOL);
|
||||
if (!expectedNegoAppProtocol.equals(negoAppProtocol)) {
|
||||
System.out.println("Unexpected negotiated app protocol: "
|
||||
+ negoAppProtocol);
|
||||
status = Status.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (status != Status.FAIL) {
|
||||
status = negativeCase
|
||||
? Status.UNEXPECTED_SUCCESS
|
||||
: Status.SUCCESS;
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
status = Utils.handleException(exception, negativeCase);
|
||||
} finally {
|
||||
if (client != null) {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("STATUS: " + status);
|
||||
System.out.println("----- Client end -----");
|
||||
}
|
||||
}
|
338
test/jdk/javax/net/ssl/compatibility/Compatibility.java
Normal file
338
test/jdk/javax/net/ssl/compatibility/Compatibility.java
Normal file
@ -0,0 +1,338 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary This test is used to check the interop compatibility on JSSE among
|
||||
* different JDK releases.
|
||||
* Note that, this is a manual test. For more details about the test and
|
||||
* its usages, please look through README.
|
||||
*
|
||||
* @library /test/lib
|
||||
* @compile -source 1.6 -target 1.6 JdkUtils.java Parameter.java Server.java Client.java
|
||||
* @run main/manual Compatibility
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
public class Compatibility {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
String javaSecurityFile
|
||||
= System.getProperty("test.src") + "/java.security";
|
||||
boolean debug = Utils.getBoolProperty("debug");
|
||||
|
||||
Set<JdkInfo> jdkInfos = jdkInfoList();
|
||||
|
||||
System.out.println("Test start");
|
||||
|
||||
List<TestCase> testCases = new ArrayList<>();
|
||||
ExecutorService executor = Executors.newCachedThreadPool();
|
||||
PrintStream origStdOut = System.out;
|
||||
PrintStream origStdErr = System.err;
|
||||
|
||||
try (PrintStream printStream = new PrintStream(
|
||||
new FileOutputStream(Utils.TEST_LOG, true))) {
|
||||
System.setOut(printStream);
|
||||
System.setErr(printStream);
|
||||
|
||||
System.out.println(Utils.startHtml());
|
||||
System.out.println(Utils.startPre());
|
||||
|
||||
for (UseCase useCase : UseCase.getAllUseCases()) {
|
||||
for (JdkInfo serverJdk : jdkInfos) {
|
||||
if (useCase.ignoredByJdk(serverJdk)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, String> props = new LinkedHashMap<>();
|
||||
if (debug) {
|
||||
props.put("javax.net.debug", "ssl");
|
||||
}
|
||||
props.put("java.security.properties", javaSecurityFile);
|
||||
|
||||
props.put(Utils.PROP_PROTOCOL, useCase.protocol.version);
|
||||
props.put(Utils.PROP_CIPHER_SUITE, useCase.cipherSuite.name());
|
||||
props.put(Utils.PROP_CLIENT_AUTH, useCase.clientAuth.name());
|
||||
if (useCase.appProtocol != AppProtocol.NONE) {
|
||||
props.put(Utils.PROP_APP_PROTOCOLS,
|
||||
Utils.join(Utils.VALUE_DELIMITER,
|
||||
useCase.appProtocol.appProtocols));
|
||||
props.put(Utils.PROP_NEGO_APP_PROTOCOL,
|
||||
useCase.appProtocol.negoAppProtocol);
|
||||
}
|
||||
props.put(Utils.PROP_SERVER_JDK, serverJdk.version);
|
||||
|
||||
props.put(Utils.PROP_SUPPORTS_SNI_ON_SERVER,
|
||||
serverJdk.supportsSNI + "");
|
||||
props.put(Utils.PROP_SUPPORTS_ALPN_ON_SERVER,
|
||||
serverJdk.supportsALPN + "");
|
||||
|
||||
for (JdkInfo clientJdk : jdkInfos) {
|
||||
if (useCase.ignoredByJdk(clientJdk)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TestCase testCase = new TestCase(serverJdk, clientJdk,
|
||||
useCase);
|
||||
System.out.println(Utils.anchorName(testCase.toString(),
|
||||
"----- Case start -----"));
|
||||
System.out.println(testCase.toString());
|
||||
|
||||
props.put(Utils.PROP_NEGATIVE_CASE_ON_SERVER,
|
||||
testCase.negativeCaseOnServer + "");
|
||||
props.put(Utils.PROP_NEGATIVE_CASE_ON_CLIENT,
|
||||
testCase.negativeCaseOnClient + "");
|
||||
|
||||
Future<OutputAnalyzer> serverFuture = executor.submit(() -> {
|
||||
return runServer(serverJdk.jdkPath, props);
|
||||
});
|
||||
int port = waitForServerStarted();
|
||||
System.out.println("port=" + port);
|
||||
|
||||
props.put(Utils.PROP_PORT, port + "");
|
||||
|
||||
props.put(Utils.PROP_CLIENT_JDK, clientJdk.version);
|
||||
|
||||
props.put(Utils.PROP_SUPPORTS_SNI_ON_CLIENT,
|
||||
clientJdk.supportsSNI + "");
|
||||
props.put(Utils.PROP_SUPPORTS_ALPN_ON_CLIENT,
|
||||
clientJdk.supportsALPN + "");
|
||||
if (useCase.serverName != ServerName.NONE) {
|
||||
props.put(Utils.PROP_SERVER_NAME,
|
||||
useCase.serverName.name);
|
||||
}
|
||||
|
||||
Status clientStatus = null;
|
||||
if (port != -1) {
|
||||
String clientOutput = runClient(clientJdk.jdkPath,
|
||||
props).getOutput();
|
||||
clientStatus = getStatus(clientOutput);
|
||||
}
|
||||
|
||||
String serverOutput = serverFuture.get().getOutput();
|
||||
Status serverStatus = getStatus(serverOutput);
|
||||
testCase.setStatus(caseStatus(serverStatus, clientStatus));
|
||||
testCases.add(testCase);
|
||||
System.out.printf(
|
||||
"ServerStatus=%s, ClientStatus=%s, CaseStatus=%s%n",
|
||||
serverStatus, clientStatus, testCase.getStatus());
|
||||
|
||||
// Confirm the server has stopped.
|
||||
if(new File(Utils.PORT_LOG).exists()) {
|
||||
throw new RuntimeException("Server doesn't stop.");
|
||||
}
|
||||
System.out.println("----- Case end -----");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(Utils.endPre());
|
||||
System.out.println(Utils.endHtml());
|
||||
}
|
||||
System.setOut(origStdOut);
|
||||
System.setErr(origStdErr);
|
||||
executor.shutdown();
|
||||
|
||||
System.out.println("Test end");
|
||||
System.out.println("Report is being generated...");
|
||||
boolean failed = generateReport(testCases);
|
||||
System.out.println("Report is generated.");
|
||||
if (failed) {
|
||||
throw new RuntimeException("At least one case failed. "
|
||||
+ "Please check logs for more details.");
|
||||
}
|
||||
}
|
||||
|
||||
private static Status getStatus(String log) {
|
||||
if (log.contains(Status.UNEXPECTED_SUCCESS.name())) {
|
||||
return Status.UNEXPECTED_SUCCESS;
|
||||
} else if (log.contains(Status.SUCCESS.name())) {
|
||||
return Status.SUCCESS;
|
||||
} else if (log.contains(Status.EXPECTED_FAIL.name())) {
|
||||
return Status.EXPECTED_FAIL;
|
||||
} else if (log.contains(Status.TIMEOUT.name())) {
|
||||
return Status.TIMEOUT;
|
||||
} else {
|
||||
return Status.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
private static Status caseStatus(Status serverStatus, Status clientStatus) {
|
||||
if (clientStatus == null || clientStatus == Status.TIMEOUT) {
|
||||
return serverStatus == Status.EXPECTED_FAIL
|
||||
? Status.EXPECTED_FAIL
|
||||
: Status.FAIL;
|
||||
} else if (serverStatus == Status.TIMEOUT) {
|
||||
return clientStatus == Status.EXPECTED_FAIL
|
||||
? Status.EXPECTED_FAIL
|
||||
: Status.FAIL;
|
||||
} else {
|
||||
return serverStatus == clientStatus
|
||||
? serverStatus
|
||||
: Status.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieves JDK info from the file which is specified by jdkListFile.
|
||||
// If no such file or no JDK is specified by the file, the current testing
|
||||
// JDK will be used.
|
||||
private static Set<JdkInfo> jdkInfoList() throws Throwable {
|
||||
List<String> jdkList = jdkList("jdkListFile");
|
||||
if (jdkList.size() == 0) {
|
||||
jdkList.add(System.getProperty("test.jdk"));
|
||||
}
|
||||
|
||||
Set<JdkInfo> jdkInfoList = new LinkedHashSet<>();
|
||||
for (String jdkPath : jdkList) {
|
||||
JdkInfo jdkInfo = new JdkInfo(jdkPath);
|
||||
// JDK version must be unique.
|
||||
if (!jdkInfoList.add(jdkInfo)) {
|
||||
System.out.println("The JDK version is duplicate: " + jdkPath);
|
||||
}
|
||||
}
|
||||
return jdkInfoList;
|
||||
}
|
||||
|
||||
private static List<String> jdkList(String listFileProp) throws IOException {
|
||||
String listFile = System.getProperty(listFileProp);
|
||||
System.out.println(listFileProp + "=" + listFile);
|
||||
if (listFile != null && new File(listFile).exists()) {
|
||||
return Files.lines(Paths.get(listFile))
|
||||
.filter(line -> { return !line.trim().isEmpty(); })
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if server is already launched, and returns server port.
|
||||
private static int waitForServerStarted()
|
||||
throws IOException, InterruptedException {
|
||||
System.out.print("Waiting for server");
|
||||
long deadline = System.currentTimeMillis() + Utils.TIMEOUT;
|
||||
int port;
|
||||
while ((port = getServerPort()) == -1
|
||||
&& System.currentTimeMillis() < deadline) {
|
||||
System.out.print(".");
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
// Retrieves the latest server port from port.log.
|
||||
private static int getServerPort() throws IOException {
|
||||
if (!new File(Utils.PORT_LOG).exists()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return Integer.valueOf(
|
||||
Files.lines(Paths.get(Utils.PORT_LOG)).findFirst().get());
|
||||
}
|
||||
|
||||
private static OutputAnalyzer runServer(String jdkPath,
|
||||
Map<String, String> props) {
|
||||
return ProcessUtils.java(jdkPath, props, Server.class);
|
||||
}
|
||||
|
||||
private static OutputAnalyzer runClient(String jdkPath,
|
||||
Map<String, String> props) {
|
||||
return ProcessUtils.java(jdkPath, props, Client.class);
|
||||
}
|
||||
|
||||
// Generates the test result report.
|
||||
private static boolean generateReport(List<TestCase> testCases)
|
||||
throws IOException {
|
||||
boolean failed = false;
|
||||
StringBuilder report = new StringBuilder();
|
||||
report.append(Utils.startHtml());
|
||||
report.append(Utils.tableStyle());
|
||||
report.append(Utils.startTable());
|
||||
report.append(Utils.row(
|
||||
"No.",
|
||||
"ServerJDK",
|
||||
"ClientJDK",
|
||||
"Protocol",
|
||||
"CipherSuite",
|
||||
"ClientAuth",
|
||||
"SNI",
|
||||
"ALPN",
|
||||
"Status"));
|
||||
for (int i = 0, size = testCases.size(); i < size; i++) {
|
||||
TestCase testCase = testCases.get(i);
|
||||
|
||||
report.append(Utils.row(
|
||||
Utils.anchorLink(
|
||||
Utils.TEST_LOG,
|
||||
testCase.toString(),
|
||||
i + ""),
|
||||
testCase.serverJdk.version,
|
||||
testCase.clientJdk.version,
|
||||
testCase.useCase.protocol.version,
|
||||
testCase.useCase.cipherSuite,
|
||||
Utils.boolToStr(
|
||||
testCase.useCase.clientAuth == ClientAuth.TRUE),
|
||||
Utils.boolToStr(
|
||||
testCase.useCase.serverName == ServerName.EXAMPLE),
|
||||
Utils.boolToStr(
|
||||
testCase.useCase.appProtocol == AppProtocol.EXAMPLE),
|
||||
testCase.getStatus()));
|
||||
failed = failed
|
||||
|| testCase.getStatus() == Status.FAIL
|
||||
|| testCase.getStatus() == Status.UNEXPECTED_SUCCESS;
|
||||
}
|
||||
report.append(Utils.endTable());
|
||||
report.append(Utils.endHtml());
|
||||
|
||||
generateFile("report.html", report.toString());
|
||||
return failed;
|
||||
}
|
||||
|
||||
private static void generateFile(String path, String content)
|
||||
throws IOException {
|
||||
try(FileWriter writer = new FileWriter(new File(path))) {
|
||||
writer.write(content);
|
||||
}
|
||||
}
|
||||
}
|
92
test/jdk/javax/net/ssl/compatibility/JdkInfo.java
Normal file
92
test/jdk/javax/net/ssl/compatibility/JdkInfo.java
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* It represents a JDK with some specific attributes.
|
||||
* If two JdkInfo instances have the same version value, the instances are
|
||||
* regarded as equivalent.
|
||||
*/
|
||||
public class JdkInfo {
|
||||
|
||||
public final String jdkPath;
|
||||
|
||||
public final String version;
|
||||
public final boolean supportsECKey;
|
||||
public final boolean supportsSNI;
|
||||
public final boolean supportsALPN;
|
||||
|
||||
public JdkInfo(String jdkPath) throws Throwable {
|
||||
this.jdkPath = jdkPath;
|
||||
|
||||
String output = jdkAttributes(jdkPath);
|
||||
if (output == null || output.trim().isEmpty()) {
|
||||
throw new RuntimeException(
|
||||
"Cannot determine the JDK attributes: " + jdkPath);
|
||||
}
|
||||
|
||||
String[] attributes = Utils.split(output, Utils.PARAM_DELIMITER);
|
||||
version = attributes[0].replaceAll(".*=", "");
|
||||
supportsECKey = Boolean.valueOf(attributes[1].replaceAll(".*=", ""));
|
||||
supportsSNI = Boolean.valueOf(attributes[2].replaceAll(".*=", ""));
|
||||
supportsALPN = Boolean.valueOf(attributes[3].replaceAll(".*=", ""));
|
||||
}
|
||||
|
||||
// Determines the specific attributes for the specified JDK.
|
||||
private static String jdkAttributes(String jdkPath) throws Throwable {
|
||||
return ProcessUtils.java(jdkPath, null, JdkUtils.class).getOutput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return version == null ? 0 : version.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
JdkInfo other = (JdkInfo) obj;
|
||||
if (version == null) {
|
||||
if (other.version != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!version.equals(other.version)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean supportsCipherSuite(CipherSuite cipherSuite) {
|
||||
JdkRelease jdkRelease = JdkRelease.getRelease(version);
|
||||
return cipherSuite.startJdk.sequence <= jdkRelease.sequence
|
||||
&& (cipherSuite.endJdk == null
|
||||
|| cipherSuite.endJdk.sequence >= jdkRelease.sequence);
|
||||
}
|
||||
}
|
58
test/jdk/javax/net/ssl/compatibility/JdkRelease.java
Normal file
58
test/jdk/javax/net/ssl/compatibility/JdkRelease.java
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JDK major versions.
|
||||
*/
|
||||
public enum JdkRelease {
|
||||
|
||||
JDK6(6, "1.6"),
|
||||
JDK7(7, "1.7"),
|
||||
JDK8(8, "1.8"),
|
||||
JDK9(9, "9"),
|
||||
JDK10(10, "10");
|
||||
|
||||
public final int sequence;
|
||||
public final String release;
|
||||
|
||||
private JdkRelease(int sequence, String release) {
|
||||
this.sequence = sequence;
|
||||
this.release = release;
|
||||
}
|
||||
|
||||
public static JdkRelease getRelease(String jdkVersion) {
|
||||
if (jdkVersion.startsWith(JDK6.release)) {
|
||||
return JDK6;
|
||||
} else if (jdkVersion.startsWith(JDK7.release)) {
|
||||
return JDK7;
|
||||
} else if (jdkVersion.startsWith(JDK8.release)) {
|
||||
return JDK8;
|
||||
} else if (jdkVersion.startsWith(JDK9.release)) {
|
||||
return JDK9;
|
||||
} else if (jdkVersion.startsWith(JDK10.release)) {
|
||||
return JDK10;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
88
test/jdk/javax/net/ssl/compatibility/JdkUtils.java
Normal file
88
test/jdk/javax/net/ssl/compatibility/JdkUtils.java
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.net.ssl.SSLParameters;
|
||||
|
||||
/*
|
||||
* This class is used for returning some specific JDK information.
|
||||
*/
|
||||
public class JdkUtils {
|
||||
|
||||
public static final String JAVA_RUNTIME_VERSION = "javaRuntimeVersion";
|
||||
public static final String SUPPORTS_EC_KEY = "supportsECKey";
|
||||
public static final String SUPPORTS_SNI = "supportsSNI";
|
||||
public static final String SUPPORTS_ALPN = "supportsALPN";
|
||||
|
||||
// Returns the JDK build version.
|
||||
public static String javaRuntimeVersion() {
|
||||
return System.getProperty("java.runtime.version");
|
||||
}
|
||||
|
||||
// Checks if EC key algorithm is supported by the JDK build.
|
||||
private static boolean supportsECKey() {
|
||||
boolean isSupported = true;
|
||||
try {
|
||||
KeyFactory.getInstance("EC");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
isSupported = false;
|
||||
}
|
||||
return isSupported;
|
||||
}
|
||||
|
||||
// Checks if SNI is supported by the JDK build.
|
||||
private static boolean supportsSNI() {
|
||||
boolean isSupported = true;
|
||||
try {
|
||||
SSLParameters.class.getMethod("getServerNames");
|
||||
} catch (NoSuchMethodException e) {
|
||||
isSupported = false;
|
||||
}
|
||||
return isSupported;
|
||||
}
|
||||
|
||||
// Checks if ALPN is supported by the JDK build.
|
||||
private static boolean supportsALPN() {
|
||||
boolean isSupported = true;
|
||||
try {
|
||||
SSLParameters.class.getMethod("getApplicationProtocols");
|
||||
} catch (NoSuchMethodException e) {
|
||||
isSupported = false;
|
||||
}
|
||||
return isSupported;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.print(Utils.join(Utils.PARAM_DELIMITER,
|
||||
attr(JAVA_RUNTIME_VERSION, javaRuntimeVersion()),
|
||||
attr(SUPPORTS_EC_KEY, supportsECKey()),
|
||||
attr(SUPPORTS_SNI, supportsSNI()),
|
||||
attr(SUPPORTS_ALPN, supportsALPN())));
|
||||
}
|
||||
|
||||
private static String attr(String name, Object value) {
|
||||
return name + "=" + String.valueOf(value);
|
||||
}
|
||||
}
|
252
test/jdk/javax/net/ssl/compatibility/Parameter.java
Normal file
252
test/jdk/javax/net/ssl/compatibility/Parameter.java
Normal file
@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A tagging interface that all TLS communication parameters must implement.
|
||||
*/
|
||||
public interface Parameter { }
|
||||
|
||||
/* The followings are TLS communication parameters. */
|
||||
|
||||
enum Protocol implements Parameter {
|
||||
|
||||
SSLV3_0(3, "SSLv3"),
|
||||
TLSV1_0(4, "TLSv1"),
|
||||
TLSV1_1(5, "TLSv1.1"),
|
||||
TLSV1_2(6, "TLSv1.2");
|
||||
|
||||
public final int sequence;
|
||||
public final String version;
|
||||
|
||||
private Protocol(int sequence, String version) {
|
||||
this.sequence = sequence;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
static Protocol getProtocol(String version) {
|
||||
for (Protocol protocol : values()) {
|
||||
if (protocol.version.equals(version)) {
|
||||
return protocol;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static Protocol[] getMandatoryValues() {
|
||||
return new Protocol[] { TLSV1_0, TLSV1_1, TLSV1_2 };
|
||||
}
|
||||
}
|
||||
|
||||
enum CipherSuite implements Parameter {
|
||||
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_RSA_WITH_AES_256_CBC_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA(),
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA(),
|
||||
TLS_RSA_WITH_AES_256_CBC_SHA(),
|
||||
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA(),
|
||||
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA(),
|
||||
TLS_DHE_RSA_WITH_AES_256_CBC_SHA(),
|
||||
TLS_DHE_DSS_WITH_AES_256_CBC_SHA(),
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_RSA_WITH_AES_128_CBC_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK7),
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA(),
|
||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(),
|
||||
TLS_RSA_WITH_AES_128_CBC_SHA(),
|
||||
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA(),
|
||||
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA(
|
||||
Protocol.SSLV3_0, JdkRelease.JDK7),
|
||||
TLS_DHE_RSA_WITH_AES_128_CBC_SHA(),
|
||||
TLS_DHE_DSS_WITH_AES_128_CBC_SHA(),
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_RSA_WITH_AES_256_GCM_SHA384(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_RSA_WITH_AES_128_GCM_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256(
|
||||
Protocol.TLSV1_2, JdkRelease.JDK8),
|
||||
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA(),
|
||||
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA(),
|
||||
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA(),
|
||||
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA(),
|
||||
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA(),
|
||||
TLS_ECDHE_RSA_WITH_RC4_128_SHA(),
|
||||
TLS_ECDH_ECDSA_WITH_RC4_128_SHA(),
|
||||
TLS_ECDH_RSA_WITH_RC4_128_SHA(),
|
||||
SSL_RSA_WITH_RC4_128_SHA(),
|
||||
SSL_RSA_WITH_3DES_EDE_CBC_SHA(),
|
||||
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA(
|
||||
Protocol.SSLV3_0, JdkRelease.JDK6),
|
||||
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA(
|
||||
Protocol.SSLV3_0, JdkRelease.JDK6),
|
||||
SSL_RSA_WITH_RC4_128_MD5(
|
||||
Protocol.SSLV3_0, JdkRelease.JDK6);
|
||||
|
||||
private static final boolean FULL_CIPHER_SUITES
|
||||
= Utils.getBoolProperty("fullCipherSuites");
|
||||
|
||||
final Protocol startProtocol;
|
||||
final Protocol endProtocol;
|
||||
|
||||
final JdkRelease startJdk;
|
||||
final JdkRelease endJdk;
|
||||
|
||||
private CipherSuite(
|
||||
Protocol startProtocol, Protocol endProtocol,
|
||||
JdkRelease startJdk, JdkRelease endJdk) {
|
||||
this.startProtocol = startProtocol;
|
||||
this.endProtocol = endProtocol;
|
||||
|
||||
this.startJdk = startJdk;
|
||||
this.endJdk = endJdk;
|
||||
}
|
||||
|
||||
private CipherSuite(Protocol startProtocol, JdkRelease startJdk) {
|
||||
this(startProtocol, null, startJdk, null);
|
||||
}
|
||||
|
||||
private CipherSuite() {
|
||||
this(Protocol.TLSV1_0, null, JdkRelease.JDK6, null);
|
||||
}
|
||||
|
||||
boolean supportedByProtocol(Protocol protocol) {
|
||||
return startProtocol.sequence <= protocol.sequence
|
||||
&& (endProtocol == null || endProtocol.sequence >= protocol.sequence);
|
||||
}
|
||||
|
||||
static CipherSuite[] getMandatoryValues() {
|
||||
return FULL_CIPHER_SUITES
|
||||
? values()
|
||||
: new CipherSuite[] {
|
||||
TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 };
|
||||
}
|
||||
|
||||
static CipherSuite getCipherSuite(String name) {
|
||||
for (CipherSuite cipherSuite : values()) {
|
||||
if (cipherSuite.name().equals(name)) {
|
||||
return cipherSuite;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
enum ClientAuth implements Parameter {
|
||||
|
||||
FALSE,
|
||||
TRUE;
|
||||
|
||||
static ClientAuth[] getMandatoryValues() {
|
||||
return new ClientAuth[] { TRUE };
|
||||
}
|
||||
}
|
||||
|
||||
enum ServerName implements Parameter {
|
||||
|
||||
NONE(null),
|
||||
EXAMPLE("www.example.com");
|
||||
|
||||
final String name;
|
||||
|
||||
private ServerName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
static ServerName[] getMandatoryValues() {
|
||||
return new ServerName[] { EXAMPLE };
|
||||
}
|
||||
}
|
||||
|
||||
enum AppProtocol implements Parameter {
|
||||
|
||||
NONE(null, null),
|
||||
EXAMPLE(new String[] { Utils.HTTP_2, Utils.HTTP_1_1 }, Utils.HTTP_2);
|
||||
|
||||
final String[] appProtocols;
|
||||
|
||||
// Expected negotiated application protocol
|
||||
final String negoAppProtocol;
|
||||
|
||||
private AppProtocol(String[] appProtocols, String negoAppProtocol) {
|
||||
this.appProtocols = appProtocols;
|
||||
this.negoAppProtocol = negoAppProtocol;
|
||||
}
|
||||
|
||||
static AppProtocol[] getMandatoryValues() {
|
||||
return new AppProtocol[] { EXAMPLE };
|
||||
}
|
||||
}
|
59
test/jdk/javax/net/ssl/compatibility/ProcessUtils.java
Normal file
59
test/jdk/javax/net/ssl/compatibility/ProcessUtils.java
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
/*
|
||||
* Utilities for executing java process.
|
||||
*/
|
||||
public class ProcessUtils {
|
||||
|
||||
private static final String TEST_CLASSES = System.getProperty("test.classes");
|
||||
|
||||
public static OutputAnalyzer java(String jdkPath, Map<String, String> props,
|
||||
Class<?> clazz) {
|
||||
List<String> cmds = new ArrayList<>();
|
||||
cmds.add(jdkPath + "/bin/java");
|
||||
|
||||
if (props != null) {
|
||||
for (Map.Entry<String, String> prop : props.entrySet()) {
|
||||
cmds.add("-D" + prop.getKey() + "=" + prop.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
cmds.add("-cp");
|
||||
cmds.add(TEST_CLASSES);
|
||||
cmds.add(clazz.getName());
|
||||
try {
|
||||
return ProcessTools.executeCommand(
|
||||
cmds.toArray(new String[cmds.size()]));
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException("Execute command failed: " + cmds, e);
|
||||
}
|
||||
}
|
||||
}
|
130
test/jdk/javax/net/ssl/compatibility/README
Normal file
130
test/jdk/javax/net/ssl/compatibility/README
Normal file
@ -0,0 +1,130 @@
|
||||
# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
|
||||
##### Summary #####
|
||||
This test is used to check the interop compatibility on JSSE among different
|
||||
JDK releases. The oldest version supported by the test is JDK 6. Some of Java
|
||||
source files, JdkUtils.java, Parameter.java, Server.java, and Client.java, use
|
||||
only JDK 6-compliant language features and APIs, in order to allowing different
|
||||
JDK releases can load and run associated classes.
|
||||
|
||||
##### Output #####
|
||||
The test can generate a report at $JTREG_WORKDIR/scratch/report.html to display
|
||||
the key information for each case. It also outputs all of details on both of
|
||||
server and client sides to a separated file at $JTREG_WORKDIR/scratch/test.html.
|
||||
|
||||
##### Report Columns #####
|
||||
No.
|
||||
A sequence number. It contains a hyper link to the corresponding details
|
||||
in $JTREG_WORKDIR/scratch/test.html.
|
||||
|
||||
ServerJDK
|
||||
The version of the JDK that acts as server.
|
||||
|
||||
ClientJDK
|
||||
The version of the JDK that acts as client.
|
||||
|
||||
Protocol
|
||||
The TLS protocol version.
|
||||
|
||||
CipherSuite
|
||||
The only enabled cipher suite on both of server and client.
|
||||
|
||||
ClientAuth
|
||||
If the client authentication is checked, the value is "Y"; otherwise, "N".
|
||||
|
||||
SNI
|
||||
If the SNI is checked, the value is "Y"; otherwise, "N".
|
||||
|
||||
ALPN
|
||||
If the ALPN is checked, the value is "Y"; otherwise, "N".
|
||||
|
||||
Status
|
||||
It indicates the communication status for a test case.
|
||||
There are three status:
|
||||
SUCCESS: Communication succeed as expected.
|
||||
UNEXPECTED_SUCCESS: Communication succeed as unexpected.
|
||||
FAIL: Communication fails with unexpected failure.
|
||||
EXPECTED_FAIL: Communication fails with expected failure.
|
||||
Please note that, if a case finishes as status UNEXPECTED_SUCCESS or FAIL,
|
||||
that means the case fails. Any failed case results in the test goes to fail.
|
||||
|
||||
##### Usage #####
|
||||
jtreg [-options] \
|
||||
[-Ddebug=<true|false>] \
|
||||
[-DfullCases=<true|false>] \
|
||||
[-DfullCipherSuites=<true|false>] \
|
||||
[-DjdkListFile=</path/to/jdkListFile>] \
|
||||
$JDK_WORKSPACE/test/jdk/javax/net/ssl/compatibility/Compatibility.java
|
||||
|
||||
Besides the common jtreg options, like -jdk, this test introduces some more
|
||||
properties:
|
||||
debug
|
||||
It indicates if the test enable -Djavax.net.ssl=debug. This is a boolean
|
||||
property, and the default value is false.
|
||||
It is not mandatory.
|
||||
|
||||
fullCases
|
||||
It indicates if testing the full or mandatory set of parameter values.
|
||||
Every parameter provides a mandatory value set that must be covered.
|
||||
For more details about the parameter value sets, please see Parameter.java.
|
||||
This is a boolean property, and the default value is false.
|
||||
It is not mandatory.
|
||||
|
||||
fullCipherSuites
|
||||
It indicates if testing the full or mandatory set of cipher suites.
|
||||
For more details about the specific cipher suite sets, see CipherSuite in
|
||||
Parameter.java.
|
||||
This is a boolean property, and the default value is false.
|
||||
It is not mandatory.
|
||||
|
||||
jdkListFile
|
||||
It indicate the path of a file, which lists the absolute paths of different
|
||||
JDK builds. If no this property, the current testing JDK, specified by JTREG
|
||||
option -jdk, is used as the testing JDK.
|
||||
It is not mandatory.
|
||||
|
||||
##### Usage Examples #####
|
||||
Example 1
|
||||
$ jtreg -jdk:/path/to/latest/jdk \
|
||||
$JDK_WS/jdk/test/javax/net/ssl/compatibility/Compatibility.java
|
||||
This example doesn't specify any property introduced by the test. That means
|
||||
it uses the current testing JDK, namely /path/to/latest/jdk, as server and
|
||||
client. It doesn't output any debug log, and tests only mandatory parameter
|
||||
value sets.
|
||||
|
||||
Example 2
|
||||
$ cat /path/to/jdkList
|
||||
/path/to/jdk6
|
||||
/path/to/jdk7
|
||||
/path/to/jdk8
|
||||
/path/to/jdk9
|
||||
/path/to/jdk10
|
||||
|
||||
$ jtreg -jdk:/path/to/latest/jdk \
|
||||
-Ddebug=true \
|
||||
-DfullCipherSuites=true \
|
||||
-DjdkListFile=/path/to/jdkList \
|
||||
$JDK_WS/jdk/test/javax/net/ssl/compatibility/Compatibility.java
|
||||
The above example uses a file "/path/to/jdkList" to contain the paths of local
|
||||
different JDK builds through 6 to 10. The execution uses each of JDK builds as
|
||||
server and client respectively. And it enables SSL debug flag, and tests the
|
||||
full parameter value set.
|
171
test/jdk/javax/net/ssl/compatibility/Server.java
Normal file
171
test/jdk/javax/net/ssl/compatibility/Server.java
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import javax.net.ssl.SSLServerSocket;
|
||||
import javax.net.ssl.SSLServerSocketFactory;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
/*
|
||||
* A simple SSL socket server.
|
||||
*/
|
||||
public class Server {
|
||||
|
||||
private final SSLServerSocket serverSocket;
|
||||
|
||||
public Server(SSLContext context, int port) throws Exception {
|
||||
SSLServerSocketFactory serverFactory = context.getServerSocketFactory();
|
||||
serverSocket = (SSLServerSocket) serverFactory.createServerSocket(port);
|
||||
serverSocket.setSoTimeout(Utils.TIMEOUT);
|
||||
}
|
||||
|
||||
public Server(Cert[] certs, int port) throws Exception {
|
||||
this(Utils.createSSLContext(certs), port);
|
||||
}
|
||||
|
||||
public Server(Cert[] certs) throws Exception {
|
||||
this(certs, 0);
|
||||
}
|
||||
|
||||
private void setEnabledCipherSuites(String... cipherSuites) {
|
||||
serverSocket.setEnabledCipherSuites(cipherSuites);
|
||||
}
|
||||
|
||||
private void setEnabledProtocols(String... protocols) {
|
||||
serverSocket.setEnabledProtocols(protocols);
|
||||
}
|
||||
|
||||
private void setNeedClientAuth(boolean needClientAuth) {
|
||||
serverSocket.setNeedClientAuth(needClientAuth);
|
||||
}
|
||||
|
||||
private void setApplicationProtocols(String... protocols) {
|
||||
SSLParameters params = serverSocket.getSSLParameters();
|
||||
params.setApplicationProtocols(protocols);
|
||||
serverSocket.setSSLParameters(params);
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return serverSocket.getLocalPort();
|
||||
}
|
||||
|
||||
private void accept() throws IOException {
|
||||
SSLSocket socket = null;
|
||||
try {
|
||||
socket = (SSLSocket) serverSocket.accept();
|
||||
|
||||
InputStream in = socket.getInputStream();
|
||||
in.read();
|
||||
|
||||
OutputStream out = socket.getOutputStream();
|
||||
out.write('S');
|
||||
out.flush();
|
||||
} finally {
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
serverSocket.close();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
System.out.println("----- Server start -----");
|
||||
String protocol = System.getProperty(Utils.PROP_PROTOCOL);
|
||||
String cipherSuite = System.getProperty(Utils.PROP_CIPHER_SUITE);
|
||||
boolean clientAuth
|
||||
= Utils.getBoolProperty(Utils.PROP_CLIENT_AUTH);
|
||||
String appProtocols = System.getProperty(Utils.PROP_APP_PROTOCOLS);
|
||||
boolean supportsALPN
|
||||
= Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_SERVER);
|
||||
boolean negativeCase
|
||||
= Utils.getBoolProperty(Utils.PROP_NEGATIVE_CASE_ON_SERVER);
|
||||
|
||||
System.out.println(Utils.join(Utils.PARAM_DELIMITER,
|
||||
"ServerJDK=" + System.getProperty(Utils.PROP_SERVER_JDK),
|
||||
"Protocol=" + protocol,
|
||||
"CipherSuite=" + cipherSuite,
|
||||
"ClientAuth=" + clientAuth,
|
||||
"AppProtocols=" + appProtocols));
|
||||
|
||||
Status status = Status.SUCCESS;
|
||||
Server server = null;
|
||||
try {
|
||||
server = new Server(Cert.getCerts(cipherSuite));
|
||||
System.out.println("port=" + server.getPort());
|
||||
server.setNeedClientAuth(clientAuth);
|
||||
server.setEnabledProtocols(protocol);
|
||||
server.setEnabledCipherSuites(cipherSuite);
|
||||
if (appProtocols != null) {
|
||||
if (supportsALPN) {
|
||||
server.setApplicationProtocols(
|
||||
Utils.split(appProtocols, Utils.VALUE_DELIMITER));
|
||||
} else {
|
||||
System.out.println(
|
||||
"Ignored due to server doesn't support ALPN.");
|
||||
}
|
||||
}
|
||||
|
||||
savePort(server.getPort());
|
||||
server.accept();
|
||||
|
||||
status = negativeCase ? Status.UNEXPECTED_SUCCESS : Status.SUCCESS;
|
||||
} catch (Exception exception) {
|
||||
status = Utils.handleException(exception, negativeCase);
|
||||
} finally {
|
||||
if (server != null) {
|
||||
server.close();
|
||||
}
|
||||
|
||||
// Cleanups port.log.
|
||||
File file = new File(Utils.PORT_LOG);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("STATUS: " + status);
|
||||
System.out.println("----- Server end -----");
|
||||
}
|
||||
|
||||
private static void savePort(int port) throws IOException {
|
||||
FileWriter writer = null;
|
||||
try {
|
||||
writer = new FileWriter(new File(Utils.PORT_LOG));
|
||||
writer.write(port + "");
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
30
test/jdk/javax/net/ssl/compatibility/Status.java
Normal file
30
test/jdk/javax/net/ssl/compatibility/Status.java
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test case result status.
|
||||
*/
|
||||
public enum Status {
|
||||
|
||||
SUCCESS, UNEXPECTED_SUCCESS, FAIL, EXPECTED_FAIL, TIMEOUT;
|
||||
}
|
64
test/jdk/javax/net/ssl/compatibility/TestCase.java
Normal file
64
test/jdk/javax/net/ssl/compatibility/TestCase.java
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A test case for a specific TLS communication use case between two JDKs.
|
||||
*/
|
||||
public class TestCase {
|
||||
|
||||
public final JdkInfo serverJdk;
|
||||
public final JdkInfo clientJdk;
|
||||
public final UseCase useCase;
|
||||
|
||||
public final boolean negativeCaseOnServer;
|
||||
public final boolean negativeCaseOnClient;
|
||||
|
||||
private Status status;
|
||||
|
||||
public TestCase(JdkInfo serverJdk, JdkInfo clientJdk, UseCase useCase) {
|
||||
this.serverJdk = serverJdk;
|
||||
this.clientJdk = clientJdk;
|
||||
this.useCase = useCase;
|
||||
|
||||
negativeCaseOnServer = useCase.negativeCase
|
||||
|| !serverJdk.supportsCipherSuite(useCase.cipherSuite);
|
||||
negativeCaseOnClient = useCase.negativeCase
|
||||
|| !clientJdk.supportsCipherSuite(useCase.cipherSuite);
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Status status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Utils.join(Utils.PARAM_DELIMITER,
|
||||
"ServerJDK=" + serverJdk.version,
|
||||
"ClientJDK=" + clientJdk.version,
|
||||
useCase.toString());
|
||||
}
|
||||
}
|
107
test/jdk/javax/net/ssl/compatibility/UseCase.java
Normal file
107
test/jdk/javax/net/ssl/compatibility/UseCase.java
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* The TLS communication use case.
|
||||
*/
|
||||
public class UseCase {
|
||||
|
||||
private static final boolean FULL_CASES
|
||||
= Utils.getBoolProperty("fullCases");
|
||||
|
||||
private static final Parameter[][] PARAMS = new Parameter[][] {
|
||||
FULL_CASES ? Protocol.values() : Protocol.getMandatoryValues(),
|
||||
FULL_CASES ? CipherSuite.values() : CipherSuite.getMandatoryValues(),
|
||||
FULL_CASES ? ClientAuth.values() : ClientAuth.getMandatoryValues(),
|
||||
FULL_CASES ? ServerName.values() : ServerName.getMandatoryValues(),
|
||||
FULL_CASES ? AppProtocol.values() : AppProtocol.getMandatoryValues() };
|
||||
|
||||
public final Protocol protocol;
|
||||
public final CipherSuite cipherSuite;
|
||||
public final ClientAuth clientAuth;
|
||||
public final ServerName serverName;
|
||||
public final AppProtocol appProtocol;
|
||||
|
||||
public final boolean negativeCase;
|
||||
|
||||
public UseCase(
|
||||
Protocol protocol,
|
||||
CipherSuite cipherSuite,
|
||||
ClientAuth clientAuth,
|
||||
ServerName serverName,
|
||||
AppProtocol appProtocol) {
|
||||
this.protocol = protocol;
|
||||
this.cipherSuite = cipherSuite;
|
||||
this.clientAuth = clientAuth;
|
||||
this.serverName = serverName;
|
||||
this.appProtocol = appProtocol;
|
||||
|
||||
negativeCase = !cipherSuite.supportedByProtocol(protocol);
|
||||
}
|
||||
|
||||
// JDK 6 doesn't support EC key algorithm.
|
||||
public boolean ignoredByJdk(JdkInfo jdkInfo) {
|
||||
return cipherSuite.name().contains("_EC") && !jdkInfo.supportsECKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Utils.join(Utils.PARAM_DELIMITER,
|
||||
"Protocol=" + protocol.version,
|
||||
"CipherSuite=" + cipherSuite,
|
||||
"ClientAuth=" + clientAuth,
|
||||
"ServerName=" + serverName,
|
||||
"AppProtocols=" + appProtocol);
|
||||
}
|
||||
|
||||
public static List<UseCase> getAllUseCases() {
|
||||
List<UseCase> useCases = new ArrayList<>();
|
||||
getUseCases(PARAMS, 0, new Parameter[PARAMS.length], useCases);
|
||||
return useCases;
|
||||
}
|
||||
|
||||
private static void getUseCases(Parameter[][] params, int index,
|
||||
Parameter[] currentValues, List<UseCase> useCases) {
|
||||
if (index == params.length) {
|
||||
Protocol protocol = (Protocol) currentValues[0];
|
||||
CipherSuite cipherSuite = (CipherSuite) currentValues[1];
|
||||
|
||||
UseCase useCase = new UseCase(
|
||||
protocol,
|
||||
cipherSuite,
|
||||
(ClientAuth) currentValues[2],
|
||||
(ServerName) currentValues[3],
|
||||
(AppProtocol) currentValues[4]);
|
||||
useCases.add(useCase);
|
||||
} else {
|
||||
Parameter[] values = params[index];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
currentValues[index] = values[i];
|
||||
getUseCases(params, index + 1, currentValues, useCases);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
282
test/jdk/javax/net/ssl/compatibility/Utils.java
Normal file
282
test/jdk/javax/net/ssl/compatibility/Utils.java
Normal file
@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyStore;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
/*
|
||||
* Utilities for testing.
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
/* ***** Properties ***** */
|
||||
public static final String PROP_PORT = "test.port";
|
||||
public static final String PROP_PROTOCOL = "test.protocol";
|
||||
public static final String PROP_CIPHER_SUITE = "test.cipher.suite";
|
||||
public static final String PROP_CLIENT_AUTH = "test.client.auth";
|
||||
public static final String PROP_SERVER_JDK = "test.server.jdk";
|
||||
public static final String PROP_CLIENT_JDK = "test.client.jdk";
|
||||
public static final String PROP_SERVER_NAME = "test.server.name";
|
||||
public static final String PROP_APP_PROTOCOLS
|
||||
= "test.app.protocols";
|
||||
public static final String PROP_NEGO_APP_PROTOCOL
|
||||
= "test.negotiated.app.protocol";
|
||||
public static final String PROP_SUPPORTS_SNI_ON_SERVER
|
||||
= "test.supports.sni.on.server";
|
||||
public static final String PROP_SUPPORTS_SNI_ON_CLIENT
|
||||
= "test.supports.sni.on.client";
|
||||
public static final String PROP_SUPPORTS_ALPN_ON_SERVER
|
||||
= "test.supports.alpn.on.server";
|
||||
public static final String PROP_SUPPORTS_ALPN_ON_CLIENT
|
||||
= "test.supports.alpn.on.client";
|
||||
public static final String PROP_NEGATIVE_CASE_ON_SERVER
|
||||
= "test.negative.case.on.server";
|
||||
public static final String PROP_NEGATIVE_CASE_ON_CLIENT
|
||||
= "test.negative.case.on.client";
|
||||
|
||||
public static final int TIMEOUT = 10000;
|
||||
public static final char[] PASSWORD = "testpass".toCharArray();
|
||||
|
||||
public static final String TEST_LOG = "test.html";
|
||||
public static final String PORT_LOG = "port";
|
||||
|
||||
public static final String HTTP_2 = "h2";
|
||||
public static final String HTTP_1_1 = "http/1.1";
|
||||
|
||||
public static final String PARAM_DELIMITER = ";";
|
||||
public static final String VALUE_DELIMITER = ",";
|
||||
|
||||
/*
|
||||
* Creates SSL context with the specified certificate.
|
||||
*/
|
||||
public static SSLContext createSSLContext(Cert... certs) throws Exception {
|
||||
KeyStore trustStore = KeyStore.getInstance("JKS");
|
||||
trustStore.load(null, null);
|
||||
for (int i = 0; i < certs.length; i++) {
|
||||
trustStore.setCertificateEntry("trust-" + certs[i].name(),
|
||||
createCert(certs[i]));
|
||||
}
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
|
||||
tmf.init(trustStore);
|
||||
|
||||
KeyStore keyStore = KeyStore.getInstance("JKS");
|
||||
keyStore.load(null, null);
|
||||
for (int i = 0; i < certs.length; i++) {
|
||||
PrivateKey privKey = createKey(certs[i]);
|
||||
keyStore.setKeyEntry("cert-" + certs[i].name(), privKey, PASSWORD,
|
||||
new Certificate[] { createCert(certs[i]) });
|
||||
}
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
|
||||
kmf.init(keyStore, PASSWORD);
|
||||
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
||||
return context;
|
||||
}
|
||||
|
||||
private static Certificate createCert(Cert cert) throws IOException {
|
||||
try {
|
||||
CertificateFactory certFactory
|
||||
= CertificateFactory.getInstance("X.509");
|
||||
return certFactory.generateCertificate(
|
||||
new ByteArrayInputStream(cert.certMaterials.getBytes()));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Create key failed: " + cert, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static PrivateKey createKey(Cert cert)
|
||||
throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(
|
||||
hexToBytes(cert.privKeyMaterials));
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(
|
||||
getKeyAlgorithm(cert.signatureAlgorithm));
|
||||
PrivateKey privKey = keyFactory.generatePrivate(privKeySpec);
|
||||
return privKey;
|
||||
}
|
||||
|
||||
private static String getKeyAlgorithm(
|
||||
SignatureAlgorithm signatureAlgorithm) {
|
||||
String signatureAlogrithmName = signatureAlgorithm.name();
|
||||
return signatureAlogrithmName.equals(SignatureAlgorithm.ECDSA.name())
|
||||
? "EC"
|
||||
: signatureAlogrithmName;
|
||||
}
|
||||
|
||||
public static byte[] hexToBytes(String hex) {
|
||||
if (hex == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int length = hex.length();
|
||||
if (length % 2 != 0) {
|
||||
throw new IllegalArgumentException("Hex format is wrong.");
|
||||
}
|
||||
|
||||
byte[] bytes = new byte[length / 2];
|
||||
for (int i = 0; i < length; i += 2) {
|
||||
bytes[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
|
||||
+ Character.digit(hex.charAt(i + 1), 16));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static String join(String delimiter, String... values) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
if (values != null && values.length > 0) {
|
||||
for (int i = 0; i < values.length - 1; i++) {
|
||||
result.append(values[i]).append(delimiter);
|
||||
}
|
||||
result.append(values[values.length - 1]);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String[] split(String str, String delimiter) {
|
||||
return str == null ? new String[0] : str.split(delimiter);
|
||||
}
|
||||
|
||||
public static String boolToStr(boolean bool) {
|
||||
return bool ? "Y" : "N";
|
||||
}
|
||||
|
||||
public static boolean getBoolProperty(String prop) {
|
||||
return Boolean.valueOf(System.getProperty(prop));
|
||||
}
|
||||
|
||||
public static Status handleException(Exception exception,
|
||||
boolean negativeCase) {
|
||||
Status status;
|
||||
if ((exception instanceof SSLHandshakeException
|
||||
|| exception instanceof IllegalArgumentException)
|
||||
&& negativeCase) {
|
||||
System.out.println("Expected exception: " + exception);
|
||||
status = Status.EXPECTED_FAIL;
|
||||
} else if (exception instanceof SocketTimeoutException) {
|
||||
status = Status.TIMEOUT;
|
||||
} else {
|
||||
exception.printStackTrace(System.out);
|
||||
status = Status.FAIL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* The HTML-related constants and methods. */
|
||||
|
||||
private static final String STYLE
|
||||
= "style=\"font-family: Courier New; "
|
||||
+ "font-size: 12px; "
|
||||
+ "white-space: pre-wrap\"";
|
||||
|
||||
private static final String TABLE_STYLE
|
||||
= "#test { font-family: \"Courier New\"; font-size: 12px; border-collapse: collapse; }\n"
|
||||
+ "#test td { border: 1px solid #ddd; padding: 4px; }\n"
|
||||
+ "#test tr:nth-child(odd) { background-color: #f2f2f2; }";
|
||||
|
||||
public static String row(Object... values) {
|
||||
StringBuilder row = new StringBuilder();
|
||||
row.append(startTr());
|
||||
for (Object value : values) {
|
||||
row.append(startTd());
|
||||
row.append(value);
|
||||
row.append(endTd());
|
||||
}
|
||||
row.append(endTr());
|
||||
return row.toString();
|
||||
}
|
||||
|
||||
public static String startHtml() {
|
||||
return startTag("html");
|
||||
}
|
||||
|
||||
public static String endHtml() {
|
||||
return endTag("html");
|
||||
}
|
||||
|
||||
public static String startPre() {
|
||||
return startTag("pre " + STYLE);
|
||||
}
|
||||
|
||||
public static String endPre() {
|
||||
return endTag("pre");
|
||||
}
|
||||
|
||||
public static String anchorName(String name, String text) {
|
||||
return "<a name=" + name + ">" + text + "</a>";
|
||||
}
|
||||
|
||||
public static String anchorLink(String file, String anchorName,
|
||||
String text) {
|
||||
return "<a href=" + file + "#" + anchorName + ">" + text + "</a>";
|
||||
}
|
||||
|
||||
public static String tableStyle() {
|
||||
return startTag("style") + TABLE_STYLE +endTag("style");
|
||||
}
|
||||
|
||||
public static String startTable() {
|
||||
return startTag("table id=\"test\"");
|
||||
}
|
||||
|
||||
public static String endTable() {
|
||||
return endTag("table");
|
||||
}
|
||||
|
||||
private static String startTr() {
|
||||
return startTag("tr");
|
||||
}
|
||||
|
||||
private static String endTr() {
|
||||
return endTag("tr");
|
||||
}
|
||||
|
||||
private static String startTd() {
|
||||
return startTag("td");
|
||||
}
|
||||
|
||||
private static String endTd() {
|
||||
return endTag("td");
|
||||
}
|
||||
|
||||
private static String startTag(String tag) {
|
||||
return "<" + tag + ">";
|
||||
}
|
||||
|
||||
private static String endTag(String tag) {
|
||||
return "</" + tag + ">";
|
||||
}
|
||||
}
|
2
test/jdk/javax/net/ssl/compatibility/java.security
Normal file
2
test/jdk/javax/net/ssl/compatibility/java.security
Normal file
@ -0,0 +1,2 @@
|
||||
jdk.certpath.disabledAlgorithms=
|
||||
jdk.tls.disabledAlgorithms=
|
@ -24,7 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 4494033 7028815 7052425 8007338 8023608 8008164 8016549 8072461 8154261 8162363 8160196 8151743 8177417
|
||||
* 8175218 8176452 8181215 8182263 8183511 8169819 8183037
|
||||
* 8175218 8176452 8181215 8182263 8183511 8169819 8183037 8185369
|
||||
* @summary Run tests on doclet stylesheet.
|
||||
* @author jamieh
|
||||
* @library ../lib
|
||||
@ -50,16 +50,6 @@ public class TestStylesheet extends JavadocTester {
|
||||
// TODO: most of this test seems a bit silly, since javadoc is simply
|
||||
// copying in the stylesheet from the source directory
|
||||
checkOutput("stylesheet.css", true,
|
||||
"/* Javadoc style sheet */",
|
||||
"/*\n"
|
||||
+ "Overall document style\n"
|
||||
+ "*/",
|
||||
"/*\n"
|
||||
+ "Heading styles\n"
|
||||
+ "*/",
|
||||
"/*\n"
|
||||
+ "Navigation bar styles\n"
|
||||
+ "*/",
|
||||
"body {\n"
|
||||
+ " background-color:#ffffff;\n"
|
||||
+ " color:#353833;\n"
|
||||
@ -173,8 +163,8 @@ public class TestStylesheet extends JavadocTester {
|
||||
+ " position:relative;\n"
|
||||
+ " padding-top:129px;\n"
|
||||
+ " margin-top:-129px;\n"
|
||||
+ "}\n"
|
||||
+ ".searchTagResult:before, .searchTagResult:target {\n"
|
||||
+ "}",
|
||||
".searchTagResult:before, .searchTagResult:target {\n"
|
||||
+ " color:red;\n"
|
||||
+ "}",
|
||||
"a[href]:hover, a[href]:focus {\n"
|
||||
|
@ -188,7 +188,7 @@ public class ForwardReferenceImportTest extends KullaTesting {
|
||||
DiagCheck.DIAG_ERROR,
|
||||
added(VALID),
|
||||
ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null)));
|
||||
assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.already.defined.static.single.import");
|
||||
assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.already.defined.single.import");
|
||||
assertActiveKeys();
|
||||
assertDrop(list,
|
||||
ste(list, VALID, DROPPED, true, null),
|
||||
|
@ -1,14 +1,14 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 7101822
|
||||
* @bug 7101822 8133616
|
||||
* @summary Check the when clashing types are imported through an ordinary and static import,
|
||||
* the compile-time error is properly reported.
|
||||
* @compile/fail/ref=NonStatic2StaticImportClash.out -XDrawDiagnostics NonStatic2StaticImportClash.java p1/A1.java p2/A2.java
|
||||
*
|
||||
*/
|
||||
|
||||
import p1.A1.f;
|
||||
import static p2.A2.f;
|
||||
import static p1.A1.f;
|
||||
import p2.A2.f;
|
||||
|
||||
public class NonStatic2StaticImportClash {
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 7101822
|
||||
* @bug 7101822 8133616
|
||||
* @summary Check the when clashing types are imported through an ordinary and static import,
|
||||
* the compile-time error is properly reported.
|
||||
* @compile/fail/ref=Static2NonStaticImportClash.out -XDrawDiagnostics Static2NonStaticImportClash.java p1/A1.java p2/A2.java
|
||||
*
|
||||
*/
|
||||
|
||||
import static p2.A2.f;
|
||||
import p1.A1.f;
|
||||
import p2.A2.f;
|
||||
import static p1.A1.f;
|
||||
|
||||
public class Static2NonStaticImportClash {
|
||||
}
|
||||
|
17
test/langtools/tools/javac/analyzer/LambdaWithMethod.java
Normal file
17
test/langtools/tools/javac/analyzer/LambdaWithMethod.java
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8191981
|
||||
* @compile/fail/ref=LambdaWithMethod.out -Werror -XDrawDiagnostics -XDfind=lambda LambdaWithMethod.java
|
||||
*/
|
||||
|
||||
public class LambdaWithMethod {
|
||||
public static void run(Runnable r) {
|
||||
run(new Runnable() {
|
||||
public void run() {
|
||||
put(get());
|
||||
}
|
||||
});
|
||||
}
|
||||
private static String get() { return null; }
|
||||
private static void put(String i) {}
|
||||
}
|
4
test/langtools/tools/javac/analyzer/LambdaWithMethod.out
Normal file
4
test/langtools/tools/javac/analyzer/LambdaWithMethod.out
Normal file
@ -0,0 +1,4 @@
|
||||
LambdaWithMethod.java:9:28: compiler.warn.potential.lambda.found
|
||||
- compiler.err.warnings.and.werror
|
||||
1 error
|
||||
1 warning
|
@ -23,5 +23,5 @@
|
||||
|
||||
// key: compiler.err.already.defined.static.single.import
|
||||
|
||||
import p.E1.A;
|
||||
import static p.E2.A;
|
||||
import static p.E1.A;
|
||||
import p.E2.A;
|
||||
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8178427
|
||||
* @summary NPE in Infer$CheckUpperBounds
|
||||
* @compile T8178427.java
|
||||
*/
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.function.*;
|
||||
import java.util.stream.*;
|
||||
|
||||
abstract class X {
|
||||
public interface N<K, V> {
|
||||
Stream<V> getValues();
|
||||
}
|
||||
|
||||
abstract <K, V> N<K, V> c();
|
||||
|
||||
abstract <T, K, V, M extends N<K, V>> Collector<T, ?, M> f(
|
||||
Function<? super T, ? extends K> k,
|
||||
Function<? super T, ? extends Stream<? extends V>> v,
|
||||
Supplier<M> multimapSupplier);
|
||||
|
||||
void m(Map<String, N<?, ?>> c, ExecutorService s) {
|
||||
s.submit(() -> {
|
||||
return c.entrySet().parallelStream()
|
||||
.collect(f(Map.Entry::getKey, e -> e.getValue().getValues(), this::c));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8191234
|
||||
* @summary Test TypeKind visitors on pseudo types.
|
||||
* @library /tools/javac/lib
|
||||
* @modules java.compiler
|
||||
* @build JavacTestingAbstractProcessor TestTypeKindVisitors
|
||||
* @compile -processor TestTypeKindVisitors -proc:only TestTypeKindVisitors.java
|
||||
*/
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.*;
|
||||
import javax.annotation.processing.*;
|
||||
import javax.lang.model.element.*;
|
||||
import javax.lang.model.type.*;
|
||||
import javax.lang.model.util.*;
|
||||
import static javax.lang.model.SourceVersion.*;
|
||||
|
||||
public class TestTypeKindVisitors extends JavacTestingAbstractProcessor {
|
||||
@Override
|
||||
public boolean process(Set<? extends TypeElement> tes,
|
||||
RoundEnvironment round) {
|
||||
if (round.processingOver())
|
||||
return true;
|
||||
|
||||
List<NoType> tradNoTypes = List.of(types.getNoType(TypeKind.NONE),
|
||||
types.getNoType(TypeKind.VOID),
|
||||
getPackageNoType());
|
||||
NoType moduleNoType = getModuleNoType();
|
||||
|
||||
// For KindVisitors based on 6, 7, and 8
|
||||
for (TypeVisitor<TypeKind, String> visitor : getVisitors()) {
|
||||
System.out.println(visitor.getClass().getSuperclass().getName());
|
||||
|
||||
for (NoType noType : tradNoTypes) {
|
||||
System.out.println("\t" + noType.toString());
|
||||
checkTypeKind(noType.getKind(), visitor.visit(noType));
|
||||
}
|
||||
|
||||
if (RELEASE_9.compareTo(visitor.getClass().getSuperclass().
|
||||
getAnnotation(SupportedSourceVersion.class).
|
||||
value()) > 0) {
|
||||
try {
|
||||
System.out.println("\t" + moduleNoType.toString());
|
||||
visitor.visit(moduleNoType);
|
||||
} catch (UnknownTypeException ute) {
|
||||
; // Expected
|
||||
}
|
||||
} else {
|
||||
checkTypeKind(moduleNoType.getKind(), visitor.visit(moduleNoType));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private NoType getPackageNoType() {
|
||||
TypeMirror type = elements.getPackageElement("java.lang").asType();
|
||||
checkTypeKind(TypeKind.PACKAGE, type.getKind());
|
||||
return (NoType) type;
|
||||
}
|
||||
|
||||
private NoType getModuleNoType() {
|
||||
TypeMirror type = elements.getModuleElement("java.base").asType();
|
||||
checkTypeKind(TypeKind.MODULE, type.getKind());
|
||||
return (NoType) type;
|
||||
}
|
||||
|
||||
private void checkTypeKind(TypeKind expected, TypeKind retreived) {
|
||||
if (retreived != expected)
|
||||
throw new AssertionError("Unexpected type kind " + retreived);
|
||||
}
|
||||
|
||||
List<TypeVisitor<TypeKind, String>> getVisitors() {
|
||||
return List.of(new TypeKindVisitor6<>(null) {
|
||||
@Override
|
||||
protected TypeKind defaultAction(TypeMirror e, String p) {
|
||||
throw new AssertionError("Should not reach");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeKind visitNoTypeAsVoid(NoType t, String p) {
|
||||
return t.getKind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeKind visitNoTypeAsNone(NoType t, String p) {
|
||||
return t.getKind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeKind visitNoTypeAsPackage(NoType t, String p) {
|
||||
return t.getKind();
|
||||
}
|
||||
// Leave default behavior for a NoType module
|
||||
},
|
||||
|
||||
new TypeKindVisitor7<>(null){
|
||||
@Override
|
||||
protected TypeKind defaultAction(TypeMirror e, String p) {
|
||||
throw new AssertionError("Should not reach");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeKind visitNoTypeAsVoid(NoType t, String p) {
|
||||
return t.getKind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeKind visitNoTypeAsNone(NoType t, String p) {
|
||||
return t.getKind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeKind visitNoTypeAsPackage(NoType t, String p) {
|
||||
return t.getKind();
|
||||
}
|
||||
// Leave default behavior for a NoType module
|
||||
|
||||
},
|
||||
|
||||
new TypeKindVisitor8<>(null){
|
||||
@Override
|
||||
protected TypeKind defaultAction(TypeMirror e, String p) {
|
||||
throw new AssertionError("Should not reach");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeKind visitNoTypeAsVoid(NoType t, String p) {
|
||||
return t.getKind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeKind visitNoTypeAsNone(NoType t, String p) {
|
||||
return t.getKind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeKind visitNoTypeAsPackage(NoType t, String p) {
|
||||
return t.getKind();
|
||||
}
|
||||
// Leave default behavior for a NoType module
|
||||
|
||||
},
|
||||
|
||||
new TypeKindVisitor9<>(null){
|
||||
@Override
|
||||
protected TypeKind defaultAction(TypeMirror e, String p) {
|
||||
throw new AssertionError("Should not reach");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeKind visitNoTypeAsVoid(NoType t, String p) {
|
||||
return t.getKind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeKind visitNoTypeAsNone(NoType t, String p) {
|
||||
return t.getKind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeKind visitNoTypeAsPackage(NoType t, String p) {
|
||||
return t.getKind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeKind visitNoTypeAsModule(NoType t, String p) {
|
||||
return t.getKind();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -240,17 +240,26 @@ public class MultiReleaseJar {
|
||||
cmds[0] = cmdPath.resolve(cmds[0]).toString();
|
||||
ProcessBuilder pb = new ProcessBuilder(cmds);
|
||||
pb.directory(mrjar.toFile());
|
||||
Process p = pb.start();
|
||||
p.waitFor(10, TimeUnit.SECONDS);
|
||||
String out;
|
||||
try (InputStream is = p.getInputStream()) {
|
||||
out = new String(is.readAllBytes());
|
||||
Process p = null;
|
||||
try {
|
||||
p = pb.start();
|
||||
p.waitFor();
|
||||
|
||||
String out;
|
||||
try (InputStream is = p.getInputStream()) {
|
||||
out = new String(is.readAllBytes());
|
||||
}
|
||||
String err;
|
||||
try (InputStream is = p.getErrorStream()) {
|
||||
err = new String(is.readAllBytes());
|
||||
}
|
||||
return new Result(cmd, p.exitValue(), out, err);
|
||||
} catch (Throwable t) {
|
||||
if (p != null) {
|
||||
p.destroyForcibly().waitFor();
|
||||
}
|
||||
throw t;
|
||||
}
|
||||
String err;
|
||||
try (InputStream is = p.getErrorStream()) {
|
||||
err = new String(is.readAllBytes());
|
||||
}
|
||||
return new Result(cmd, p.exitValue(), out, err);
|
||||
}
|
||||
|
||||
void checkResult(Result r) throws Exception {
|
||||
|
219
test/nashorn/script/basic/es6/JDK-8059835.js
Normal file
219
test/nashorn/script/basic/es6/JDK-8059835.js
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8059835: Optimistic splitting doesn't work with let and const
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
* @option --language=es6
|
||||
* @option -Dnashorn.compiler.splitter.threshold=100
|
||||
* @fork
|
||||
*/
|
||||
|
||||
function f() {
|
||||
let sum = 0;
|
||||
const c = 13;
|
||||
if (true) {
|
||||
let x = 0;
|
||||
const y = 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
sum += x;
|
||||
sum += y;
|
||||
}
|
||||
outer: while (true) {
|
||||
let x = 0;
|
||||
const y = 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
sum += x;
|
||||
sum += y;
|
||||
sum += c;
|
||||
let i = 0;
|
||||
const k = 1;
|
||||
while (true) {
|
||||
x += k;
|
||||
if (++i === 10) {
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
x += k;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
function g() {
|
||||
let sum = 0;
|
||||
const c = 13;
|
||||
if (true) {
|
||||
let x = 0;
|
||||
const y = 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
sum += x;
|
||||
sum += y;
|
||||
}
|
||||
outer: while (true) {
|
||||
let x = 0;
|
||||
const y = 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
x += 1;
|
||||
sum += x;
|
||||
sum += y;
|
||||
sum += c;
|
||||
let i = 0;
|
||||
const k = 1;
|
||||
while (true) {
|
||||
x += k;
|
||||
if (++i === 10) return 'abc';
|
||||
}
|
||||
x += k;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
Assert.assertTrue(f() === 80);
|
||||
Assert.assertTrue(g() === 'abc');
|
Loading…
Reference in New Issue
Block a user