I have a set of classes to which I am trying to apply unit tests, to maintain their current utility through future revisions.
My problem is that within CPPUNIT, to which I am new, where-ever I call CPPUNIT_ASSERT ( [condition] ), I am met with Error Unhandled Exception...: Access Violation at 0xffffffffffffffff.
This happens even I write the simplest test case
int main(){
CPPUNIT_ASSERT ( true );
}
I have tried calling my testing functions with manual calls, as well as adding them to a registry, as is done in the Money example. The problem reportedly arises within the constructor for SourceLine, as the filename string it expects is a bad pointer.
After a bit of a search I've found that this is called within the CPPUNIT_ASSERT, as it's a macro with the following definition
#define CPPUNIT_ASSERT(condition) \
( CPPUNIT_NS::Asserter::failIf( !(condition), \
CPPUNIT_NS::Message( "assertion failed", \
"Expression: " #condition), \
CPPUNIT_SOURCELINE() ) )
I've searched the tutorials on CppUnit's site, and scrutinised stackoverflow, but I have not found anything that addresses this in particular. I do find it strange that what is, in every example I've seen, a single-parameter function (assert), will call another function with no arguments (sourceline) that is actually another macro that is assuming it receives a string, but can receive no such thing. I found that SourceLine is a class that still has a default constructor, but above is called a macro, which really refers to the 2-parameter constructor, but is passed no arguments that I can see. I am at a loss.
I am using a 64 bit compilation of CppUnit, verified with a dumpbin, and Visual Studio 2008.
Cppunit's assertion system uses macros so it is expected that your simple example complains about unhandled exception.
Normally you don't use an assertion outside of a test method. I suggest you have a look at the Cppunit Cookbook which provides some information and examples how to effectively use cppunit.
Related
Example:
data class T(val flag: Boolean) {
constructor(n: Int) : this(run {
// Some computation here...
<Boolean result>
})
}
In this example, the custom constructor needs to run some computation in order to determine which value to pass to the primary constructor, but the compiler does not accept the run, citing Cannot access 'run' before superclass constructor has been called, which, if I understand correctly, means instead of interpreting it as the non-extension run (the variant with no object reference in https://kotlinlang.org/docs/reference/scope-functions.html#function-selection), it construes it as a call to this.run (the variant with an object reference in the above table) - which is invalid as the object has not completely instantiated yet.
What can I do in order to let the compiler know I mean the run function which is not an extension method and doesn't take a scope?
Clarification: I am interested in an answer to the question as asked, not in a workaround.
I can think of several workarounds - ways to rewrite this code in a way that works as intended without calling run: extracting the code to a function; rewriting it as a (possibly highly nested) let expression; removing the run and invoking the lambda (with () after it) instead (funnily enough, IntelliJ IDEA tags that as Redundant lambda creation and suggests to Inline the body, which reinstates the non-compiling run). But the question is not how to rewrite this without using run - it's how to make run work in this context.
A good answer should do one of the following things:
Explain how to instruct the compiler to call a function rather than an extension method when a name is overloaded, in general; or
Explain how to do that specifically for run; or
Explain that (and ideally also why) it is not possible to do (ideally with supporting references); or
Explain what I got wrong, in case I got something wrong and the whole question is irrelevant (e.g. if my analysis is incorrect, and the problem is something other than the compiler construing the call to run as this.run).
If someone has a neat workaround not mentioned above they're welcome to post it in a comment - not as an answer.
In case it matters: I'm using multi-platform Kotlin 1.4.20.
Kotlin favors the receiver overload if it is in scope. The solution is to use the fully qualified name of the non-receiver function:
kotlin.run { //...
The specification is explained here.
Another option when the overloads are not in the same package is to use import renaming, but that won't work in this case since both run functions are in the same package.
here is the function that worked prior to upgrading to 7.0
function set_session_vars() {
$nb_args=func_num_args();
$arg_list=func_get_args();
for($i=0;$i<$nb_args;$i++) {
global $$arg_list[$i];
$_SESSION[$arg_list[$i]] = $$arg_list[$i];
}
}
now it causer error that says:
Parse error: syntax error, unexpected '[', expecting ',' or ';' in /home/mvyc1956/public_html/members/includes/functions.php on line 322
I believe its related to non backward compatable changes to GLOBAL and the use of $$ and arrays, but my PHP is not good enough to figure it out.
Is there someone who is familiar with why this line :
global $$arg_list[$i];
which is line 322 that is being reported as the cause of the error, would be failing now, and what would you recommend I change the code to in order to have it work with PHP 7?
I did some googling and found this page but again, im not understanding what needs to be changed.
thanks
says syntax error so some of the code in the function is no longer valid, but it would take a php 7 expert to see it.
UPDATE
I removed the word GLOBAL from the above code and the app "seems" to be now working fine so I will now ask:
Does anyone know specifically, why Global was the non compatibility issue? and is my fix of simply removing it a solid one or will is there a better practice or will this removal come back to haunt me?
Backward incompatible changes:
global only accepts simple variables
Variable variables can no longer be used with the global keyword. The curly brace syntax can be used to emulate the previous behaviour if required:
// Valid in PHP 5 only.
global $$foo->bar;
// Valid in PHP 5 and 7.
global ${$foo->bar};
So in your case it should become:
global ${$arg_list[$i]};
The global keyword tells PHP to access a global variable (per launch of the script) instead of a local variable (per function). For example,
global $foo;
means that future uses of the variable $foo in that function refer to the global variable with that name, rather than a variable within the function itself.
What this is trying to do is look up a variable by arbitrary name in the global namespace. That's entirely the wrong way to do things. Instead, you should have a global array and use keys in the array. In fact, $$ is arguably a bad idea in general.
But that's neither here nor there. The problem is that the parsing rules changed in PHP 7.0 in a non-backwards-compatible way (because they're using a more traditional parser now, and thus had to make their associativity rules self-consistent).
More details here:
http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.variable-handling.indirect
To make a long story short, you need to rewrite that as:
global ${$arg_list[$i]};
and then your code will work correctly on both PHP 7 and PHP 5.
Incidentally, the function only appears to work without the global keyword. In fact, it is always getting empty values for those variables.
While modifying an existing program's CASE statement, I had to add a second block where some logic is repeated to set NetWeaver portal settings. This is done by setting values in a local variable, then assigning that variable to a Changing parameter. I copied over the code and did a Pretty Print, expecting to compiler to complain about the unknown variable. To my surprise however, this code actually compiles just fine:
CASE i_actionid.
WHEN 'DOMIGO'.
DATA: ls_portal_actions TYPE powl_follow_up_sty.
CLEAR ls_portal_actions.
ls_portal_actions-bo_system = 'SAP_ECC_Common'.
" [...]
c_portal_actions = ls_portal_actions.
WHEN 'EBELN'.
ls_portal_actions-bo_system = 'SAP_ECC_Common'.
" [...]
C_PORTAL_ACTIONS = ls_portal_actions.
ENDCASE.
As I have seen in every other programming language, the DATA: declaration in the first WHEN statement should be encapsulated and available only inside that switch block. Does SAP ignore this encapsulation to make that value available in the entire CASE statement? Is this documented anywhere?
Note that this code compiles just fine and double-clicking the local variable in the second switch takes me to the data declaration in the first. I have however not been able to test that this code executes properly as our testing environment is down.
In short you cannot do this. You will have the following scopes in an abap program within which to declare variables (from local to global):
Form routine: all variables between FORM and ENDFORM
Method: all variables between METHOD and ENDMETHOD
Class - all variables between CLASS and ENDCLASS but only in the CLASS DEFINITION section
Function module: all variables between FUNCTION and ENDFUNCTION
Program/global - anything not in one of the above is global in the current program including variables in PBO and PAI modules
Having the ability to define variables locally in a for loop or if is really useful but unfortunately not possible in ABAP. The closest you will come to publicly available documentation on this is on help.sap.com: Local Data in the Subroutine
As for the compile process do not assume that ABAP will optimize out any variables you do not use it won't, use the code inspector to find and remove them yourself. Since ABAP works the way it does I personally define all my variables at the start of a modularization unit and not inline with other code and have gone so far as to modify the pretty printer to move any inline definitions to the top of the current scope.
Your assumption that a CASE statement defines its own scope of variables in ABAP is simply wrong (and would be wrong for a number of other programming languages as well). It's a bad idea to litter your code with variable declarations because that makes it awfully hard to read and to maintain, but it is possible. The DATA statements - as well as many other declarative statements - are only evaluated at compile time and are completely ignored at runtime. You can find more information about the scopes in the online documentation.
The inline variable declarations are now possible with the newest version of SAP Netweaver. Here is the link to the documentation DATA - inline declaration. Here are also some guidelines of a good and bad usage of this new feature
Here is a quote from this site:
A declaration expression with the declaration operator DATA declares a variable var used as an operand in the current writer position. The declared variable is visible statically in the program from DATA(var) and is valid in the current context. The declaration is made when the program is compiled, regardless of whether the statement is actually executed.
Personally have not had time to check it out yet, because of lack of access to such system.
Today I discovered that something I had assumed about VB.NET for many years was not true (worrying!). I assumed that a variable declared within a loop had a lifetime of the iteration it was declared in, but in fact it seems it has a lifetime of the whole procedure.
For example:
For i As Integer = 0 To 1
Dim var1 As Boolean
Console.WriteLine(var1.ToString())
var1 = True
Console.WriteLine(var1.ToString())
Next
Console.ReadKey()
I had assumed an output of False, True, False, True but instead it is actually False, True, True, True.
In C# the equivalent code would not compile as you would get a compile time error of Error "Use of unassigned local variable 'var1'".
I realise there are many ways to fix this and that best practice would be to declare the variable outside of the loop and reset it at the beginning of every loop through.
I find this behaviour so counter-intuitive to me that I would like at least a compile time warning in VB.NET when/if I do this. (I could also then set this on any projects I already have and get warning that would allow me to check that my assumptions aren't causing errors).
Does anyone know how/if I can get this to generate a compile time warning in VB.NET? Am I the only one that finds this counter-intuitive?
We'll have to work on fixing your intuition because getting an error out of the compiler is not an option. It is partially implemented, you can get this warning:
error BC42104: Variable 'mumble' is used before it has been assigned a value. A null reference exception could result at runtime.
And elevate it from a warning to an error with Project + Properties, Compile tab. However, as the warning message indicates, this is only supported for reference type references, it won't budge for a variable of a value type.
Okay, intuition. If the runtime would implement your desired behavior then it would have to allocate a new variable for each iteration of the loop. Which implies that the number of local variables is bounded only by the number of iterations. This is very wasteful and a very easy trigger for StackOverflowException. The JIT compiler doesn't do this, it re-uses the variable. This happens in C# as well, minus the option of letting you not initialize the value explicitly of course.
Fwiw: I very much agree with you that this is unhelpful behavior. You'll probably find receptive ears at connect.microsoft.com, post your feature request there and the VB.NET team will see it. There has been strong backing from customers as well as within MSFT to make VB.NET and C# feature comparable. If you post a link to your feedback report then I'll be happy to vote it up.
I'm having trouble with a .NET Assembly that is com visible, and calling certain methods from VB6.
What I have found is that if the parameters are well defined types, (e.g. string), calls work fine. If they are higher level objects, it raises a runtime error '438' suggesting that the property or method is not present. I suspect that this is a question of having the correct signature on the call, but I can't see how to do this correctly.
I believe that I've done everything correct on the .NET side (ComVisible, public interfaces, etc. and even have it down to a simple enough case).
Looking at the output from the typelib viewer, I have the following:
dispinterface ISimple {
properties:
methods:
[id(0x60020000)]
void Add([in] ISimpleMember* member);
[id(0x60020001)]
ISimpleMember* Create();
};
OK. So I have 2 methods in my ISimple interface. One takes an ISimpleMember (Add), whilst the other, returns an ISimpleMember.
The corresponding code in VB looks like this:
Dim item As ISimpleMember
Dim simple As simple
Set item = New SimpleMember
item.S1 = "Hello"
item.S2 = "World"
Set simple = New simple
simple.Add (item) <---- This raised the run time error 438
Set item = simple.Create <---- This works fine, returning me an ISimpleMember
I've tried a couple of things:
1. Dim item as SimpleMember (makes no difference)
2. simple.Add(ObjPtr(item)) - Syntax error
3. simple.Add(ByRef item) - Syntax error
Basically, The run time error is the same as if I had
simple.AMethodThatIHaventWritten()
Also, If I browse References in the VB6 Environment, The Add method is well defined:
Sub Add(member As SimpleMember)
I've found the answer I believe. It was very simple:
When calling a SubRoutine, I shouldn't put the name in braces. the call should have been:
simple.add member
rather than
simple.add(member)
If I change it to a function (i.e. return a value rather than void) the braces are necessary
This seems to work
(Probably) The top 3 VB6 coding mistakes made by devs who now mainly code in C#, Javascript etc. Are:-
Placing ; at the end of lines. Its a syntax error very easily spotted and picked up the compiler.
Not placing Then on the other side of an If condition expression. Again its a syntax error.
Calling a method without retrieving a value and yet using ( ) to enclose the parameter list. With multiple parameters this is a syntax error and easily found. With only one parameter the use of ( ) is interpreted as an expression. Its the result of the ( ) expression which is passed as parameter. This causes problems when ByRef is expected by the callee.