SonarQube detects two lines as duplicates

  • SonarQube10.2.1.78527, Docker

Hi,

we are currently updating some error handling and simply updated some classes with their respective error handling code.
These are mostly only two lines.
In total, we have 5 classes that have the same two lines of error handling. However, for two of them, SonarQube detects them as duplicated lines. Because the PR is quite small, the Quality Gate fails therefore.
Why does Sonar detect it for two of the classes, i.e., says duplication 100%, but 0 for the other three?
These are the lines that are added in all 5 classes:

outputArguments[0] = OperationStatus.CommunicationError;
return StatusCodes.UnexpectedError;

In general, can I define the number of lines that are needed for SonarQube to detect a duplication?

Cheers,
Lukas


Hi Lukas,

Welcome to the community!

Per the docs, Java duplications are detected when there are:

at least 10 successive and duplicated statements

It’s hard to know without the full context, but I guess in the cases where a duplication is detected in the PR, they’re each part of a larger 10+ statement block, whereas the other three aren’t…?

Looking at the context, does that make sense?

 
Ann

Hi Ann,

thanks for your response! :slight_smile:

I attached the whole diff in this PR. Now, Sonar detects a duplicate of 100% in Class4.cs and Class6.cs but not for any other class or method.
There are no blocks larger than 10 lines that are equal…

diff --git a/src/Test/Class1Test.cs b/src/Test/Class1Test.cs
--- a/src/Test/Class1Test.cs
+++ b/src/Test/Class1Test.cs
@@ -137,7 +137,7 @@ public class Class1Test : IClassFixture {
         ServiceResult result = m_killTag.OnCall(callContext, innerMethod, inArgs, outArgs);
 
         Assert.NotNull(result);
-        Assert.Equal(StatusCodes.DeviceFailure, result.StatusCode);
+        Assert.Equal(StatusCodes.UnexpectedError, result.StatusCode);
     }
 
     [Theory]
diff --git a/src/Test/Calss2Test.cs b/src/Test/Calss2Test.cs
--- a/src/Test/Calss2Test.cs
+++ b/src/Test/Calss2Test.cs
@@ -144,7 +144,7 @@ public class Calss2Test : IClassFixture {
         ServiceResult result = m_lockTag.OnCall(callContext, innerMethod, inArgs, outArgs);
 
         Assert.NotNull(result);
-        Assert.Equal(StatusCodes.DeviceFailure, result.StatusCode);
+        Assert.Equal(StatusCodes.UnexpectedError, result.StatusCode);
     }
 
     [Theory]
diff --git a/src/Test/Calss3Test.cs b/src/Test/Calss3Test.cs
--- a/src/Test/Calss3Test.cs
+++ b/src/Test/Calss3Test.cs
@@ -145,7 +145,11 @@ public class Calss3Test : IClassFixture {
         ServiceResult result = m_method.OnCall(callContext, innerMethod, inArgs, outArgs);
 
         Assert.NotNull(result);
-        Assert.Equal(StatusCodes.DeviceFailure, result.StatusCode);
+        Assert.Equal(StatusCodes.UnexpectedError, result.StatusCode);
+
+        Assert.Equal(2, outArgs.Count);
+        Assert.Equal(Array.Empty<byte>(), outArgs[0]);
+        Assert.Equal(OperationStatus.CommunicationError, outArgs[1]);
     }
 
     [Theory]
@@ -156,14 +160,20 @@ public class Calss3Test : IClassFixture {
         MethodState innerMethod = m_method.OpcUaMethod;
         Assert.NotNull(innerMethod);
 
+        const string readDataStr = "Read Data";
+
         ISystemContext callContext = Substitute.For<ISystemContext>();
 
         _ = m_fixture.ServiceMock.Configure().method().
-            ReturnsForAnyArgs(x => Task.FromResult(new methodResult(OperationStatus.Success, StatusCodes.Good, Encoding.ASCII.GetBytes("Read Data"))));
+            ReturnsForAnyArgs(x => Task.FromResult(new methodResult(OperationStatus.Success, StatusCodes.Good, Encoding.ASCII.GetBytes(readDataStr))));
 
         ServiceResult result = m_method.OnCall(callContext, innerMethod, inArgs, outArgs);
 
         Assert.NotNull(result);
         Assert.Equal(StatusCodes.Good, result.StatusCode);
+
+        Assert.Equal(2, outArgs.Count);
+        Assert.Equal(Encoding.ASCII.GetBytes(readDataStr), outArgs[0]);
+        Assert.Equal(OperationStatus.Success, outArgs[1]);
     }
 }
diff --git a/src/Test/Calss4Test.cs b/src/Test/Calss4Test.cs
--- a/src/Test/Calss4Test.cs
+++ b/src/Test/Calss4Test.cs
@@ -144,7 +144,7 @@ public class Calss4Test : IClassFixture {
         ServiceResult result = m_setTagPassword.OnCall(callContext, innerMethod, inArgs, outArgs);
 
         Assert.NotNull(result);
-        Assert.Equal(StatusCodes.DeviceFailure, result.StatusCode);
+        Assert.Equal(StatusCodes.UnexpectedError, result.StatusCode);
     }
 
     [Theory]
