Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

D39652_D39651_D39645 Mock Data Defect Fixed #3825

Merged
merged 2 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 64 additions & 22 deletions Ginger/GingerCoreNET/RosLynLib/CodeProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@ limitations under the License.
using Amdocs.Ginger.Common;
using Amdocs.Ginger.CoreNET.RosLynLib;
using Amdocs.Ginger.Repository;
using DocumentFormat.OpenXml.Office2010.ExcelAc;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
using OfficeOpenXml.Drawing.Slicer.Style;
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

Expand Down Expand Up @@ -65,13 +68,19 @@ public static string GetResult(string Expression)
"((?'Close-Open'})[^{}]*)+" +
")*" +
"(?(Open)(?!))";
pattern = "{CS({.*}|[^{}]*)*}";
Regex CsExppattern = new Regex("{CS Exp({.*}|[^{}]*)*}", RegexOptions.Compiled);


Pattern = new Regex(pattern);
Regex Clean = new Regex("{CS(\\s)*Exp(\\s)*=");
MatchCollection PatternMatchlist = CsExppattern.Matches(Expression);
if (PatternMatchlist == null || PatternMatchlist.Count == 0)
{
Reporter.ToLog(eLogLevel.DEBUG, Expression + System.Environment.NewLine + " not a valid c# expression to evaluate");
return string.Empty;
}

foreach (Match M in Pattern.Matches(Expression))
foreach (Match M in PatternMatchlist)
{
string csharpError = "";
string match = M.Value;
Expand All @@ -82,9 +91,7 @@ public static string GetResult(string Expression)
string evalresult = GetEvaluteResult(exp, out csharpError);
Expression = Expression.Replace(match, evalresult);
}

return Expression;

}

public static string GetEvaluteResult(string expression, out string error)
Expand All @@ -105,6 +112,15 @@ public static string GetEvaluteResult(string expression, out string error)
{
evalresult = result.ToString().ToLower();
}
else if(result.GetType() == typeof(string))
{
evalresult = result.ToString();
}
else if(result.GetType() == typeof(string[]))
{
evalresult = string.Join(",", (string[])result);
evalresult = $"[{evalresult}]";
}
else
{
evalresult = result.ToString();
Expand Down Expand Up @@ -254,26 +270,40 @@ public static object ExecuteNew(string code)
/// <returns></returns>
public static string GetBogusDataGenerateresult(string Expression)
{
if (!Expression.Contains(@"{MockDataExp"))
try
{
if (!Expression.Contains(@"{MockDataExp"))
{
return Expression;
}
Pattern = new Regex("^\\{MockDataExp Fun=.*\\}$", RegexOptions.Compiled, new TimeSpan(0, 0, 5));
Regex Clean = new Regex("{MockDataExp(\\s)*Fun(\\s)*=", RegexOptions.Compiled);
MatchCollection PatternMatchlist = Pattern.Matches(Expression);
if (PatternMatchlist == null || PatternMatchlist.Count == 0)
{
Reporter.ToLog(eLogLevel.DEBUG, Expression + System.Environment.NewLine + " not a valid c# expression to evaluate");
return string.Empty;
}

foreach (Match M in PatternMatchlist)
{
string Error = "";
string match = M.Value;
string exp = match;
exp = exp.Replace(Clean.Match(exp).Value, "");
exp = exp.Remove(exp.Length - 1);
string evalresult = GetBogusExpressionEvaluteResult(exp, out Error);
Expression = Expression.Replace(match, evalresult);
}
return Expression;
}
const string pattern = "{MockDataExp({.*}|[^{}]*)*}";
Pattern = new Regex(pattern, RegexOptions.Compiled);
Regex Clean = new Regex("{MockDataExp(\\s)*Fun(\\s)*=", RegexOptions.Compiled);

foreach (Match M in Pattern.Matches(Expression))
catch(RegexMatchTimeoutException ex)
{
string Error = "";
string match = M.Value;
string exp = match;
exp = exp.Replace(Clean.Match(exp).Value, "");
exp = exp.Remove(exp.Length - 1);
string evalresult = GetBogusExpressionEvaluteResult(exp, out Error);
Expression = Expression.Replace(match, evalresult);
Reporter.ToLog(eLogLevel.ERROR, "Timeout Exception", ex);
return string.Empty;
}
return Expression;
}

/// <summary>
/// The GetBogusExpressionEvaluteResult function is responsible for evaluating and generating data using Bogus library expressions based on the provided expression.
/// It handles different types of expressions related to data generation and returns the evaluated result as a string.
Expand All @@ -285,9 +315,9 @@ public static string GetBogusDataGenerateresult(string Expression)
/// <param name="expression"></param>
/// <param name="error"></param>
/// <returns></returns>
public static string GetBogusExpressionEvaluteResult(string expression, out string error)
public static string GetBogusExpressionEvaluteResult(string expression, out string evalresult)
{
error = string.Empty;
evalresult = string.Empty;
try
{
Assembly BogusAssembly = Assembly.Load("Bogus");
Expand Down Expand Up @@ -335,13 +365,25 @@ public static string GetBogusExpressionEvaluteResult(string expression, out stri
}

object result = CSharpScript.EvaluateAsync(expression, ScriptOptions.Default.WithReferences(BogusAssembly)).Result;
return result.ToString();
//c# generate True/False for bool.tostring which fails in subsequent expressions
if (result == null)
{
Reporter.ToLog(eLogLevel.DEBUG, $"{expression} evaluation returned null value");
}
else if (result.GetType() == typeof(int[]))
{
evalresult = string.Join(",", (int[])result);
}
else
{
evalresult = result.ToString();
}
}
catch (Exception e)
{
Reporter.ToLog(eLogLevel.DEBUG, expression + System.Environment.NewLine + " not a valid Bogus data generate expression to evaluate", e);
}
return error;
return evalresult;
}
}
}
93 changes: 53 additions & 40 deletions Ginger/GingerCoreNET/ValueExpressionLib/ValueExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ limitations under the License.
using GingerCore.GeneralLib;
using GingerCore.Variables;
using GingerCoreNET.RosLynLib;
using SikuliStandard.sikuli_REST;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text.RegularExpressions;

