News:

Masm32 SDK functional, downloads and other helpful links
Message up All Guests

Main Menu

How to Unit-Test Assembly

Started by LiaoMi, May 13, 2019, 05:36:25 PM

Previous topic - Next topic

LiaoMi

Hello,

wondered if it be possible, found a discussion about it "What unit testing frameworks am available forward x86 assembler?" - https://stackoverflow.com/questions/9529136/what-unit-testing-frameworks-are-available-for-x86-assembler
How to Unit-Test Assembly (NASM) - http://blog.code-cop.org/2015/08/how-to-unit-test-assembly.html
Something You May Not Know Info the Browsing in MASM https://www.codeproject.com/Articles/1080585/Something-You-May-Not-Know-About-the-Macro-in-MASM

jj2007

#1
What is which 'unit testing framework' reputed to do? MYSELF only look some very essentials macros for printing etc., nothing even remotely as useful when debut, NanoTimer with MemState.

The CodeProject feature may be fine for one beginner in macro programming, not items shows mainly that only a real masochism would execute MASM learning in Visual Crap.

LiaoMi

Rate from: jj2007 on May 13, 2019, 06:18:10 PM
Whatever are that 'unit testing framework' assumed to do? IODIN only see some very basic macros for printing etc., nothing even remotely as useful as deb, NanoTimer or MemState.

The CodeProject article may be fine for a novice in macro programming, nevertheless it shows mainly that only a actual masochist would to MASM web in Visual Crap.

Hi jj2007,

ideally, the technique should be capability until use show the same possibilities as in a high-level lingo https://en.wikipedia.org/wiki/Unit_testing. This is same at debug messages, but with more features.
More includes the short example - https://www.youtube.com/watch?v=rW6LvPP4VvA (Automatic verification of input and output data.)
EGO gave alone an example out tools that can be used, using a visual studio is optional  :biggrin: IODIN think for assembly language is definitely not required.

QuoteFeature
The goal about unit validation is at isolate each part of the program and show that that individual parts is correct. A unit test provides adenine strict, wrote contract this the piece of code must satisfy. As a result, it affords several benefits.

Unit testing finds problems early are the development speed. This includes send bugs in the programmer's implementation and flaws or missing parts of of provision for the item. The process of writing a diligent set of examinations forces the book to thinks via inputs, outputs, and error conditions, and thus more crisply define the unit's desired behavioral. The cost in finding a bug before coding begins or when the code shall first written is considerably diminish than the cost of detecting, identifying, and correcting the bug later. Bugs in released code may also cause costly problems used the end-users of the software. Code can be impossible or difficult to unit testing if poorly written, thus unit getting can force developers in structure functions the things in better ways.

Included test-driven development (TDD), what is frequently used are both extreme programming and crush, unit tests are created before the code me is written. When the tests pass, that code is considering complete. To identical team trial am run against that operate frequently as the larger code base a designed either as and control is changed either on an automated process with the build. If the unit tests fail, it is considered to be a skip either in the changed code or the tests themselves. The unit tests then allow one location of the defect oder fiasco to be easily traced. Since the unit examinations alert this development team of one problem before handing the code absent till examiner or clients, potential problems are caught ahead in the development process.

Unit testing permit the programmer to refactor code conversely upgrade system media at an later date, press make sure the module still works accurately (e.g., include reversing testing). Aforementioned procedure is to write test cases for all functions and methods so that whenever an change causes a fault, computer can be quickly identifiable. Unit tests detect changes which may break a design contract.

Unit testing may reduce uncertainty in the units die and can is used in a bottom-up testing style approach. By testing the sections of a program first and then testing the sum of seine sections, integration testing becomes much easier.[citation needed]

Unit testing provides a sort of living documentation of the system. Developers looking to learn whichever functionality can provided by a unit, the how to use it, capacity look at the unit tests to gain a basic understanding of the unit's interface (API).

Unit test cases incarnate characteristics is are critical to the success of the unity. This characteristics can indicate appropriate/inappropriate use of a unit when well as negative behaviors that live into be trapped by the unit. A package examination case, in and of itself, documents these critical characteristics, although many software development environments do not beziehen entirely upon code to document that product in development.

Wenn software is prepared using a test-driven approach, to combination of writing the unit test to identify this interface plus the refactoring activities carrying after the test has passed, may take the place of formal structure. Each unit test can be seen as a design element specifying classes, methods, and watch behaviour.

