I have the following PexMethod:
[PexMethod]
public bool fwAlertConfig_objectConfigExists(
[PexAssumeUnderTest]WinCC target,
[PexAssumeNotNull] List<mixed> alertConfigObject,
[PexAssumeNotNull] ref int configType,
[PexAssumeNotNull] ref List<string> exceptionInfo
)
{
PexAssume.TrueForAll(alertConfigObject, x => x.value != null);
PexAssume.AreElementsNotNull(alertConfigObject);
bool result
= target.fwAlertConfig_objectConfigExists(alertConfigObject, ref configType, ref exceptionInfo);
return result;
}
I deliberately placed the [PexAssumeNotNull] and PexAssume there. However,
it seems that these things are ignored when I "Run Pex explorations" these are the inputs created:
Please notice the following:
in exceptionInfo is null in every line, although it has [PexAssumeNotNull]
line 2: alertConfigObject is {null}, although I defined PexAssume.AreElementsNotNull(alertConfigObject)
line 4: new mixed has {value=null}, although I defined
PexAssume.TrueForAll(alertConfigObject, x => x.value != null)
However: [PexAssumeNotNull] works well for alertConfigObject, as I do not see null as an input anymore.
So why are the other assumptions not working?
I couldn't test it, because you didn't provide the code under test, but you can try to replace the [PexAssumeNotNull] attribute with the static method PexAssume.IsNotNull, like this:
[PexMethod]
public bool fwAlertConfig_objectConfigExists(
WinCC target,
List<mixed> alertConfigObject,
ref int configType,
ref List<string> exceptionInfo)
{
PexAssume.IsNotNull(target);
PexAssume.IsNotNull(alertConfigObject);
PexAssume.IsNotNull(configType);
PexAssume.IsNotNull(exceptionInfo);
PexAssume.TrueForAll(alertConfigObject, x => x.value != null);
PexAssume.AreElementsNotNull(alertConfigObject);
bool result
= target.fwAlertConfig_objectConfigExists(alertConfigObject, ref configType, ref exceptionInfo);
return result;
}
Related
Im a bit confused with whats happening bellow:
Can anyone explain me why is dataType keep saying StatisticData instead of SibsMonthly??
dataType is a enum? passad as ref param to this method and its initialized as null before the method call..
Here is the code:
string errorMessage = null;
Enums.Uploads.DataType? dataType = null;
if (ValidadeFile(file, ref errorMessage, ref dataType))
{
...
}
private bool ValidadeFile(IBrowserFile file, ref string errorMessage, ref Enums.Uploads.DataType? dataType)
{
List<string> acceptedFileTypes = new List<string>
{
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
};
var valid = true;
if (AcceptedFileNames != null && AcceptedFileNames.Length > 0)
{
var tmp = AcceptedFileNames.Where(x => new Regex(x.Regex).IsMatch(file.Name))
.OrderByDescending(x => x.DataType)
.Select(x => x.DataType)
.FirstOrDefault();
dataType = tmp;
if (dataType == null)
{
valid = false;
errorMessage = Constants.Uploads.Error.InvalidFileName;
}
}
...
}
The WASM debugger doesn't seem to like ref variables, it seems to look at their address, not their value:
Inspecting them at their call site or in the Debug window behaves as expected; this is a debugger isssue.
While looking though some code of the project I'm working on, I've come across a pretty hefty method which does
the following:
public string DataField(int id, string fieldName)
{
var data = _dataRepository.Find(id);
if (data != null)
{
if (data.A == null)
{
data.A = fieldName;
_dataRepository.InsertOrUpdate(data);
return "A";
}
if (data.B == null)
{
data.B = fieldName;
_dataRepository.InsertOrUpdate(data);
return "B";
}
// keep going data.C through data.Z doing the exact same code
}
}
Obviously having 26 if statements just to determine if a property is null and then to update that property and do a database call is
probably very naive in implementation. What would be a better way of doing this unit of work?
Thankfully C# is able to inspect and assign class members dynamically, so one option would be to create a map list and iterate over that.
public string DataField(int id, string fieldName)
{
var data = _dataRepository.Find(id);
List<string> props = new List<string>();
props.Add("A");
props.Add("B");
props.Add("C");
if (data != null)
{
Type t = typeof(data).GetType();
foreach (String entry in props) {
PropertyInfo pi = t.GetProperty(entry);
if (pi.GetValue(data) == null) {
pi.SetValue(data, fieldName);
_dataRepository.InsertOrUpdate(data);
return entry;
}
}
}
}
You could just loop through all the character from 'A' to 'Z'. It gets difficult because you want to access an attribute of your 'data' object with the corresponding name, but that should (as far as I know) be possible through the C# reflection functionality.
While you get rid of the consecutive if-statements this still won't make your code nice :P
there is a fancy linq solution for your problem using reflection:
but as it was said before: your datastructure is not very well thought through
public String DataField(int id, string fieldName)
{
var data = new { Z = "test", B="asd"};
Type p = data.GetType();
var value = (from System.Reflection.PropertyInfo fi
in p.GetProperties().OrderBy((fi) => fi.Name)
where fi.Name.Length == 1 && fi.GetValue(data, null) != null
select fi.Name).FirstOrDefault();
return value;
}
ta taaaaaaaaa
like that you get the property but the update is not yet done.
var data = _dataRepository.Find(id);
If possible, you should use another DataType without those 26 properties. That new DataType should have 1 property and the Find method should return an instance of that new DataType; then, you could get rid of the 26 if in a more natural way.
To return "A", "B" ... "Z", you could use this:
return (char)65; //In this example this si an "A"
And work with some transformation from data.Value to a number between 65 and 90 (A to Z).
Since you always set the lowest alphabet field first and return, you can use an additional field in your class that tracks the first available field. For example, this can be an integer lowest_alphabet_unset and you'd update it whenever you set data.{X}:
Init:
lowest_alphabet_unset = 0;
In DataField:
lowest_alphabet_unset ++;
switch (lowest_alphabet_unset) {
case 1:
/* A is free */
/* do something */
return 'A';
[...]
case 7:
/* A through F taken */
data.G = fieldName;
_dataRepository.InsertOrUpdate(data);
return 'G';
[...]
}
N.B. -- do not use, if data is object rather that structure.
what comes to my mind is that, if A-Z are all same type, then you could theoretically access memory directly to check for non null values.
start = &data;
for (i = 0; i < 26; i++){
if ((typeof_elem) *(start + sizeof(elem)*i) != null){
*(start + sizeof(elem)*i) = fieldName;
return (char) (65 + i);
}
}
not tested but to give an idea ;)
Before someone shouts out the answer, please read the question through.
What is the purpose of the method in .NET 4.0's ExpressionVisitor:
public static ReadOnlyCollection<T> Visit<T>(ReadOnlyCollection<T> nodes, Func<T, T> elementVisitor)
My first guess as to the purpose of this method was that it would visit each node in each tree specified by the nodes parameter and rewrite the tree using the result of the elementVisitor function.
This does not appear to be the case. Actually this method appears to do a little more than nothing, unless I'm missing something here, which I strongly suspect I am...
I tried to use this method in my code and when things didn't work out as expected, I reflectored the method and found:
public static ReadOnlyCollection<T> Visit<T>(ReadOnlyCollection<T> nodes, Func<T, T> elementVisitor)
{
T[] list = null;
int index = 0;
int count = nodes.Count;
while (index < count)
{
T objA = elementVisitor(nodes[index]);
if (list != null)
{
list[index] = objA;
}
else if (!object.ReferenceEquals(objA, nodes[index]))
{
list = new T[count];
for (int i = 0; i < index; i++)
{
list[i] = nodes[i];
}
list[index] = objA;
}
index++;
}
if (list == null)
{
return nodes;
}
return new TrueReadOnlyCollection<T>(list);
}
So where would someone actually go about using this method? What am I missing here?
Thanks.
It looks to me like a convenience method to apply an aribitrary transform function to an expression tree, and return the resulting transformed tree, or the original tree if there is no change.
I can't see how this is any different of a pattern that a standard expression visitor, other than except for using a visitor type, it uses a function.
As for usage:
Expression<Func<int, int, int>> addLambdaExpression= (a, b) => a + b;
// Change add to subtract
Func<Expression, Expression> changeToSubtract = e =>
{
if (e is BinaryExpression)
{
return Expression.Subtract((e as BinaryExpression).Left,
(e as BinaryExpression).Right);
}
else
{
return e;
}
};
var nodes = new Expression[] { addLambdaExpression.Body }.ToList().AsReadOnly();
var subtractExpression = ExpressionVisitor.Visit(nodes, changeToSubtract);
You don't explain how you expected it to behave and why therefore you think it does little more than nothing.
Okay first to explain the rules:
I need a function that constructs a delegate matching any delegate type that encapsulates a body of which invokes a delegate of type (Object) (Object[] args) with 'args' containing all of the arguments passed to the original delegate during invocation.
My work so far:
delegate void TestDelegate(int x, int y);
delegate object TestDelegate2(object[] args);
static void Main(string[] sargs)
{
TestDelegate d = (TestDelegate)CreateAnonymousFromType(typeof(TestDelegate));
object ret = d.DynamicInvoke(2, 6);
if (ret != null) { Console.WriteLine(ret); }
Console.ReadKey();
}
static void SpecialInvoke(int x, int y)
{
Console.WriteLine("x: {0}\r\ny: {1}", x, y);
}
static Delegate CreateAnonymousFromType(Type type)
{
MethodInfo method = type.GetMethod("Invoke");
TestDelegate2 _delegate = new TestDelegate2(
delegate(object[] args)
{
Console.WriteLine("x: {0}\r\ny: {1}", args[0], args[1]);
return "This is the return";
});
var typeargs = CreateArgs(method.GetParameters());
var argindex = -1;
var tmp = Expression.Parameter(typeof(Object), "tmp");
var index = Expression.Parameter(typeof(int), "index");
var length = Expression.Constant(typeargs.Length);
var _break = Expression.Label("breakto");
var delegateargs = Expression.Parameter(typeof(object[]), "args");
return Expression.Lambda(
type,
Expression.Block(
new[] { tmp, index, delegateargs },
Expression.Assign(index, Expression.Constant(0)),
Expression.Assign(delegateargs, Expression.NewArrayBounds(typeof(Object), length)),
Expression.Loop(
Expression.IfThenElse(Expression.LessThan(index, length),
Expression.Block(
Expression.Assign(tmp, Expression.Convert(typeargs[++argindex], typeof(Object))),
Expression.Assign(Expression.ArrayAccess(delegateargs, index), tmp),
Expression.PostIncrementAssign(index)
),
Expression.Break(_break)
),
_break
),
Expression.Call(_delegate.Method, delegateargs)
),
typeargs
).Compile();
}
static ParameterExpression[] CreateArgs(ParameterInfo[] _params)
{
ParameterExpression[] ret = new ParameterExpression[_params.Length];
for (int i = 0; i < ret.Length; i++)
ret[i] = Expression.Parameter(_params[i].ParameterType, _params[i].Name);
return ret;
}
Now this SORTA works... I only get the value of typeargs[0] passed to the delegate "TestDelegate2" for both parameters x and y, the 'args' parameter at runtime is object[] { 2, 2 } and I can't for the life of me find a way to increment "argindex" inside the scope of the argument iteration... parameter count at compile time is indefinate.
Anybody know how I can solve this?
I've tried just copying the argument array using Expression.NewArrayInit(typeof(Object), typeargs) but that fails saying it can't use Int32 to initialize an array of Object
I've also tried this:
var arguments = Expression.Constant(typeargs);
And accessing the value of "arguments" at "index", however this produces the strings "x" and "y" .. apparently the names of the arguments and not their values.
This is honestly my first major attempt at using expression trees so any help.. no matter how little. Would be appreciated.
Thank you.
I think you were on the right track with Expression.NewArrayInit. You can fix the "An expression of type 'System.Int32' cannot be used to initialize an array of type 'System.Object'" error by using Expression.Convert to insert a conversion for each parameter:
var typeargs = CreateArgs(method.GetParameters());
return Expression.Lambda(
type,
Expression.Call(_delegate.Method, Expression.NewArrayInit(typeof(object),
typeargs.Select(arg => Expression.Convert(arg, typeof(object)))
)),
typeargs
).Compile();
In most cases, validation methods I've overridden execute twice each time the parent field is changed. Everything still works, but the InfoLog displays double messages every time.
Is there any way to prevent this?
Thanks
public boolean validate()
{
boolean ret;
int exlowValue;
int lowValue;
int highValue;
int exhighValue;
str errorMessage;
;
ret = super();
//Make sure a numeric value was entered
if (ABC_RegExValidator::validateMe("integer", int2str (ABC_Checks_checkExtremeLow.value())))
{
//get the form values
exlowValue = ABC_Checks_checkExtremeLow.value();
lowValue = str2int(ABC_Checks_checkLow.valueStr());
highValue = str2int(ABC_Checks_checkHigh.valueStr());
exhighValue = str2int(ABC_Checks_checkExtremeHigh.valueStr());
//Extreme Low must be 0 or less than all others
if (exlowValue != 0)
{
//A non-zero value was entered; it must be less than all other fields
if ((exlowValue >= lowValue && lowValue > 0) || (exlowValue >= highValue && highValue > 0) || (exlowValue >= exhighValue && exhighValue > 0))
{
//Return an error
ret = checkfailed(strFmt("#ABC197", int2str(exlowValue)));
}
else
{
//Not greater than any other value
//Success!
ret = true;
} //Greater than all others?
}
else
{
//No errors
ret = true;
} // 0?
}
else
{
//Regular expression failed
//Return an error
ret = checkfailed("#ABC192");
} //Regular expression
return ret;
}
Your description of the problem is not really clear. One can override the valite method on a form control, the validate method on a form datasource and the validatefield method on the table. That's my knowledge of version 3.0.
And how do you mean the "parent field"? I presume the table field?
If I put info messages in each of these methods they only execute once when I modify a value. That's the case in 3.0. I don't know which version you're using.
Maybe you could be more precise about which validation method you're testing?