Expand Down Expand Up @@ -108,6 +110,8 @@ public class ValueExpression : IValueExpression
private static Regex rxe = new Regex(@"{RegEx" + rxVare + ".*}", RegexOptions.Compiled | RegexOptions.Singleline);

private static Regex rNestedfunc = new Regex("{Function(\\s)*Fun(\\s)*=(\\s)*([a-zA-Z]|\\d)*\\(([^()])*\\)}", RegexOptions.Compiled);
private static Regex MockDataExpPattern = new Regex("^\\{MockDataExp Fun=.*\\}$", RegexOptions.Compiled, new TimeSpan(0, 0, 5));
private static Regex CsExppattern = new Regex("{CS Exp({.*}|[^{}]*)*}", RegexOptions.Compiled);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Add timeout option to CsExppattern

The regex pattern CsExppattern is well-defined but lacks a timeout option. Consider adding a timeout option to prevent potential performance issues.

- private static Regex CsExppattern = new Regex("{CS Exp({.*}|[^{}]*)*}", RegexOptions.Compiled);
+ private static Regex CsExppattern = new Regex("{CS Exp({.*}|[^{}]*)*}", RegexOptions.Compiled, new TimeSpan(0, 0, 5));
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private static Regex CsExppattern = new Regex("{CS Exp({.*}|[^{}]*)*}", RegexOptions.Compiled);
private static Regex CsExppattern = new Regex("{CS Exp({.*}|[^{}]*)*}", RegexOptions.Compiled, new TimeSpan(0, 0, 5));


// Enable setting value simply by assigned string,
// so no need to create new VE class everywhere in code
Expand Down Expand Up @@ -1728,50 +1732,59 @@ private void ReplaceVarWithValue(string p, string[] a)

