preload

TestComplete Type Casting

Posted by Albert Gareev on Sep 14, 2010 | Categories: NotesTools

TestComplete Type Casting in VBScript: It’s a bug!

In computer science, type conversion or typecasting refers to changing an entity of one data type into another. This is done to take advantage of certain features of type hierarchies. For instance, values from a more limited set, such as integers, can be stored in a more compact format and later converted to a different format enabling operations not previously possible, such as division with several decimal places’ worth of accuracy. In object-oriented programming languages, type conversion allows programs to treat objects of one type as one of their ancestor types to simplify interacting with them.
Wikipedia.org

TestComplete (as Quick Test Professional) uses Microsoft VBScript Engine to execute code. In VBScript, scalar data types are not explicitly defined. They are all stored as “Variant”.

Now let’s get to our little exercise.

Public Sub P1

  Dim S1, S2, S3, S4, S5, intValue, sEmpty
  Dim intL1, intL2
 
  Dim sResult
 
  intValue = 0
  sEmpty = ""
 
  S1 = String(5, " ")
  S2 = String(5, "!")
  S3 = String(5, "0")
  S4 = String(5, 0)
  S5 = String(5, intValue)
 
  intL1 = Len(sEmpty)
  intL2 = Len(S4)
 
  sResult = S2 & S4 & S3

End Sub

String(Number, Character) function in VBScript simply generates a string consisting of number of characters. I.e. S2 in our code is supposed to receive “!!!!!”, S3 – “00000”, and same for S4, S5. As for sResult, we may expect to see “!!!!!0000000000”

Let’s execute the code and see results.

Oddly enough, S4 as a string is empty, but, unlike empty string, has a length different from zero. For sResult, we can see only first part (taken from S2), and can’t see the rest. But, again, length of sResult is 15, that means, the missing characters were stored somehow.

This behavior is certainly a bug. A tool should either properly convert data type on its own or throw an exception.