diff --git a/src/Test/Calss5Test.cs b/src/Test/Calss5Test.cs
--- a/src/Test/Calss5Test.cs
+++ b/src/Test/Calss5Test.cs
@@ -144,7 +144,7 @@ public class Calss5Test : IClassFixture {
         ServiceResult result = m_writeTagId.OnCall(callContext, innerMethod, inArgs, outArgs);
 
         Assert.NotNull(result);
-        Assert.Equal(StatusCodes.DeviceFailure, result.StatusCode);
+        Assert.Equal(StatusCodes.UnexpectedError, result.StatusCode);
     }
 
     [Theory]
diff --git a/src/Test/Calss6Test.cs b/src/Test/Calss6Test.cs
--- a/src/Test/Calss6Test.cs
+++ b/src/Test/Calss6Test.cs
@@ -144,7 +144,7 @@ public class Calss6Test : IClassFixture {
         ServiceResult result = m_writeTag.OnCall(callContext, innerMethod, inArgs, outArgs);
 
         Assert.NotNull(result);
-        Assert.Equal(StatusCodes.DeviceFailure, result.StatusCode);
+        Assert.Equal(StatusCodes.UnexpectedError, result.StatusCode);
     }
 
     [Theory]
diff --git a/src//BusinessLogic/Class1.cs b/src//BusinessLogic/Class1.cs
--- a/src//BusinessLogic/Class1.cs
+++ b/src//BusinessLogic/Class1.cs
@@ -53,8 +53,8 @@ internal class Class1()
 
             return response.StatusCode;
         } catch {
-            outputArguments[0] = OperationStatus.DeviceFault;
-            return StatusCodes.DeviceFailure;
+            outputArguments[0] = OperationStatus.CommunicationError;
+            return StatusCodes.UnexpectedError;
         }
     }
     #endregion
diff --git a/src//BusinessLogic/Calss2.cs b/src//BusinessLogic/Calss2.cs
--- a/src//BusinessLogic/Calss2.cs
+++ b/src//BusinessLogic/Calss2.cs
@@ -61,8 +61,8 @@ internal class Calss2()
 
             return response.StatusCode;
         } catch {
-            outputArguments[0] = OperationStatus.DeviceFault;
-            return StatusCodes.DeviceFailure;
+            outputArguments[0] = OperationStatus.CommunicationError;
+            return StatusCodes.UnexpectedError;
         }
     }
 
diff --git a/src//BusinessLogic/Calss3.cs b/src//BusinessLogic/Calss3.cs
--- a/src//BusinessLogic/Calss3.cs
+++ b/src//BusinessLogic/Calss3.cs
@@ -59,8 +59,9 @@ internal class Calss3()
 
             return response.StatusCode;
         } catch {
-            outputArguments[1] = OperationStatus.DeviceFault;
-            return StatusCodes.DeviceFailure;
+            outputArguments[0] = Array.Empty<byte>();
+            outputArguments[1] = OperationStatus.CommunicationError;
+            return StatusCodes.UnexpectedError;
         }
     }
 
diff --git a/src//BusinessLogic/Calss4.cs b/src//BusinessLogic/Calss4.cs
--- a/src//BusinessLogic/Calss4.cs
+++ b/src//BusinessLogic/Calss4.cs
@@ -55,8 +55,8 @@ internal class Calss4()
 
             return response.StatusCode;
         } catch {
-            outputArguments[0] = OperationStatus.DeviceFault;
-            return StatusCodes.DeviceFailure;
+            outputArguments[0] = OperationStatus.CommunicationError;
+            return StatusCodes.UnexpectedError;
         }
     }
 
diff --git a/src//BusinessLogic/Calss6.cs b/src//BusinessLogic/Calss6.cs
--- a/src//BusinessLogic/Calss6.cs
+++ b/src//BusinessLogic/Calss6.cs
@@ -57,8 +57,8 @@ internal class Calss6()
             return response.StatusCode;
 
         } catch {
-            outputArguments[0] = OperationStatus.DeviceFault;
-            return StatusCodes.DeviceFailure;
+            outputArguments[0] = OperationStatus.CommunicationError;
+            return StatusCodes.UnexpectedError;
         }
     }
 
diff --git a/src//BusinessLogic/Calss5.cs b/src//BusinessLogic/Calss5.cs
--- a/src//BusinessLogic/Calss5.cs
+++ b/src//BusinessLogic/Calss5.cs
@@ -57,8 +57,8 @@ internal class Calss5()
             return response.StatusCode;
 
         } catch {
-            outputArguments[0] = OperationStatus.DeviceFault;
-            return StatusCodes.DeviceFailure;
+            outputArguments[0] = OperationStatus.CommunicationError;
+            return StatusCodes.UnexpectedError;
         }
     }

Hi,

Can I have a screenshot of the duplication in SonarQube?

 
Thx,
Ann

Sure!

Hi,

I was actually looking for a screenshot of the code with both the new lines and the duplication marked. Something like this:

 
Ann

Sorry for the delay. I see the problem now! :slight_smile:
SonarQube detects some lines above and below as duplicates. Thus, it detects the two new lines as duplicates too.
Thanks! :slight_smile:

1 Like