private bool ContainsFormula(string mValueCalculated)
{
if (rxGlobalParamPattern.IsMatch(mValueCalculated))
{
return true;
}
else if (rxEnvParamPattern.IsMatch(mValueCalculated))
{
return true;
}
else if (rxEnvUrlPattern.IsMatch(mValueCalculated))
{
return true;
}
else if (rxe.IsMatch(mValueCalculated))
{
return true;
}
else if (VBSRegex.IsMatch(mValueCalculated))
{
return true;
}
else if (rNestedfunc.IsMatch(mValueCalculated))
{
return true;
}
else if (rxDSPattern.IsMatch(mValueCalculated))
{
return true;
}
else if (rxFDPattern.IsMatch(mValueCalculated))
{
return true;
}
else if (rxExecutionJsonDataPattern.IsMatch(mValueCalculated))
try
{
return true;
if (rxGlobalParamPattern.IsMatch(mValueCalculated))
{
return true;
}
else if (rxEnvParamPattern.IsMatch(mValueCalculated))
{
return true;
}
else if (rxEnvUrlPattern.IsMatch(mValueCalculated))
{
return true;
}
else if (rxe.IsMatch(mValueCalculated))
{
return true;
}
else if (VBSRegex.IsMatch(mValueCalculated))
{
return true;
}
else if (rNestedfunc.IsMatch(mValueCalculated))
{
return true;
}
else if (rxDSPattern.IsMatch(mValueCalculated))
{
return true;
}
else if (rxFDPattern.IsMatch(mValueCalculated))
{
return true;
}
else if (rxExecutionJsonDataPattern.IsMatch(mValueCalculated))
{
return true;
}
else if (CsExppattern.IsMatch(mValueCalculated))
{
return true;
}
else if (MockDataExpPattern.IsMatch(mValueCalculated))
{
return true;
}
}
else if (mValueCalculated.Contains(@"{CS"))
catch (RegexMatchTimeoutException ex)
{
return true;
}
else if(mValueCalculated.Contains(@"{MockDataExp"))
{
return true;
Reporter.ToLog(eLogLevel.ERROR, "Timeout Exception", ex);
return false;
}

return false;
}

Expand Down
11 changes: 8 additions & 3 deletions Ginger/GingerCoreNETUnitTest/RosLynTestLib/GlobalsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ limitations under the License.
using GingerCoreNET.RosLynLib;
using GingerTestHelper;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NPOI.SS.Formula.Functions;
using OpenTracing.Tag;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace GingerCoreNETUnitTest.RosLynTestLib
{
Expand Down Expand Up @@ -300,7 +305,7 @@ public void TestBogusData_RandomizerNumber_IsNotnullAndEmpty()
string Expression = "{MockDataExp Fun=Randomizer().Number(1,10);}";
string error = string.Empty;
string output = CodeProcessor.GetBogusDataGenerateresult(Expression);
Assert.IsTrue(output != null && !output.Equals(string.Empty));
Assert.IsTrue(output != null && !output.Equals(string.Empty) && Regex.IsMatch(output, @"\d"));
}

[TestMethod]
Expand All @@ -309,7 +314,7 @@ public void TestBogusData_RandomizerDigits_IsNotnullAndEmpty()
string Expression = "{MockDataExp Fun=Randomizer().Digits(3,0,9);}";
string error = string.Empty;
string output = CodeProcessor.GetBogusDataGenerateresult(Expression);
Assert.IsTrue(output != null && !output.Equals(string.Empty));
Assert.IsTrue(output != null && !output.Equals(string.Empty) && output.Split(",").Select(i => i.Trim()).All(x=> Regex.IsMatch(x, @"\d")));
}

[TestMethod]
Expand All @@ -318,7 +323,7 @@ public void TestBogusData_RandomizerDecimal_IsNotnullAndEmpty()
string Expression = "{MockDataExp Fun=Randomizer().Decimal();}";
string error = string.Empty;
string output = CodeProcessor.GetBogusDataGenerateresult(Expression);
Assert.IsTrue(output != null && !output.Equals(string.Empty));
Assert.IsTrue(output != null && !output.Equals(string.Empty) && Regex.IsMatch(output, "^[+-]?(\\d*\\.)?\\d+$"));
}

[TestMethod]
Expand Down
Loading