To workaround it use explicit type conversion of parameters via CStr() function.


  • 9 responses to "TestComplete Type Casting"

  • Silverfish Bug
    14th September 2010 at 10:17

    See another bug example.

    [Albert’s comment. These spammers become more and more creative. Got to keep this one as a reward.]

  • Helen
    14th September 2010 at 14:50

    Albert,

    I’m sorry to disappoint you, but it’s not a bug. :)

    [ Albert’s reply. Thanks for stopping by :) ]

    First of all, you need to understand that if the Character parameter of the String function is a number, it’s treated as an ASCII character code. (For example, if you use 65, you’ll get a string of A’s.) This number is NOT converted to its string representation (“65”). Although this isn’t clearly stated in the description of the String function in MSDN, one can deduce this from the example given:
    http://msdn.microsoft.com/en-us/library/6978d214.aspx

    [ Albert’s reply. I do understand that, what I don’t understand why an inconsistency like that is not a bug to you:)) ]

    The character code 0, which you use to generate the S4 string, corresponds to the null character:
    http://en.wikipedia.org/wiki/Null_character
    So S4 isn’t actually empty – it consists of five null characters.

    [ Albert’s reply. Here’s another Wikipedia link for you. Read from “The length of a C string is found by searching for the (first) NUL byte.” And how come the length in our case is still 5 ? ]

    However, since the null character is used to indicate the end of the string, the UI displays only the characters up to and ignores the rest.

    [ Albert’s reply. So you mean this is a UI bug? ]

    That’s why S4 looks empty in the Watch List and nothing is displayed after !!!!!. You’ll see the same result if you MsgBox the S4 and sResult strings. Hope the mystery is now solved for you. :)

    [ Albert’s reply. Here’s another mistery for you to solve. Since you’re sure that characters after zero should be ignored, than why InStr(sResult, “0”) returns 11 ? ]

    FYI, many VBScript gotchas are thoroughly explained in Eric Lipper’s blog (he’s one of the developers of VBScript):
    http://blogs.msdn.com/b/ericlippert/archive/tags/vbscript/

    [ Albert’s reply. Thanks for linking this great blog. ]

    Of course, they are also in effect when third-party applications run VBScript code using the native engine.

    [ Albert’s reply. Well, some tools wrap around questionable pieces. Known bug is still a bug. ]

    Best regards,
    Helen

  • Alex
    15th September 2010 at 10:03

    Hi Albert,
    An interesting excercise :)
    However, the problem is in your code and not in VBScript. All Variant strings are null-terminated. That is, to mark the end of a string in memory, the null-character is used (the character with the zero code). In your script, you are trying to build a string value containing null-characters. It is a mistake – you can’t do this in VBScript and many other programming language where null-temrinated strings are used.
    If you want to get zeroes in a string, use the “0” string as the second parameter of the String function. If you use an integer number there, it is treated as the code of the symbol.
    I hope this clarifies things a bit.

    Alex

    [ Albert’s reply.
    Dear Alex, looks like you have not carefully read the code provided.
    First of all, there is no such thing as “Variant string”. Interpreter may treat Variant as string, integer, pointer, and it is supposed to (that is – designed and programmed to, and claimed to) recognize and convert types automatically – or bring up error message, or raise an exception. In this case, it does neither.
    You are also wrong going “you can’t do this”. I already did – and the code was accepted and executed.
    Next thing you should pay attention to, is that the string, containing zeros, is not null-sized. Its length is 5. So your assertion about null-terminated nature of strings in Variant is invalid. Moreover, the string sResult happily accepted characters after 0, and its length is 15!

    Now, I want to thank you for bringing up a live example of “programmer bias”. But let me assure you, in real world programs often do much more then they were coded to, and often they also do some things wrong, for example, if boundary or special cases are not handled properly.
    Another famous type conversion example that ended in disaster is 64-bit floating point to 16-bit signed integer conversion that killed Ariane 5 Flight 501. Post-launch analysis indicated that the module, which caused the problem, was used in Ariane 4 flight control system, and has not been re-tested for Ariane 5 as “already working”. Yet the function, accepting trajectory data, didn’t do proper alignment for all the cases.

    Thanks, Albert ]

  • avk
    16th September 2010 at 7:05

    Albert,

    It is not a bug in VBScript, in TestComplete or QTP. As far as I can see, you don’t pay atttention to the parameter types.

    Read the description of the VBScript String function in MSDN. It says the second parameter of the String function is a character code.

    [ Albert’s reply. Actually, it is written as character code specifying the character or string expression whose first character is used to build the return string. ]

    Now, if you specify the second parameter as a character (“a”, “b” or “0”, “1”) the VBScript engine gets its character code and repeats the character in the resulting string.

    If the second parameter is an integer (as in case of S4), then VBScript treats this parameter as character code, not a character. (The code of the “0” character is 48, “1” – 49, “2” – 50, the code of “a” – 64, “b” – 65 etc. You can find character codes in MSDN).

    When you call String(5, 0) you get a string of five null symbols (in C++ and C# the null symbols are written as ).

    In programming (in C and C++ and other languages) the null symbols are used as special symbols to mark the end of a string in memory. That is why you see nothing in the Watch List window – the Windows API function that draws text on screen finds the character at the beginning of string and draws nothing.

    As for the length for sResult – VBScript’s Len function calculates the string length in other way (which does not depend on the symbols), so you get 15. That’s right.

    [ Albert’s reply. Yes, and that is where root of the problem. While string length is stored separately, some code components still use another rule “string ends as zero code is encountered”. ]

  • Helen
    16th September 2010 at 11:15

    Hi Albert and thanks for your replies.

    >> I do understand that, what I don’t understand why an inconsistency like that is not a bug to you:))

    Why do YOU think it’s an inconsistency? :) I often write VBScript code and actually find it very convenient to be able to specify a code instead of a character itself. For example, this lets me save some keystrokes and write
    String(5, 9)
    to get a string of 5 tabs, rather than
    String(5, Chr(9))

    [ Albert’s reply. I’m fine with dual nature of parameter for this function. But I want to digress here.
    Time, saved on a difference between coding keystrokes as String(5, 9) and String(5, Chr(9)) is minimal. However, the latter is much better notation in terms of maintenance of your code. ]

    I’m pretty sure it was originally designed like this according to the VBScript specification. Should we ask Eric Lippert to confirm that? :)

    [ Albert’s reply. You know, it doesn’t matter how it was designed to be. What matters is how it’s happened to be. As a side example, you can slice bread with kitchen knife, or you can cut one’s throat. Since it’s possible to do, there is always a chance it will eventually happen ]

    Also, when I’m not sure how a function works and what the parameters mean, I just look up the docs (that’s exactly what they are for, you know). :)

    [ Albert’s reply.
    When you look up the docs, you receive information only about how a thing was supposed to work in opinion of the person who wrote the document, at that time and under that circumstances.
    When I am not sure how it works (and we’re talking about programs here), I test it. With regards to the specific function or object it’s as simple as to write the code and observe the execution.
    I’m gonna blog more about it. Thanks for the idea. ]

    >> Here’s another Wikipedia link for you. Read from “The length of a C string is found by searching for the (first) NUL byte.” And how come the length in our case is still 5 ?

    OK, if you want to dig into low-level implementation – VBScript strings are actually BSTR strings:
    http://msdn.microsoft.com/en-us/library/ms221069.aspx
    and they can include embedded null characters. (Anticipating the probable question – no, it’s not a bug :) it’s part of the BSTR specification. COM programmers can tell you what embedded ‘s can be used for.) The length of a BSTR string is stored inside the string itself, that’s why you get the actual length, but not the length up to the first .

    >> So you mean this is a UI bug?

    No, I don’t think so.
    Firstly, if a BSTR string contains an embedded (and I mean strings returned by real API functions, but not artificially constructed ones like in your example), then most likely, the text after is some random unitialized garbage. That is, in this case is used as an early string terminator, saying “hey, don’t even look at what goes after me – the only meaningful info is before.”
    Secondly, the low-level Windows API painting and drawing functions use C-style strings, which can’t include ‘s. (Ironically, the matter now boils down to Windows :) If you want to display a string with embedded ‘s on the screen, you need to split it by ‘s and draw each part separately. Otherwise, the the BSTR to C string conversion cuts the string at the first .
    Think of this as a design guideline: “Don’t use ‘s in strings that are supposed to be on screen. is a special character and if you mess with it and use it in a way it’s not supposed to be used, it’s your own headache. Don’t say we didn’t warn you.” :)

    [ Albert’s reply. Such inconsistency is a bug. I can only agree that the issue is not quite exactly in type casting. ]

    >> Here’s another mistery for you to solve. Since you’re sure that characters after zero should be ignored, than why InStr(sResult, “0”) returns 11 ?
    I meant that the part after wasn’t displayed on screen. (Sorry for not being clear.)
    As for the length, see the reply above.

    To sum up, the behavior you observed is valid, it conforms to the specifications and can be reasonably explained why it works the way it does.

    [ Albert’s reply. Well, you know what we, testers, say. “If code conforms specification then the bug is in specification”. ]

    You can stick to your opinion that this is a bug, but I strongly disagree.

    [ Albert’s reply. The perfect reply here would be Michael Bolton’s “A Letter To The Programmer”. Note comments below, too. ]

    Best regards,
    Helen

  • Helen
    16th September 2010 at 11:23

    Looks like WordPress removes the “slash-zero” character sequences from comments (I used it as a shorthand for “null character”). So, ‘s and missing words should read “null character”.

  • Alex
    17th September 2010 at 3:06

    Hi Albert,
    We’ve got an interesting discussion here, don’t you think?

    [ Albert’s reply. Hi Alex! Yes, absolutely enjoying it. ]

    But I have just realized that your position can be expressed in a very short phrase:

    [ Albert’s reply. “The world was created in 6 days.” Sounds pretty short and simple, isn’t it?
    But, in testing, I’m against simplification. ]

    WinAPI functions don’t work well with BSTR strings – this is a bug.

    [ Albert’s reply. That’s too generalized.
    Any program doesn’t work well with something under certain conditions. ]

    Does this express your point?

    [ Albert’s reply. If you claim something a bug, you have to be specific.
    I agreed that it’s not exactly type casting bug and TestComplete just “inherited” it. We may call it “an inconsistency in how different code components treat BSTR data format, specifically, with null-character inside a string”.
    It might be considered a minor issue but even a minor issue can cause major failure. ]


    Alex

  • pradeep
    2nd September 2011 at 6:01

    Hi Albert,
    I understand that this is a very old thread.

    @Helen mentioned VbScript strings are BSTR strings, but i couldn’t find any related article.

    Others assumed it is null terminated. Termination of strings has to be worried in case of a compiled language and not for interpreted languages i believe. However for inter-op communication like COM and others (which are compiled) the strings should have some way of indicating termination of strings (e.g BSTR). Since an interpreter sits in middle its possible to implement in anyway ryt??

  • greg
    26th October 2013 at 5:18

    hi all

    Interesting indeed.

    The line:
    S4 = String(5, 0)

    Cannot be stored as a string. Its more likely a type of array. Otherwise the first 0 would terminate the “string” as zero length.

    Perhaps we are seeing how the design of VBS is working out how to deal with the series of nulls. Not an actual bug if seen this way.

    What do you think?

Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported
This work by Albert Gareev is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported.