undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
352
test/jdk/java/awt/geom/AffineTransform/TestRotateMethods.java
Normal file
352
test/jdk/java/awt/geom/AffineTransform/TestRotateMethods.java
Normal file
|
|
@ -0,0 +1,352 @@
|
|||
/*
|
||||
* Copyright (c) 2004, 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 4980035
|
||||
* @summary Unit test for new methods:
|
||||
*
|
||||
* AffineTransform.getRotateInstance(double x, double y);
|
||||
* AffineTransform.setToRotation(double x, double y);
|
||||
* AffineTransform.rotate(double x, double y);
|
||||
*
|
||||
* AffineTransform.getQuadrantRotateInstance(int numquads);
|
||||
* AffineTransform.setToQuadrantRotation(int numquads);
|
||||
* AffineTransform.quadrantRotate(int numquads);
|
||||
*
|
||||
* @author flar
|
||||
* @run main TestRotateMethods
|
||||
*/
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
public class TestRotateMethods {
|
||||
/* The maximum errors allowed, measured in double precision "ulps"
|
||||
* Note that for most fields, the tests are extremely accurate - to
|
||||
* within 3 ulps of the smaller value in the comparison
|
||||
* For the translation components, the tests are still very accurate,
|
||||
* but the absolute number of ulps can be noticeably higher when we
|
||||
* use one of the rotate methods that takes an anchor point.
|
||||
* Since a double precision value has 56 bits of precision, even
|
||||
* 1024 ulps is extremely small as a ratio of the value.
|
||||
*/
|
||||
public static final double MAX_ULPS = 3.0;
|
||||
public static final double MAX_ANCHOR_TX_ULPS = 1024.0;
|
||||
public static double MAX_TX_ULPS = MAX_ULPS;
|
||||
|
||||
// Vectors for quadrant rotations
|
||||
public static final double quadxvec[] = { 1.0, 0.0, -1.0, 0.0 };
|
||||
public static final double quadyvec[] = { 0.0, 1.0, 0.0, -1.0 };
|
||||
|
||||
// Run tests once for each type of method:
|
||||
// tx = AffineTransform.get<Rotate>Instance()
|
||||
// tx.set<Rotate>()
|
||||
// tx.<rotate>()
|
||||
public static enum Mode { GET, SET, MOD };
|
||||
|
||||
// Used to accumulate and report largest differences encountered by tests
|
||||
public static double maxulps = 0.0;
|
||||
public static double maxtxulps = 0.0;
|
||||
|
||||
// Sample anchor points for testing.
|
||||
public static Point2D zeropt = new Point2D.Double(0, 0);
|
||||
public static Point2D testtxpts[] = {
|
||||
new Point2D.Double( 5, 5),
|
||||
new Point2D.Double( 20, -10),
|
||||
new Point2D.Double(-Math.PI, Math.E),
|
||||
};
|
||||
|
||||
public static void main(String argv[]) {
|
||||
test(Mode.GET);
|
||||
test(Mode.SET);
|
||||
test(Mode.MOD);
|
||||
|
||||
System.out.println("Max scale and shear difference: "+maxulps+" ulps");
|
||||
System.out.println("Max translate difference: "+maxtxulps+" ulps");
|
||||
}
|
||||
|
||||
public static void test(Mode mode) {
|
||||
MAX_TX_ULPS = MAX_ULPS; // Stricter tx testing with no anchor point
|
||||
test(mode, 0.5, null);
|
||||
test(mode, 1.0, null);
|
||||
test(mode, 3.0, null);
|
||||
|
||||
// Anchor points make the tx values less reliable
|
||||
MAX_TX_ULPS = MAX_ANCHOR_TX_ULPS;
|
||||
for (int i = 0; i < testtxpts.length; i++) {
|
||||
test(mode, 1.0, testtxpts[i]);
|
||||
}
|
||||
MAX_TX_ULPS = MAX_ULPS; // Restore to default
|
||||
}
|
||||
|
||||
public static void verify(AffineTransform at1, AffineTransform at2,
|
||||
Mode mode, double vectorscale, Point2D txpt,
|
||||
String message, double num, String units)
|
||||
{
|
||||
if (!compare(at1, at2)) {
|
||||
System.out.println("mode == "+mode);
|
||||
System.out.println("vectorscale == "+vectorscale);
|
||||
System.out.println("txpt == "+txpt);
|
||||
System.out.println(at1+", type = "+at1.getType());
|
||||
System.out.println(at2+", type = "+at2.getType());
|
||||
System.out.println("ScaleX values differ by "+
|
||||
ulps(at1.getScaleX(), at2.getScaleX())+" ulps");
|
||||
System.out.println("ScaleY values differ by "+
|
||||
ulps(at1.getScaleY(), at2.getScaleY())+" ulps");
|
||||
System.out.println("ShearX values differ by "+
|
||||
ulps(at1.getShearX(), at2.getShearX())+" ulps");
|
||||
System.out.println("ShearY values differ by "+
|
||||
ulps(at1.getShearY(), at2.getShearY())+" ulps");
|
||||
System.out.println("TranslateX values differ by "+
|
||||
ulps(at1.getTranslateX(),
|
||||
at2.getTranslateX())+" ulps");
|
||||
System.out.println("TranslateY values differ by "+
|
||||
ulps(at1.getTranslateY(),
|
||||
at2.getTranslateY())+" ulps");
|
||||
throw new RuntimeException(message + num + units);
|
||||
}
|
||||
}
|
||||
|
||||
public static void test(Mode mode, double vectorscale, Point2D txpt) {
|
||||
AffineTransform at1, at2, at3;
|
||||
|
||||
for (int deg = -720; deg <= 720; deg++) {
|
||||
if ((deg % 90) == 0) continue;
|
||||
double radians = Math.toRadians(deg);
|
||||
double vecy = Math.sin(radians) * vectorscale;
|
||||
double vecx = Math.cos(radians) * vectorscale;
|
||||
|
||||
at1 = makeAT(mode, txpt, radians);
|
||||
at2 = makeAT(mode, txpt, vecx, vecy);
|
||||
verify(at1, at2, mode, vectorscale, txpt,
|
||||
"vector and radians do not match for ", deg, " degrees");
|
||||
|
||||
if (txpt == null) {
|
||||
// Make sure output was same as a with a 0,0 anchor point
|
||||
if (vectorscale == 1.0) {
|
||||
// Only need to test radians method for one scale factor
|
||||
at3 = makeAT(mode, zeropt, radians);
|
||||
verify(at1, at3, mode, vectorscale, zeropt,
|
||||
"radians not invariant with 0,0 translate at ",
|
||||
deg, " degrees");
|
||||
}
|
||||
// But test vector methods with all scale factors
|
||||
at3 = makeAT(mode, zeropt, vecx, vecy);
|
||||
verify(at2, at3, mode, vectorscale, zeropt,
|
||||
"vector not invariant with 0,0 translate at ",
|
||||
deg, " degrees");
|
||||
}
|
||||
}
|
||||
|
||||
for (int quad = -8; quad <= 8; quad++) {
|
||||
double degrees = quad * 90.0;
|
||||
double radians = Math.toRadians(degrees);
|
||||
double vecx = quadxvec[quad & 3] * vectorscale;
|
||||
double vecy = quadyvec[quad & 3] * vectorscale;
|
||||
|
||||
at1 = makeAT(mode, txpt, radians);
|
||||
at2 = makeAT(mode, txpt, vecx, vecy);
|
||||
verify(at1, at2, mode, vectorscale, txpt,
|
||||
"quadrant vector and radians do not match for ",
|
||||
degrees, " degrees");
|
||||
at2 = makeQuadAT(mode, txpt, quad);
|
||||
verify(at1, at2, mode, vectorscale, txpt,
|
||||
"quadrant and radians do not match for ",
|
||||
quad, " quadrants");
|
||||
if (txpt == null) {
|
||||
at3 = makeQuadAT(mode, zeropt, quad);
|
||||
verify(at2, at3, mode, vectorscale, zeropt,
|
||||
"quadrant not invariant with 0,0 translate at ",
|
||||
quad, " quadrants");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AffineTransform makeRandomAT() {
|
||||
AffineTransform at = new AffineTransform();
|
||||
at.scale(Math.random() * -10.0, Math.random() * 100.0);
|
||||
at.rotate(Math.random() * Math.PI);
|
||||
at.shear(Math.random(), Math.random());
|
||||
at.translate(Math.random() * 300.0, Math.random() * -20.0);
|
||||
return at;
|
||||
}
|
||||
|
||||
public static AffineTransform makeAT(Mode mode, Point2D txpt,
|
||||
double radians)
|
||||
{
|
||||
AffineTransform at;
|
||||
double tx = (txpt == null) ? 0.0 : txpt.getX();
|
||||
double ty = (txpt == null) ? 0.0 : txpt.getY();
|
||||
switch (mode) {
|
||||
case GET:
|
||||
if (txpt != null) {
|
||||
at = AffineTransform.getRotateInstance(radians, tx, ty);
|
||||
} else {
|
||||
at = AffineTransform.getRotateInstance(radians);
|
||||
}
|
||||
break;
|
||||
case SET:
|
||||
at = makeRandomAT();
|
||||
if (txpt != null) {
|
||||
at.setToRotation(radians, tx, ty);
|
||||
} else {
|
||||
at.setToRotation(radians);
|
||||
}
|
||||
break;
|
||||
case MOD:
|
||||
at = makeRandomAT();
|
||||
at.setToIdentity();
|
||||
if (txpt != null) {
|
||||
at.rotate(radians, tx, ty);
|
||||
} else {
|
||||
at.rotate(radians);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("unrecognized mode: "+mode);
|
||||
}
|
||||
|
||||
return at;
|
||||
}
|
||||
|
||||
public static AffineTransform makeAT(Mode mode, Point2D txpt,
|
||||
double vx, double vy)
|
||||
{
|
||||
AffineTransform at;
|
||||
double tx = (txpt == null) ? 0.0 : txpt.getX();
|
||||
double ty = (txpt == null) ? 0.0 : txpt.getY();
|
||||
switch (mode) {
|
||||
case GET:
|
||||
if (txpt != null) {
|
||||
at = AffineTransform.getRotateInstance(vx, vy, tx, ty);
|
||||
} else {
|
||||
at = AffineTransform.getRotateInstance(vx, vy);
|
||||
}
|
||||
break;
|
||||
case SET:
|
||||
at = makeRandomAT();
|
||||
if (txpt != null) {
|
||||
at.setToRotation(vx, vy, tx, ty);
|
||||
} else {
|
||||
at.setToRotation(vx, vy);
|
||||
}
|
||||
break;
|
||||
case MOD:
|
||||
at = makeRandomAT();
|
||||
at.setToIdentity();
|
||||
if (txpt != null) {
|
||||
at.rotate(vx, vy, tx, ty);
|
||||
} else {
|
||||
at.rotate(vx, vy);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("unrecognized mode: "+mode);
|
||||
}
|
||||
|
||||
return at;
|
||||
}
|
||||
|
||||
public static AffineTransform makeQuadAT(Mode mode, Point2D txpt,
|
||||
int quads)
|
||||
{
|
||||
AffineTransform at;
|
||||
double tx = (txpt == null) ? 0.0 : txpt.getX();
|
||||
double ty = (txpt == null) ? 0.0 : txpt.getY();
|
||||
switch (mode) {
|
||||
case GET:
|
||||
if (txpt != null) {
|
||||
at = AffineTransform.getQuadrantRotateInstance(quads, tx, ty);
|
||||
} else {
|
||||
at = AffineTransform.getQuadrantRotateInstance(quads);
|
||||
}
|
||||
break;
|
||||
case SET:
|
||||
at = makeRandomAT();
|
||||
if (txpt != null) {
|
||||
at.setToQuadrantRotation(quads, tx, ty);
|
||||
} else {
|
||||
at.setToQuadrantRotation(quads);
|
||||
}
|
||||
break;
|
||||
case MOD:
|
||||
at = makeRandomAT();
|
||||
at.setToIdentity();
|
||||
if (txpt != null) {
|
||||
at.quadrantRotate(quads, tx, ty);
|
||||
} else {
|
||||
at.quadrantRotate(quads);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("unrecognized mode: "+mode);
|
||||
}
|
||||
|
||||
return at;
|
||||
}
|
||||
|
||||
public static boolean compare(AffineTransform at1, AffineTransform at2) {
|
||||
maxulps = Math.max(maxulps, ulps(at1.getScaleX(), at2.getScaleX()));
|
||||
maxulps = Math.max(maxulps, ulps(at1.getScaleY(), at2.getScaleY()));
|
||||
maxulps = Math.max(maxulps, ulps(at1.getShearX(), at2.getShearX()));
|
||||
maxulps = Math.max(maxulps, ulps(at1.getShearY(), at2.getShearY()));
|
||||
maxtxulps = Math.max(maxtxulps,
|
||||
ulps(at1.getTranslateX(), at2.getTranslateX()));
|
||||
maxtxulps = Math.max(maxtxulps,
|
||||
ulps(at1.getTranslateY(), at2.getTranslateY()));
|
||||
return (getModifiedType(at1) == getModifiedType(at2) &&
|
||||
(compare(at1.getScaleX(), at2.getScaleX(), MAX_ULPS)) &&
|
||||
(compare(at1.getScaleY(), at2.getScaleY(), MAX_ULPS)) &&
|
||||
(compare(at1.getShearX(), at2.getShearX(), MAX_ULPS)) &&
|
||||
(compare(at1.getShearY(), at2.getShearY(), MAX_ULPS)) &&
|
||||
(compare(at1.getTranslateX(),
|
||||
at2.getTranslateX(), MAX_TX_ULPS)) &&
|
||||
(compare(at1.getTranslateY(),
|
||||
at2.getTranslateY(), MAX_TX_ULPS)));
|
||||
}
|
||||
|
||||
public static int getModifiedType(AffineTransform at) {
|
||||
int type = at.getType();
|
||||
// Some of the vector methods can introduce a tiny uniform scale
|
||||
// at some angles...
|
||||
if ((type & AffineTransform.TYPE_UNIFORM_SCALE) != 0) {
|
||||
maxulps = Math.max(maxulps, ulps(at.getDeterminant(), 1.0));
|
||||
if (ulps(at.getDeterminant(), 1.0) <= MAX_ULPS) {
|
||||
// Really tiny - we will ignore it
|
||||
type &= (~AffineTransform.TYPE_UNIFORM_SCALE);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public static boolean compare(double val1, double val2, double maxulps) {
|
||||
return (ulps(val1, val2) <= maxulps);
|
||||
}
|
||||
|
||||
public static double ulps(double val1, double val2) {
|
||||
double diff = Math.abs(val1 - val2);
|
||||
double ulpmax = Math.min(Math.ulp(val1), Math.ulp(val2));
|
||||
return (diff / ulpmax);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue