From 47d111f7ac613b8add9b266c1496c69e30af0fd7 Mon Sep 17 00:00:00 2001 From: NathaneTouboul Date: Tue, 20 May 2025 15:54:37 +0200 Subject: [PATCH 1/2] [feat/WEB42108-search-retryable] first commit --- .../java/checks/SpringMaxRetryableCheck.java | 62 +++ src/test/files/SpringMaxRetryableCheck.java | 509 ++++++++++++++++++ .../java/checks/SpringMaxRetryableTest.java | 36 ++ 3 files changed, 607 insertions(+) create mode 100644 src/main/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableCheck.java create mode 100644 src/test/files/SpringMaxRetryableCheck.java create mode 100644 src/test/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableTest.java diff --git a/src/main/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableCheck.java b/src/main/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableCheck.java new file mode 100644 index 00000000..3dfd2c2e --- /dev/null +++ b/src/main/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableCheck.java @@ -0,0 +1,62 @@ +/* + * creedengo - Java language - Provides rules to reduce the environmental footprint of your Java programs + * Copyright © 2024 Green Code Initiative (https://green-code-initiative.org/) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.greencodeinitiative.creedengo.java.checks; + +import org.sonar.check.Rule; +import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; +import org.sonar.plugins.java.api.tree.*; +import org.sonar.plugins.java.api.tree.Tree.Kind; + +import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.List; + +// TODO DDC : rule already existing natively in SonarQube 9.9 (see java:S3012) for a part of checks +// ==> analyse / add our tag to it (?) + +/** + * Array Copy Check + * + * @author Aubay + * @formatter:off + */ +@Rule(key = "GCI604") +public class SpringMaxRetryableCheck extends IssuableSubscriptionVisitor { + + public static final String MESSAGE_RULE = "Avoid using Pattern.compile() in a non-static context."; + + + @Override + public List nodesToVisit() { + return Collections.singletonList(Kind.METHOD); + } + + /** + * Check a node. Report issue when found. + */ + @Override + public void visitNode(@Nonnull Tree tree) { + if (tree instanceof MethodTree) { + final MethodTree methodTree = (MethodTree) tree; + + if (!methodTree.is(Kind.CONSTRUCTOR)) { +// methodTree.accept(visitor); + } + } + } +} diff --git a/src/test/files/SpringMaxRetryableCheck.java b/src/test/files/SpringMaxRetryableCheck.java new file mode 100644 index 00000000..bdfb3f11 --- /dev/null +++ b/src/test/files/SpringMaxRetryableCheck.java @@ -0,0 +1,509 @@ +/* + * creedengo - Java language - Provides rules to reduce the environmental footprint of your Java programs + * Copyright © 2024 Green Code Initiative (https://green-code-initiative.org/) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +class TestClass { + + @Retryable(maxAttempts = 5, backoff = @Backoff(delay = 10)) + public void springMaxRetryOK() { + } + + @Retryable() // Noncompliant {{Missing parameters ofr Retryable}} + public void springMaxRetryOK() { + } + +// @Retryable(maxAttempts = 5, backoff = @Backoff(delay = 10)) // +// public void springMaxRetryOK() { +// } + + + +// public void nonRegression() { +// final int len = 5; +// final boolean[] src = new boolean[len]; +// boolean[] dest = new boolean[len]; +// +// // Simple assignation +// for (int i = 0; i < len; i++) { +// dest[i] = true; +// } +// +// // Edit same array +// for (int i = 0; i < len-1; i++) { +// dest[i] = dest[i+1]; +// } +// +// // Objects assignations +// String a = null; +// String b = "Sample Value"; +// for (int i = 0; i < len; i++) { +// a = b; +// } +// } +// +// public void copyWithForLoop() { +// final int len = 5; +// final boolean[] src = new boolean[len]; +// boolean[] dest = new boolean[len]; +// +// // Simple copy +// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// dest[i] = src[i]; +// } +// +// // Copy with nested conditions +// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(i + 2 < len) { +// dest[i] = src[i + 2]; +// } +// } +// +// // Copy with nested ELSE conditions +// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(i + 2 >= len) { +// i++; +// } else { +// dest[i] = src[i + 2]; +// } +// } +// +// // Copy with more nested conditions +// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(i + 2 < len) { +// if(dest != null) { +// if(src != null) { +// if(i > 1 && i + 2 < src.length) { +// dest[i] = src[i + 2]; +// } +// } +// } +// } +// } +// +// // Copy nested by try/catch +// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// dest[i] = src[i]; +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } +// } +// +// // Copy nested by try/catch and if +// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// if(dest != null) { +// dest[i] = src[i]; +// } +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } +// } +// +// // Copy nested by try/catch in catch +// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// dest.toString(); +// } catch (RuntimeException e) { +// if(dest != null) { +// dest[i] = src[i]; +// } +// } +// } +// +// // Copy nested by try/catch in finally +// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// dest.toString(); +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } finally { +// dest[i] = src[i]; +// } +// } +// +// // Array transformation +// for (int i = 0; i < len; i++) { +// dest[i] = transform(src[i]); +// } +// } +// +// public void copyWithForEachLoop() { +// final int len = 5; +// final boolean[] src = new boolean[len]; +// boolean[] dest = new boolean[len]; +// +// // Simple copy by foreach +// int i = -1; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// dest[++i] = b; +// } +// +// // Copy with nested conditions by foreach +// i = -1; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(b) { +// dest[++i] = b; +// } +// } +// +// // Copy with nested ELSE conditions by foreach +// i = -1; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(i + 2 >= len) { +// i++; +// } else { +// dest[++i] = b; +// } +// } +// +// // Copy with more nested conditions +// i = -1; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(i + 2 < len) { +// if(dest != null) { +// if(src != null) { +// if(i > 1 && i + 2 < src.length) { +// dest[++i] = b; +// } +// } +// } +// } +// } +// +// // Copy nested by try/catch +// i = -1; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// dest[++i] = b; +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } +// } +// +// // Copy nested by try/catch and if +// i = -1; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// if(dest != null) { +// dest[++i] = b; +// } +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } +// } +// +// // Copy nested by try/catch in catch +// i = -1; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// dest.toString(); +// } catch (RuntimeException e) { +// if(dest != null) { +// dest[++i] = b; +// } +// } +// } +// +// // Copy nested by try/catch in finally +// i = -1; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// dest.toString(); +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } finally { +// dest[++i] = b; +// } +// } +// +// // Array transformation +// i = -1; +// for (boolean b : src) { +// dest[++i] = transform(b); +// } +// +// // Simple copy +// int i = 0; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// dest[i] = src[i]; +// i++; +// } +// +// // Copy with nested conditions +// i = 0; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(b) { +// dest[i] = src[i]; +// } +// i++; +// } +// +// // Copy with nested ELSE conditions +// i = 0; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(i + 2 >= len) { +// i++; +// } else { +// dest[i] = src[i + 2]; +// } +// i++; +// } +// +// // Copy with more nested conditions +// i = 0; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(i + 2 < len) { +// if(dest != null) { +// if(src != null) { +// if(i > 1 && i + 2 < src.length) { +// dest[i] = src[i + 2]; +// } +// } +// } +// } +// i++; +// } +// +// // Copy nested by try/catch +// i = 0; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// dest[i] = src[i]; +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } +// i++; +// } +// +// // Copy nested by try/catch and if +// i = 0; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// if(dest != null) { +// dest[i] = src[i]; +// } +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } +// i++; +// } +// +// // Copy nested by try/catch in catch +// i = 0; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// dest.toString(); +// } catch (RuntimeException e) { +// if(dest != null) { +// dest[i] = src[i]; +// } +// } +// i++; +// } +// +// // Copy nested by try/catch in finally +// i = 0; +// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// dest.toString(); +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } finally { +// dest[i] = src[i]; +// } +// i++; +// } +// +// // Array transformation +// i = 0; +// for (boolean b : src) { +// dest[i] = transform(src[i]); +// i++; +// } +// } +// +// public void copyWithWhileLoop() { +// final int len = 5; +// final boolean[] src = new boolean[len]; +// boolean[] dest = new boolean[len]; +// +// // Simple copy +// int i = 0; +// while (i < len) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// dest[i] = src[i]; +// i++; +// } +// +// // Copy with nested conditions +// i = 0; +// while (i < len) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(i + 2 < len) { +// dest[i] = src[i + 2]; +// } +// i++; +// } +// +// // Copy with nested ELSE conditions +// i = 0; +// while (i < len) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(i + 2 >= len) { +// i++; +// } else { +// dest[i] = src[i + 2]; +// } +// i++; +// } +// +// // Copy with more nested conditions +// i = 0; +// while (i < len) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(i + 2 < len) { +// if(dest != null) { +// if(src != null) { +// if(i > 1 && i + 2 < src.length) { +// dest[i] = src[i + 2]; +// } +// } +// } +// } +// i++; +// } +// +// // Copy nested by try/catch and if +// i = 0; +// while (i < len) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// if(dest != null) { +// dest[i] = src[i]; +// } +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } +// i++; +// } +// +// // Copy nested by try/catch in catch +// i = 0; +// while (i < len) { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// dest.toString(); +// } catch (RuntimeException e) { +// if(dest != null) { +// dest[i] = src[i]; +// } +// } +// i++; +// } +// +// // Array transformation +// i = 0; +// while (i < len) { +// dest[i] = transform(src[i]); +// i++; +// } +// } +// +// public void copyWithDoWhileLoop() { +// final int len = 5; +// final boolean[] src = new boolean[len]; +// boolean[] dest = new boolean[len]; +// +// // Simple copy +// int i = 0; +// do { // Noncompliant {{Use System.arraycopy to copy arrays}} +// dest[i] = src[i]; +// i++; +// } while (i < len); +// +// // Copy with nested conditions +// i = 0; +// do { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(i + 2 < len) { +// dest[i] = src[i + 2]; +// } +// i++; +// } while (i < len); +// +// // Copy with nested ELSE conditions +// i = 0; +// do { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(i + 2 >= len) { +// i++; +// } else { +// dest[i] = src[i + 2]; +// } +// i++; +// } while (i < len); +// +// // Copy with more nested conditions +// i = 0; +// do { // Noncompliant {{Use System.arraycopy to copy arrays}} +// if(i + 2 < len) { +// if(dest != null) { +// if(src != null) { +// if(i > 1 && i + 2 < src.length) { +// dest[i] = src[i + 2]; +// } +// } +// } +// } +// i++; +// } while (i < len); +// +// // Copy nested by try/catch and if +// i = 0; +// do { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// if(dest != null) { +// dest[i] = src[i]; +// } +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } +// i++; +// } while (i < len); +// +// // Copy nested by try/catch in catch +// i = 0; +// do { // Noncompliant {{Use System.arraycopy to copy arrays}} +// try { +// dest.toString(); +// } catch (RuntimeException e) { +// if(dest != null) { +// dest[i] = src[i]; +// } +// } +// i++; +// } while (i < len); +// +// // Array transformation +// i = 0; +// do { +// dest[i] = transform(src[i]); +// i++; +// } while (i < len); +// } +// +// private boolean transform(boolean a) { +// return !a; +// } + +} diff --git a/src/test/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableTest.java b/src/test/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableTest.java new file mode 100644 index 00000000..bed514af --- /dev/null +++ b/src/test/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableTest.java @@ -0,0 +1,36 @@ +/* + * creedengo - Java language - Provides rules to reduce the environmental footprint of your Java programs + * Copyright © 2024 Green Code Initiative (https://green-code-initiative.org/) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.greencodeinitiative.creedengo.java.checks; + +import org.junit.jupiter.api.Test; +import org.sonar.java.checks.verifier.CheckVerifier; + +class SpringMaxRetryableTest { + + /** + * @formatter:off + */ + @Test + void test() { + CheckVerifier.newVerifier() + .onFile("src/test/files/SpringMaxRetryableCheck.java") + .withCheck(new ArrayCopyCheck()) + .verifyIssues(); + } + +} From 10449d2c3f65b0d98b3414258e4705830c2022bf Mon Sep 17 00:00:00 2001 From: NathTouboul Date: Wed, 21 May 2025 15:29:51 +0200 Subject: [PATCH 2/2] [feat/WEB42108-search-retryable] final commit --- .../java/checks/SpringMaxRetryableCheck.java | 145 +++++- src/test/files/SpringMaxRetryableCheck.java | 490 +----------------- .../java/checks/SpringMaxRetryableTest.java | 2 +- 3 files changed, 141 insertions(+), 496 deletions(-) diff --git a/src/main/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableCheck.java b/src/main/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableCheck.java index 3dfd2c2e..a5561b12 100644 --- a/src/main/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableCheck.java +++ b/src/main/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableCheck.java @@ -22,41 +22,152 @@ import org.sonar.plugins.java.api.tree.*; import org.sonar.plugins.java.api.tree.Tree.Kind; -import javax.annotation.Nonnull; +import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; // TODO DDC : rule already existing natively in SonarQube 9.9 (see java:S3012) for a part of checks // ==> analyse / add our tag to it (?) -/** - * Array Copy Check - * - * @author Aubay - * @formatter:off - */ @Rule(key = "GCI604") public class SpringMaxRetryableCheck extends IssuableSubscriptionVisitor { - public static final String MESSAGE_RULE = "Avoid using Pattern.compile() in a non-static context."; + public static final String MESSAGE_RULE = "Please use optimized @Retryable parameters."; + private static final long MAX_TIMEOUT = 5000; + private static final int MAX_RETRY = 3; + + public static long calculateRetryTimeout(Integer maxAttempts, Long delay, Double multiplier) { + int attempts = (maxAttempts != null) ? maxAttempts : 3; + long initialDelay = (delay != null) ? delay : 1000L; + double factor = (multiplier != null) ? multiplier : 1.0; + long total = 0; + long currentDelay = initialDelay; + for (int i = 1; i < attempts; i++) { + total += currentDelay; + currentDelay = (long) (currentDelay * factor); + } + return total; + } @Override public List nodesToVisit() { - return Collections.singletonList(Kind.METHOD); + return Collections.singletonList(Kind.ANNOTATION); + } + + private Optional extractConstantAsString(ExpressionTree tree) { + Optional asInt = tree.asConstant(Integer.class); + if (asInt.isPresent()) { + return Optional.of(String.valueOf(asInt.get())); + } + + Optional asDouble = tree.asConstant(Double.class); + return asDouble.map(String::valueOf).or(() -> tree.asConstant(String.class)); } - /** - * Check a node. Report issue when found. - */ @Override - public void visitNode(@Nonnull Tree tree) { - if (tree instanceof MethodTree) { - final MethodTree methodTree = (MethodTree) tree; + public void visitNode(Tree tree) { + AnnotationTree annotationTree = (AnnotationTree) tree; + if (!"Retryable".equals(annotationTree.symbolType().fullyQualifiedName())) { + return; + } + + List params = new ArrayList<>(); + + for (ExpressionTree argument : annotationTree.arguments()) { + if (!argument.is(Tree.Kind.ASSIGNMENT)) { + continue; + } + AssignmentExpressionTree assignmentTree = (AssignmentExpressionTree) argument; + String paramName = ((IdentifierTree) assignmentTree.variable()).name(); + ExpressionTree valueTree = assignmentTree.expression(); + + var extractedParams = extractParametersAndValues(argument, valueTree, paramName); + if (!extractedParams.isEmpty()) { + params.addAll(extractedParams); + } + } + + if (!params.isEmpty()) { + checkValues(params); + } + } + + private List extractParametersAndValues(ExpressionTree argument, ExpressionTree valueTree, String paramName) { + List params = new ArrayList<>(); - if (!methodTree.is(Kind.CONSTRUCTOR)) { -// methodTree.accept(visitor); + if (valueTree.asConstant(Integer.class).isPresent()) { + int value = valueTree.asConstant(Integer.class).get(); + params.add(new ArgumentDetails(argument, paramName, String.valueOf(value))); + } else if (valueTree.is(Kind.ANNOTATION)) { + AnnotationTree nestedAnnotation = (AnnotationTree) valueTree; + for (ExpressionTree nestedArg : nestedAnnotation.arguments()) { + if (nestedArg.is(Kind.ASSIGNMENT)) { + AssignmentExpressionTree nestedAssignment = (AssignmentExpressionTree) nestedArg; + String nestedParam = ((IdentifierTree) nestedAssignment.variable()).name(); + ExpressionTree nestedValueTree = nestedAssignment.expression(); + + Optional constValue = extractConstantAsString(nestedValueTree); + constValue.ifPresent(val -> + params.add(new ArgumentDetails(nestedArg, paramName + "." + nestedParam, val)) + ); + } } } + + return params; + } + + void checkValues(List params) { + Integer maxAttempts = params.stream() + .filter(argumentDetails -> argumentDetails.paramName.equals("maxAttempts")) + .map(ArgumentDetails::getParamValue) + .map(Integer::valueOf) + .findFirst().orElse(null); + + Long delay = params.stream() + .filter(argumentDetails -> argumentDetails.paramName.equals("backoff.delay")) + .map(ArgumentDetails::getParamValue) + .map(Long::valueOf) + .findFirst().orElse(null); + + Double multiplier = params.stream() + .filter(argumentDetails -> argumentDetails.paramName.equals("backoff.multiplier")) + .map(ArgumentDetails::getParamValue) + .map(Double::parseDouble) + .findFirst().orElse(null); + + if (isGreaterThanMax(maxAttempts, delay, multiplier)) { + reportIssue(params.get(0).getArgument(), MESSAGE_RULE); + } + } + + public boolean isGreaterThanMax(Integer maxAttempts, Long delay, Double multiplier) { + return (calculateRetryTimeout(maxAttempts, delay, multiplier) > MAX_TIMEOUT) || maxAttempts > MAX_RETRY; + } + + class ArgumentDetails { + private final ExpressionTree argument; + private final String paramName; + private final String paramValue; + + ArgumentDetails(ExpressionTree argument, String paramName, String paramValue) { + this.argument = argument; + this.paramName = paramName; + this.paramValue = paramValue; + } + + public ExpressionTree getArgument() { + return argument; + } + + public String getParamName() { + return paramName; + } + + public String getParamValue() { + return paramValue; + } } } diff --git a/src/test/files/SpringMaxRetryableCheck.java b/src/test/files/SpringMaxRetryableCheck.java index bdfb3f11..9d663383 100644 --- a/src/test/files/SpringMaxRetryableCheck.java +++ b/src/test/files/SpringMaxRetryableCheck.java @@ -21,489 +21,23 @@ class TestClass { - @Retryable(maxAttempts = 5, backoff = @Backoff(delay = 10)) + @Retryable(maxAttempts = 3, backoff = @Backoff(delay = 10)) public void springMaxRetryOK() { } - @Retryable() // Noncompliant {{Missing parameters ofr Retryable}} - public void springMaxRetryOK() { + @Retryable(maxAttempts = 3, backoff = @Backoff(delay = 10, multiplier = 2)) + public void springMaxRetryWithFullParamsOK() { } -// @Retryable(maxAttempts = 5, backoff = @Backoff(delay = 10)) // -// public void springMaxRetryOK() { -// } - + @Retryable() + public void springMaxRetryWithoutParamsOK() { + } + @Retryable(maxAttempts = 5, backoff = @Backoff(delay = 10, multiplier = 2)) // Noncompliant {{Please use optimized @Retryable parameters.}} + public void springMaxRetryMaxAttemptsKO() { + } -// public void nonRegression() { -// final int len = 5; -// final boolean[] src = new boolean[len]; -// boolean[] dest = new boolean[len]; -// -// // Simple assignation -// for (int i = 0; i < len; i++) { -// dest[i] = true; -// } -// -// // Edit same array -// for (int i = 0; i < len-1; i++) { -// dest[i] = dest[i+1]; -// } -// -// // Objects assignations -// String a = null; -// String b = "Sample Value"; -// for (int i = 0; i < len; i++) { -// a = b; -// } -// } -// -// public void copyWithForLoop() { -// final int len = 5; -// final boolean[] src = new boolean[len]; -// boolean[] dest = new boolean[len]; -// -// // Simple copy -// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// dest[i] = src[i]; -// } -// -// // Copy with nested conditions -// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(i + 2 < len) { -// dest[i] = src[i + 2]; -// } -// } -// -// // Copy with nested ELSE conditions -// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(i + 2 >= len) { -// i++; -// } else { -// dest[i] = src[i + 2]; -// } -// } -// -// // Copy with more nested conditions -// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(i + 2 < len) { -// if(dest != null) { -// if(src != null) { -// if(i > 1 && i + 2 < src.length) { -// dest[i] = src[i + 2]; -// } -// } -// } -// } -// } -// -// // Copy nested by try/catch -// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// dest[i] = src[i]; -// } catch (RuntimeException e) { -// e.printStackTrace(); -// } -// } -// -// // Copy nested by try/catch and if -// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// if(dest != null) { -// dest[i] = src[i]; -// } -// } catch (RuntimeException e) { -// e.printStackTrace(); -// } -// } -// -// // Copy nested by try/catch in catch -// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// dest.toString(); -// } catch (RuntimeException e) { -// if(dest != null) { -// dest[i] = src[i]; -// } -// } -// } -// -// // Copy nested by try/catch in finally -// for (int i = 0; i < len; i++) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// dest.toString(); -// } catch (RuntimeException e) { -// e.printStackTrace(); -// } finally { -// dest[i] = src[i]; -// } -// } -// -// // Array transformation -// for (int i = 0; i < len; i++) { -// dest[i] = transform(src[i]); -// } -// } -// -// public void copyWithForEachLoop() { -// final int len = 5; -// final boolean[] src = new boolean[len]; -// boolean[] dest = new boolean[len]; -// -// // Simple copy by foreach -// int i = -1; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// dest[++i] = b; -// } -// -// // Copy with nested conditions by foreach -// i = -1; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(b) { -// dest[++i] = b; -// } -// } -// -// // Copy with nested ELSE conditions by foreach -// i = -1; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(i + 2 >= len) { -// i++; -// } else { -// dest[++i] = b; -// } -// } -// -// // Copy with more nested conditions -// i = -1; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(i + 2 < len) { -// if(dest != null) { -// if(src != null) { -// if(i > 1 && i + 2 < src.length) { -// dest[++i] = b; -// } -// } -// } -// } -// } -// -// // Copy nested by try/catch -// i = -1; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// dest[++i] = b; -// } catch (RuntimeException e) { -// e.printStackTrace(); -// } -// } -// -// // Copy nested by try/catch and if -// i = -1; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// if(dest != null) { -// dest[++i] = b; -// } -// } catch (RuntimeException e) { -// e.printStackTrace(); -// } -// } -// -// // Copy nested by try/catch in catch -// i = -1; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// dest.toString(); -// } catch (RuntimeException e) { -// if(dest != null) { -// dest[++i] = b; -// } -// } -// } -// -// // Copy nested by try/catch in finally -// i = -1; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// dest.toString(); -// } catch (RuntimeException e) { -// e.printStackTrace(); -// } finally { -// dest[++i] = b; -// } -// } -// -// // Array transformation -// i = -1; -// for (boolean b : src) { -// dest[++i] = transform(b); -// } -// -// // Simple copy -// int i = 0; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// dest[i] = src[i]; -// i++; -// } -// -// // Copy with nested conditions -// i = 0; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(b) { -// dest[i] = src[i]; -// } -// i++; -// } -// -// // Copy with nested ELSE conditions -// i = 0; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(i + 2 >= len) { -// i++; -// } else { -// dest[i] = src[i + 2]; -// } -// i++; -// } -// -// // Copy with more nested conditions -// i = 0; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(i + 2 < len) { -// if(dest != null) { -// if(src != null) { -// if(i > 1 && i + 2 < src.length) { -// dest[i] = src[i + 2]; -// } -// } -// } -// } -// i++; -// } -// -// // Copy nested by try/catch -// i = 0; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// dest[i] = src[i]; -// } catch (RuntimeException e) { -// e.printStackTrace(); -// } -// i++; -// } -// -// // Copy nested by try/catch and if -// i = 0; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// if(dest != null) { -// dest[i] = src[i]; -// } -// } catch (RuntimeException e) { -// e.printStackTrace(); -// } -// i++; -// } -// -// // Copy nested by try/catch in catch -// i = 0; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// dest.toString(); -// } catch (RuntimeException e) { -// if(dest != null) { -// dest[i] = src[i]; -// } -// } -// i++; -// } -// -// // Copy nested by try/catch in finally -// i = 0; -// for (boolean b : src) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// dest.toString(); -// } catch (RuntimeException e) { -// e.printStackTrace(); -// } finally { -// dest[i] = src[i]; -// } -// i++; -// } -// -// // Array transformation -// i = 0; -// for (boolean b : src) { -// dest[i] = transform(src[i]); -// i++; -// } -// } -// -// public void copyWithWhileLoop() { -// final int len = 5; -// final boolean[] src = new boolean[len]; -// boolean[] dest = new boolean[len]; -// -// // Simple copy -// int i = 0; -// while (i < len) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// dest[i] = src[i]; -// i++; -// } -// -// // Copy with nested conditions -// i = 0; -// while (i < len) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(i + 2 < len) { -// dest[i] = src[i + 2]; -// } -// i++; -// } -// -// // Copy with nested ELSE conditions -// i = 0; -// while (i < len) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(i + 2 >= len) { -// i++; -// } else { -// dest[i] = src[i + 2]; -// } -// i++; -// } -// -// // Copy with more nested conditions -// i = 0; -// while (i < len) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(i + 2 < len) { -// if(dest != null) { -// if(src != null) { -// if(i > 1 && i + 2 < src.length) { -// dest[i] = src[i + 2]; -// } -// } -// } -// } -// i++; -// } -// -// // Copy nested by try/catch and if -// i = 0; -// while (i < len) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// if(dest != null) { -// dest[i] = src[i]; -// } -// } catch (RuntimeException e) { -// e.printStackTrace(); -// } -// i++; -// } -// -// // Copy nested by try/catch in catch -// i = 0; -// while (i < len) { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// dest.toString(); -// } catch (RuntimeException e) { -// if(dest != null) { -// dest[i] = src[i]; -// } -// } -// i++; -// } -// -// // Array transformation -// i = 0; -// while (i < len) { -// dest[i] = transform(src[i]); -// i++; -// } -// } -// -// public void copyWithDoWhileLoop() { -// final int len = 5; -// final boolean[] src = new boolean[len]; -// boolean[] dest = new boolean[len]; -// -// // Simple copy -// int i = 0; -// do { // Noncompliant {{Use System.arraycopy to copy arrays}} -// dest[i] = src[i]; -// i++; -// } while (i < len); -// -// // Copy with nested conditions -// i = 0; -// do { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(i + 2 < len) { -// dest[i] = src[i + 2]; -// } -// i++; -// } while (i < len); -// -// // Copy with nested ELSE conditions -// i = 0; -// do { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(i + 2 >= len) { -// i++; -// } else { -// dest[i] = src[i + 2]; -// } -// i++; -// } while (i < len); -// -// // Copy with more nested conditions -// i = 0; -// do { // Noncompliant {{Use System.arraycopy to copy arrays}} -// if(i + 2 < len) { -// if(dest != null) { -// if(src != null) { -// if(i > 1 && i + 2 < src.length) { -// dest[i] = src[i + 2]; -// } -// } -// } -// } -// i++; -// } while (i < len); -// -// // Copy nested by try/catch and if -// i = 0; -// do { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// if(dest != null) { -// dest[i] = src[i]; -// } -// } catch (RuntimeException e) { -// e.printStackTrace(); -// } -// i++; -// } while (i < len); -// -// // Copy nested by try/catch in catch -// i = 0; -// do { // Noncompliant {{Use System.arraycopy to copy arrays}} -// try { -// dest.toString(); -// } catch (RuntimeException e) { -// if(dest != null) { -// dest[i] = src[i]; -// } -// } -// i++; -// } while (i < len); -// -// // Array transformation -// i = 0; -// do { -// dest[i] = transform(src[i]); -// i++; -// } while (i < len); -// } -// -// private boolean transform(boolean a) { -// return !a; -// } - + @Retryable(maxAttempts = 3, backoff = @Backoff(delay = 10, multiplier = 10000)) // Noncompliant {{Please use optimized @Retryable parameters.}} + public void springMaxRetryTimeOutKO() { + } } diff --git a/src/test/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableTest.java b/src/test/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableTest.java index bed514af..a3d44162 100644 --- a/src/test/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableTest.java +++ b/src/test/java/org/greencodeinitiative/creedengo/java/checks/SpringMaxRetryableTest.java @@ -29,7 +29,7 @@ class SpringMaxRetryableTest { void test() { CheckVerifier.newVerifier() .onFile("src/test/files/SpringMaxRetryableCheck.java") - .withCheck(new ArrayCopyCheck()) + .withCheck(new SpringMaxRetryableCheck()) .verifyIssues(); }