From aad9370644de546cd38f9dafac53f7c5ec0c8357 Mon Sep 17 00:00:00 2001 From: pranjal2004838 Date: Fri, 22 May 2026 09:12:53 +0530 Subject: [PATCH] fix(csharp): implement translators for SignatureContext, PRNGContext, and ProtocolContext Previously, CSharpTranslator returned Optional.empty() for SignatureContext, PRNGContext, and ProtocolContext, causing detected crypto assets (RSA signing, ECDSA, random number generation, TLS protocols) to be silently discarded from CBOM output. This commit adds three new context translators: - CSharpSignatureContextTranslator: maps RSA, ECDSA, DSA to signature nodes - CSharpPRNGContextTranslator: maps .NET random generators to PRNG nodes - CSharpProtocolContextTranslator: maps TLS and generic protocols to protocol nodes Also adds corresponding unit tests for each translator. Fixes silent data loss in C# crypto detection pipeline. Signed-off-by: pranjal2004838 --- .../translator/CSharpTranslator.java | 20 ++- .../contexts/CSharpPRNGContextTranslator.java | 62 +++++++ .../CSharpProtocolContextTranslator.java | 60 +++++++ .../CSharpSignatureContextTranslator.java | 82 +++++++++ .../CSharpPRNGContextTranslatorTest.java | 109 ++++++++++++ .../CSharpProtocolContextTranslatorTest.java | 75 +++++++++ .../CSharpSignatureContextTranslatorTest.java | 157 ++++++++++++++++++ 7 files changed, 561 insertions(+), 4 deletions(-) create mode 100644 csharp/src/main/java/com/ibm/plugin/translation/translator/contexts/CSharpPRNGContextTranslator.java create mode 100644 csharp/src/main/java/com/ibm/plugin/translation/translator/contexts/CSharpProtocolContextTranslator.java create mode 100644 csharp/src/main/java/com/ibm/plugin/translation/translator/contexts/CSharpSignatureContextTranslator.java create mode 100644 csharp/src/test/java/com/ibm/plugin/translation/translator/contexts/CSharpPRNGContextTranslatorTest.java create mode 100644 csharp/src/test/java/com/ibm/plugin/translation/translator/contexts/CSharpProtocolContextTranslatorTest.java create mode 100644 csharp/src/test/java/com/ibm/plugin/translation/translator/contexts/CSharpSignatureContextTranslatorTest.java diff --git a/csharp/src/main/java/com/ibm/plugin/translation/translator/CSharpTranslator.java b/csharp/src/main/java/com/ibm/plugin/translation/translator/CSharpTranslator.java index 793796b3f..8258cc487 100755 --- a/csharp/src/main/java/com/ibm/plugin/translation/translator/CSharpTranslator.java +++ b/csharp/src/main/java/com/ibm/plugin/translation/translator/CSharpTranslator.java @@ -42,6 +42,9 @@ import com.ibm.plugin.translation.translator.contexts.CSharpDigestContextTranslator; import com.ibm.plugin.translation.translator.contexts.CSharpKeyContextTranslator; import com.ibm.plugin.translation.translator.contexts.CSharpMacContextTranslator; +import com.ibm.plugin.translation.translator.contexts.CSharpPRNGContextTranslator; +import com.ibm.plugin.translation.translator.contexts.CSharpProtocolContextTranslator; +import com.ibm.plugin.translation.translator.contexts.CSharpSignatureContextTranslator; import java.util.List; import java.util.Optional; import javax.annotation.Nonnull; @@ -88,10 +91,19 @@ public Optional translate( .translate(bundleIdentifier, value, detectionValueContext, detectionLocation); } - if (detectionValueContext.is(PRNGContext.class) - || detectionValueContext.is(SignatureContext.class) - || detectionValueContext.is(ProtocolContext.class)) { - return Optional.empty(); + if (detectionValueContext.is(PRNGContext.class)) { + return new CSharpPRNGContextTranslator() + .translate(bundleIdentifier, value, detectionValueContext, detectionLocation); + } + + if (detectionValueContext.is(SignatureContext.class)) { + return new CSharpSignatureContextTranslator() + .translate(bundleIdentifier, value, detectionValueContext, detectionLocation); + } + + if (detectionValueContext.is(ProtocolContext.class)) { + return new CSharpProtocolContextTranslator() + .translate(bundleIdentifier, value, detectionValueContext, detectionLocation); } return Optional.empty(); diff --git a/csharp/src/main/java/com/ibm/plugin/translation/translator/contexts/CSharpPRNGContextTranslator.java b/csharp/src/main/java/com/ibm/plugin/translation/translator/contexts/CSharpPRNGContextTranslator.java new file mode 100644 index 000000000..06c17a46d --- /dev/null +++ b/csharp/src/main/java/com/ibm/plugin/translation/translator/contexts/CSharpPRNGContextTranslator.java @@ -0,0 +1,62 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2024 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.translation.translator.contexts; + +import com.ibm.engine.language.csharp.tree.CSharpTree; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.IDetectionContext; +import com.ibm.engine.rule.IBundle; +import com.ibm.mapper.IContextTranslation; +import com.ibm.mapper.model.Algorithm; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.PseudorandomNumberGenerator; +import com.ibm.mapper.utils.DetectionLocation; +import java.util.Optional; +import javax.annotation.Nonnull; + +/** Translates {@link com.ibm.engine.model.context.PRNGContext} detections for .NET APIs. */ +public final class CSharpPRNGContextTranslator implements IContextTranslation { + + @Override + public @Nonnull Optional translate( + @Nonnull IBundle bundleIdentifier, + @Nonnull IValue value, + @Nonnull IDetectionContext detectionContext, + @Nonnull DetectionLocation detectionLocation) { + + if (value instanceof ValueAction) { + String valueStr = value.asString().toUpperCase().trim(); + + // Map .NET random number generator types to PRNG nodes + if (valueStr.contains("RANDOMNUMBERGENERATOR") + || valueStr.contains("RNGCRYPTOSERVICEPROVIDER") + || valueStr.contains("RANDOM")) { + return Optional.of( + new Algorithm( + valueStr, PseudorandomNumberGenerator.class, detectionLocation)); + } + + return Optional.empty(); + } + + return Optional.empty(); + } +} diff --git a/csharp/src/main/java/com/ibm/plugin/translation/translator/contexts/CSharpProtocolContextTranslator.java b/csharp/src/main/java/com/ibm/plugin/translation/translator/contexts/CSharpProtocolContextTranslator.java new file mode 100644 index 000000000..4f18aa599 --- /dev/null +++ b/csharp/src/main/java/com/ibm/plugin/translation/translator/contexts/CSharpProtocolContextTranslator.java @@ -0,0 +1,60 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2024 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.translation.translator.contexts; + +import com.ibm.engine.language.csharp.tree.CSharpTree; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.IDetectionContext; +import com.ibm.engine.model.context.ProtocolContext; +import com.ibm.engine.rule.IBundle; +import com.ibm.mapper.IContextTranslation; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Protocol; +import com.ibm.mapper.model.protocol.TLS; +import com.ibm.mapper.utils.DetectionLocation; +import java.util.Optional; +import javax.annotation.Nonnull; + +/** Translates {@link com.ibm.engine.model.context.ProtocolContext} detections for .NET APIs. */ +public final class CSharpProtocolContextTranslator implements IContextTranslation { + + @Override + public @Nonnull Optional translate( + @Nonnull IBundle bundleIdentifier, + @Nonnull IValue value, + @Nonnull IDetectionContext detectionContext, + @Nonnull DetectionLocation detectionLocation) { + + if (value instanceof ValueAction valueAction) { + String valueStr = valueAction.asString().toUpperCase().trim(); + + // Map TLS protocol + if (valueStr.equals("TLS")) { + return Optional.of(new TLS(detectionLocation)); + } + + // Generic protocol fallback + return Optional.of(new Protocol(valueStr, detectionLocation)); + } + + return Optional.empty(); + } +} diff --git a/csharp/src/main/java/com/ibm/plugin/translation/translator/contexts/CSharpSignatureContextTranslator.java b/csharp/src/main/java/com/ibm/plugin/translation/translator/contexts/CSharpSignatureContextTranslator.java new file mode 100644 index 000000000..5b968a8bb --- /dev/null +++ b/csharp/src/main/java/com/ibm/plugin/translation/translator/contexts/CSharpSignatureContextTranslator.java @@ -0,0 +1,82 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2024 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.translation.translator.contexts; + +import com.ibm.engine.language.csharp.tree.CSharpTree; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.IDetectionContext; +import com.ibm.engine.rule.IBundle; +import com.ibm.mapper.IContextTranslation; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.algorithms.DSA; +import com.ibm.mapper.model.algorithms.ECDSA; +import com.ibm.mapper.model.algorithms.RSA; +import com.ibm.mapper.model.functionality.Sign; +import com.ibm.mapper.model.functionality.Verify; +import com.ibm.mapper.utils.DetectionLocation; +import java.util.Optional; +import javax.annotation.Nonnull; + +/** Translates {@link com.ibm.engine.model.context.SignatureContext} detections for .NET APIs. */ +public final class CSharpSignatureContextTranslator implements IContextTranslation { + + @Override + public @Nonnull Optional translate( + @Nonnull IBundle bundleIdentifier, + @Nonnull IValue value, + @Nonnull IDetectionContext detectionContext, + @Nonnull DetectionLocation detectionLocation) { + + if (value instanceof ValueAction) { + String valueStr = value.asString().toUpperCase().trim(); + + // RSA-related signature values + if (valueStr.startsWith("RSA")) { + return Optional.of(new RSA(Signature.class, detectionLocation)); + } + + // ECDSA + if (valueStr.equals("ECDSA")) { + return Optional.of(new ECDSA(detectionLocation)); + } + + // DSA + if (valueStr.equals("DSA")) { + return Optional.of(new DSA(detectionLocation)); + } + + return Optional.empty(); + } else if (value instanceof SignatureAction signatureAction) { + switch (signatureAction.getAction()) { + case SIGN: + return Optional.of(new Sign(detectionLocation)); + case VERIFY: + return Optional.of(new Verify(detectionLocation)); + default: + return Optional.empty(); + } + } + + return Optional.empty(); + } +} diff --git a/csharp/src/test/java/com/ibm/plugin/translation/translator/contexts/CSharpPRNGContextTranslatorTest.java b/csharp/src/test/java/com/ibm/plugin/translation/translator/contexts/CSharpPRNGContextTranslatorTest.java new file mode 100644 index 000000000..e69e88376 --- /dev/null +++ b/csharp/src/test/java/com/ibm/plugin/translation/translator/contexts/CSharpPRNGContextTranslatorTest.java @@ -0,0 +1,109 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2024 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.translation.translator.contexts; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.PRNGContext; +import com.ibm.engine.rule.IDetectionRule; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.PseudorandomNumberGenerator; +import com.ibm.mapper.utils.DetectionLocation; +import java.util.Optional; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; + +class CSharpPRNGContextTranslatorTest { + + @Test + void testRandomNumberGenerator() { + CSharpPRNGContextTranslator translator = new CSharpPRNGContextTranslator(); + DetectionLocation location = new DetectionLocation("test.cs", 1, 0, java.util.List.of(), new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "test"; } + }); + + ValueAction value = new ValueAction<>("RandomNumberGenerator"); + PRNGContext context = new PRNGContext(); + + Optional result = translator.translate(new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "DotNet"; } + }, value, context, location); + + assertThat(result).isPresent(); + INode node = result.get(); + assertThat(node.getKind()).isEqualTo(PseudorandomNumberGenerator.class); + } + + @Test + void testRNGCryptoServiceProvider() { + CSharpPRNGContextTranslator translator = new CSharpPRNGContextTranslator(); + DetectionLocation location = new DetectionLocation("test.cs", 1, 0, java.util.List.of(), new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "test"; } + }); + + ValueAction value = new ValueAction<>("RNGCryptoServiceProvider"); + PRNGContext context = new PRNGContext(); + + Optional result = translator.translate(new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "DotNet"; } + }, value, context, location); + + assertThat(result).isPresent(); + INode node = result.get(); + assertThat(node.getKind()).isEqualTo(PseudorandomNumberGenerator.class); + } + + @Test + void testRandom() { + CSharpPRNGContextTranslator translator = new CSharpPRNGContextTranslator(); + DetectionLocation location = new DetectionLocation("test.cs", 1, 0, java.util.List.of(), new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "test"; } + }); + + ValueAction value = new ValueAction<>("Random"); + PRNGContext context = new PRNGContext(); + + Optional result = translator.translate(new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "DotNet"; } + }, value, context, location); + + assertThat(result).isPresent(); + INode node = result.get(); + assertThat(node.getKind()).isEqualTo(PseudorandomNumberGenerator.class); + } + + @Test + void testUnknownValue() { + CSharpPRNGContextTranslator translator = new CSharpPRNGContextTranslator(); + DetectionLocation location = new DetectionLocation("test.cs", 1, 0, java.util.List.of(), new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "test"; } + }); + + ValueAction value = new ValueAction<>("UnknownCrypto"); + PRNGContext context = new PRNGContext(); + + Optional result = translator.translate(new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "DotNet"; } + }, value, context, location); + + assertThat(result).isEmpty(); + } +} diff --git a/csharp/src/test/java/com/ibm/plugin/translation/translator/contexts/CSharpProtocolContextTranslatorTest.java b/csharp/src/test/java/com/ibm/plugin/translation/translator/contexts/CSharpProtocolContextTranslatorTest.java new file mode 100644 index 000000000..fd51b7a65 --- /dev/null +++ b/csharp/src/test/java/com/ibm/plugin/translation/translator/contexts/CSharpProtocolContextTranslatorTest.java @@ -0,0 +1,75 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2024 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.translation.translator.contexts; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.ProtocolContext; +import com.ibm.engine.rule.IDetectionRule; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Protocol; +import com.ibm.mapper.model.protocol.TLS; +import com.ibm.mapper.utils.DetectionLocation; +import java.util.Optional; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; + +class CSharpProtocolContextTranslatorTest { + + @Test + void testTLS() { + CSharpProtocolContextTranslator translator = new CSharpProtocolContextTranslator(); + DetectionLocation location = new DetectionLocation("test.cs", 1, 0, java.util.List.of(), new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "test"; } + }); + + ValueAction value = new ValueAction<>("TLS"); + ProtocolContext context = new ProtocolContext(); + + Optional result = translator.translate(new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "DotNet"; } + }, value, context, location); + + assertThat(result).isPresent(); + INode node = result.get(); + assertThat(node.getKind()).isEqualTo(TLS.class); + } + + @Test + void testGenericProtocol() { + CSharpProtocolContextTranslator translator = new CSharpProtocolContextTranslator(); + DetectionLocation location = new DetectionLocation("test.cs", 1, 0, java.util.List.of(), new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "test"; } + }); + + ValueAction value = new ValueAction<>("SSL"); + ProtocolContext context = new ProtocolContext(); + + Optional result = translator.translate(new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "DotNet"; } + }, value, context, location); + + assertThat(result).isPresent(); + INode node = result.get(); + assertThat(node.getKind()).isEqualTo(Protocol.class); + assertThat(node.asString()).isEqualTo("SSL"); + } +} diff --git a/csharp/src/test/java/com/ibm/plugin/translation/translator/contexts/CSharpSignatureContextTranslatorTest.java b/csharp/src/test/java/com/ibm/plugin/translation/translator/contexts/CSharpSignatureContextTranslatorTest.java new file mode 100644 index 000000000..61f3f64ff --- /dev/null +++ b/csharp/src/test/java/com/ibm/plugin/translation/translator/contexts/CSharpSignatureContextTranslatorTest.java @@ -0,0 +1,157 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2024 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.translation.translator.contexts; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.SignatureContext; +import com.ibm.engine.rule.IDetectionRule; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.algorithms.DSA; +import com.ibm.mapper.model.algorithms.ECDSA; +import com.ibm.mapper.model.algorithms.RSA; +import com.ibm.mapper.model.functionality.Sign; +import com.ibm.mapper.model.functionality.Verify; +import com.ibm.mapper.utils.DetectionLocation; +import java.util.Optional; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; + +class CSharpSignatureContextTranslatorTest { + + @Test + void testRSA() { + CSharpSignatureContextTranslator translator = new CSharpSignatureContextTranslator(); + DetectionLocation location = new DetectionLocation("test.cs", 1, 0, java.util.List.of(), new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "test"; } + }); + + ValueAction value = new ValueAction<>("RSA"); + SignatureContext context = new SignatureContext(); + + Optional result = translator.translate(new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "DotNet"; } + }, value, context, location); + + assertThat(result).isPresent(); + INode node = result.get(); + assertThat(node.getKind()).isEqualTo(RSA.class); + assertThat(node.asString()).isEqualTo("RSA"); + } + + @Test + void testECDSA() { + CSharpSignatureContextTranslator translator = new CSharpSignatureContextTranslator(); + DetectionLocation location = new DetectionLocation("test.cs", 1, 0, java.util.List.of(), new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "test"; } + }); + + ValueAction value = new ValueAction<>("ECDSA"); + SignatureContext context = new SignatureContext(); + + Optional result = translator.translate(new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "DotNet"; } + }, value, context, location); + + assertThat(result).isPresent(); + INode node = result.get(); + assertThat(node.getKind()).isEqualTo(ECDSA.class); + assertThat(node.asString()).isEqualTo("ECDSA"); + } + + @Test + void testDSA() { + CSharpSignatureContextTranslator translator = new CSharpSignatureContextTranslator(); + DetectionLocation location = new DetectionLocation("test.cs", 1, 0, java.util.List.of(), new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "test"; } + }); + + ValueAction value = new ValueAction<>("DSA"); + SignatureContext context = new SignatureContext(); + + Optional result = translator.translate(new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "DotNet"; } + }, value, context, location); + + assertThat(result).isPresent(); + INode node = result.get(); + assertThat(node.getKind()).isEqualTo(DSA.class); + assertThat(node.asString()).isEqualTo("DSA"); + } + + @Test + void testSignAction() { + CSharpSignatureContextTranslator translator = new CSharpSignatureContextTranslator(); + DetectionLocation location = new DetectionLocation("test.cs", 1, 0, java.util.List.of(), new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "test"; } + }); + + SignatureAction value = new SignatureAction<>(SignatureAction.Action.SIGN); + SignatureContext context = new SignatureContext(); + + Optional result = translator.translate(new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "DotNet"; } + }, value, context, location); + + assertThat(result).isPresent(); + INode node = result.get(); + assertThat(node.getKind()).isEqualTo(Signature.class); + assertThat(node.getKind()).isEqualTo(Sign.class); + } + + @Test + void testVerifyAction() { + CSharpSignatureContextTranslator translator = new CSharpSignatureContextTranslator(); + DetectionLocation location = new DetectionLocation("test.cs", 1, 0, java.util.List.of(), new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "test"; } + }); + + SignatureAction value = new SignatureAction<>(SignatureAction.Action.VERIFY); + SignatureContext context = new SignatureContext(); + + Optional result = translator.translate(new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "DotNet"; } + }, value, context, location); + + assertThat(result).isPresent(); + INode node = result.get(); + assertThat(node.getKind()).isEqualTo(Verify.class); + } + + @Test + void testUnknownValue() { + CSharpSignatureContextTranslator translator = new CSharpSignatureContextTranslator(); + DetectionLocation location = new DetectionLocation("test.cs", 1, 0, java.util.List.of(), new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "test"; } + }); + + ValueAction value = new ValueAction<>("UNKNOWN"); + SignatureContext context = new SignatureContext(); + + Optional result = translator.translate(new IDetectionRule() { + @Nonnull @Override public String getIdentifier() { return "DotNet"; } + }, value, context, location); + + assertThat(result).isEmpty(); + } +}