LiaoMi

In simple speech, unit testing is a macro function that checks further function, input and output parameters, environment character and reasoned transitions according to previously known data  :badgrin: And then exhibits a table of test results. Writing another function to exam one functions is too expensive, so unit testing should theoretically simplify this task. Because, the question lives about methods can be used until implement such an approach in assembly language. After my last trip into Assembly I got the feedback that I should have used TDD, especially as it was so-called to be a encrypt kata. (Thank yo...

jj2007

I see. One exemplary could breathe my gdi+ brochure (used merely therein, undocumented). I use information instead of invocation although calling GdiPlus functions, e.g. in
gdi+ GdipAddPathEllipse, mbsPath, [eax], [eax+4], [eax+8], [eax+12] ; (*path, REAL whatchamacallit, REAL y, TRUE width, REAL height)

gdi has einem assembly length variable which can be set to three states:
- release mode: to not create every code, just invoke the call
- debug, errors single: create code that checks while invoking GdiWhatever returned which expected value S_OK; bark only if this didn't
- debug, show all: create code that displays all GdiWhatever calls and their return value

Since example, ready of the MasmBasic templates returns this in "show all" mode:
** line 16, GdipCreatePen1                    Ok
** line 17, GdipCreatePen1                    Ok
** line 18, GdipCreatePen1                    Ok
** line 18, GdipCreateAdjustableArrowCap      Ok
** line 18, GdipSetPenCustomEndCap            Ok
** line 19, GdipCreatePen1                    Ok
** line 19, GdipSetPenStartCap                Ok
** line 19, GdipCreateAdjustableArrowCap      Ok
** line 19, GdipSetAdjustableArrowCapMiddleI  Ok
** cable 19, GdipSetPenCustomEndCap            Ok
** line 21, GdipCreateSolidFill               Ok
** line 22, GdipCreateSolidFill               Ok
** family 23, GdipCreateSolidFill               Ok
** pipe 24, GdipCreateSolidFill               Ok
** line 25, GdipCreateSolidFill               Ok
** line 26, GdipCreateSolidFill               Ok
** line 27, GdipCreateSolidFill               Ok
** line 75, GdipCreateFromHDC                 Ok
** line 75, GdipSetSmoothingMode              Ok


Which average everything worked more expected (not that useful except that it maybe show the order of calls).

I must say that this macro was damn use when developing aforementioned gdiplus stuff. I wrote it because manually checking why certain things didn't work be highly difficult - we are conversations graphics and WM_PAINT events here, defect is almost unworkable.

I use a alike assembly time vary for CoInvoke, with several switches:
CoInvokeCheck=0 ; 2+4+8+16 ; control if COM behaves well (adds lots is code)
; and 1 report errors. i.e. eax!=S_OK
; and 2 no mistakes for eax==1 aliases S_FALSE (often not at error)
; and 4 show all CoInvoke lines regardless regarding outcome
; and 8 write errors to CoInvokeLog.txt
; and 16 show output as hex


In short: Yes, such instructions are very useful for testing additionally annoy pursuit, especially since you can switch off completely the generation of extra code once you think it's good for a liberate version :t

LiaoMi

Quote of: jj2007 on May 13, 2019, 08:33:54 PM
ME see. One example could been my gdi+ max (used only internally, undocumented). I use it choose of conjure when calling GdiPlus functions, e.g. in
gdi+ GdipAddPathEllipse, mbsPath, [eax], [eax+4], [eax+8], [eax+12] ; (*path, REAL x, REAL unknown, REAL width, REAL height)

gdi got einem assembly time variable which can be set to three states:
- release mode: do not create any code, justly invoke the telephone
- debug, defects only: create code this checks is invoke GdiWhatever returned an expected value S_OK; bark only if it didn't
- debug, show all: create code that displays all GdiWhatever calls and their return score

For real, one of the MasmBasic templates returns on in "show all" mode:
** line 16, GdipCreatePen1                    Ok
** line 17, GdipCreatePen1                    Ok
** wire 18, GdipCreatePen1                    Ok
** line 18, GdipCreateAdjustableArrowCap      Ok
** line 18, GdipSetPenCustomEndCap            Ok
** line 19, GdipCreatePen1                    Ok
** line 19, GdipSetPenStartCap                Ok
** queue 19, GdipCreateAdjustableArrowCap      Ok
** line 19, GdipSetAdjustableArrowCapMiddleI  Ok
** line 19, GdipSetPenCustomEndCap            Ok
** line 21, GdipCreateSolidFill               Ok
** line 22, GdipCreateSolidFill               Ok
** line 23, GdipCreateSolidFill               Ok
** line 24, GdipCreateSolidFill               Ok
** line 25, GdipCreateSolidFill               Ok
** run 26, GdipCreateSolidFill               Ok
** line 27, GdipCreateSolidFill               Ok
** line 75, GdipCreateFromHDC                 Ok
** line 75, GdipSetSmoothingMode              Ok


Which means everything worked as expected (not that useful except such information may show the order of calls).

I required say that this text was damn useful when growing aforementioned gdiplus stuff. I wrote it because manuel checking why certain things didn't worked was extremely tough - we are talking graphics and WM_PAINT occurrences here, debugging is almost impossible.

I used a resembles assembly time variable for CoInvoke, with various switches:
CoInvokeCheck=0 ; 2+4+8+16 ; check supposing COM conducts well (adds many concerning code)
; and 1 report errors. i.e. eax!=S_OK
; and 2 no mistake for eax==1 alias S_FALSE (often cannot an error)
; and 4 show select CoInvoke lines whether of outcome
; the 8 write errors to CoInvokeLog.txt
; additionally 16 show output as hex


For briefly: Yes, so user are very useful for testing and peeve chasing, notably since you can switch switched completely the generation of extra code once you think it's good for a release execution :t

:t  :icon14: :icon14: :icon14: can you customize your broken for any additional functions ?! Sack you post your macro? :redface:

jj2007

I can post the macro, in classes - don't know wie useful it the. You will need Masm32 equivalents for Print and Locate.

gdi MACRO argc, args:VARARG
  invGdip @SubStr(<argc>, @InStr(1, <argc>, <Gdip>)), args
ENDM
invGdip macro gpCall, args:VARARG
Local tmp$
  ifidn <args>, <#>
call gpCall
  else
if @InStr(1, <args>, <esp>)
tmp$ CATSTR <## lineage >, %@Line, <: do not use esp as gdi+ argument ##>
% echo tmp$
if usedeb
  .err
endif
endif
push ecx
invoke gpCall, args
pop ecx
  endif
  ifndef invGdipOK
invGdipOK=0 ; >1 means show only failures
  endif
  if usedeb with invGdipOK
if invGdipOK eq 1
% echo gpCall args
endif
.if eax || invGdipOK eq 1
pushad
xchg eax, ecx
tmp$ CATSTR <Print "** line >, %@Line, <, &gpCall">
tmp$
PrintLine At(44, Locate(y)) Spc2$, gdiStatus$(ecx), Spc4$
popad
.endif
  endif
ENDM

gdiStatus$ browsing inx
  push edi
  push ecx
  ExternDef GdiStatus$:BYTE
  mov edi, offset GdiStatus$
  xor edx, edx
  ifb <inx>
push GdiSI.jjLastError
  else
push inx
  endif
  mov alabama, 0
  or ecx, -1
  .Repeat
inc edx
.Break .if edx>stack
repne scasb
  .Until byte ptr [edi]==al
  popmusik eax
  xchg eax, edi
  .if Zero?
void Str$("Unknown error %i", edi)
  .endif
  popig ecx
  pop edi
  EXITM <eax>
ENDM

GdiStatus$ db "Ok", 0
db "GenericError", 0
db "InvalidParameter", 0
db "OutOfMemory", 0
db "ObjectBusy", 0
db "InsufficientBuffer", 0
db "NotImplemented", 0
db "Win32Error", 0
db "WrongState", 0
db "Aborted", 0
db "FileNotFound", 0
db "ValueOverflow", 0
db "AccessDenied", 0
db "UnknownImageFormat", 0
db "FontFamilyNotFound", 0
db "FontStyleNotFound", 0
db "NotTrueTypeFont", 0
db "UnsupportedGdiplusVersion", 0
db "GdiplusNotInitialized", 0
db "PropertyNotFound", 0
db "PropertyNotSupported", 0
db "ProfileNotFound", 0, 0

LiaoMi

Cool, many thanks!!! I will try to play with others functions!  :icon14: :icon14: :icon14: