Unit test failure on strings, inconsistent match fails?!

Many weeks ago I had an issue which turned out to be masked by having portray_text(true) in effect. That is no longer the case. Just now I started writing more unit tests, all was well until I added two more that failed. Once again, the error message is totally baffling, here is the failure output.

ERROR: /home/sean/Documents/code/prolog/the-f-word-project/src/ast/ast.plt:165:
	test defun_arglist_simple_var_no_value: wrong answer (compared using ==)
ERROR:     Expected: [defun((0,1,0),tk((7,1,7),"foo"),[tk((12,1,12),"xyz")],[])]
ERROR:     Got:      [defun((0,1,0),tk((7,1,7),"foo"),[tk((12,1,12),"xyx")],[])]
ERROR: /home/sean/Documents/code/prolog/the-f-word-project/src/ast/ast.plt:171:
	test defun_arglist_multi_simple: wrong answer (compared using ==)
ERROR:     Expected: [defun((0,1,0),tk((7,1,7),"foo"),[tk((12,1,12),"xyz"),tk((16,1,16),"n1"),tk((19,1,19),"count/int")],[])]
ERROR:     Got:      [defun((0,1,0),tk((7,1,7),"foo"),[tk((12,1,12),"xyx"),tk((16,1,16),"n1"),tk((19,1,19),"count/int")],[])]

Here is the test code. The failures are the last two, I created them by cutting and pasting the previous test, extending it, then cutting and pasting it again. Why should these fail even if the test output looks correct?

:- begin_tests(defun_syntax_errors).
:- use_module(myapp(helpers)).

test(defun_no_function_name,
     [throws(ast(syntax((0,1,0), defun_function_name((7,1,7)))))]) :-
    rawast("(defun ())", _Ast).

test(defun_no_arglist,
     [throws(ast(syntax((0,1,0), expected_paren_open((10,1,10)))))]) :-
    rawast("(defun foo)", _Ast).

test(defun_arglist_empty,
     [true(Ast == [defun((0,1,0), tk((7,1,7),"foo"), [], [])])]) :-
    rawast("(defun foo ())", Ast).

test(defun_arglist_simple_var_no_value,
     [true(Ast == [defun((0,1,0), tk((7,1,7),"foo"),
        [tk((12,1,12), "xyz")],
        [])])]) :-
    rawast("(defun foo (xyx))", Ast).

test(defun_arglist_multi_simple,
     [true(Ast ==
        [defun((0, 1, 0), tk((7, 1, 7), "foo"),
                [tk((12, 1, 12), "xyz"),
                tk((16, 1, 16), "n1"),
                tk((19, 1, 19), "count/int")],
                [])]
          )]) :-
    rawast("(defun foo (xyx n1 count/int))", Ast).

:- end_tests(defun_syntax_errors).

This time I am completely baffled as I KNOW I have consistent string representation going on whereas before I had allowed some character-code/string inconsistencies to slip in but that has been ruled out at the tokenisation level with tests…which pass!

If I do this:

?- helpers:rawast("(defun foo (xyz n1 count/int))", X).
X = [defun((0, 1, 0), tk((7, 1, 7), "foo"), [tk((12, 1, 12), "xyz"), tk((16, 1, 16), "n1"), tk((19, 1, 19), "count/int")], [])].

I get the same output, then, relying on $X being present, if I do this:

?- assertion([defun((0,1,0),tk((7,1,7),"foo"),[tk((12,1,12),"xyz"),tk((16,1,16),"n1"),tk((19,1,19),"count/int")],[])] == $X).
X = [defun((0, 1, 0), tk((7, 1, 7), "foo"), [tk((12, 1, 12), "xyz"), tk((16, 1, 16), "n1"), tk((19, 1, 19), "count/int")], [])].

The assertion doesn’t fail yet it is the same code?!?!
:man_facepalming:

I have encountered this problem also where a test result and expected test result look exactly the same on the screen but SWI-Prolog states they are not the same.

In my case it was because I was using non-ASCII characters. IIRC I converted both strings to codes then did the comparison. The problem with that is that we are use to seeing strings as a sequence of letter, digits, etc., and seeing them as a list of codes is hard to figure out which character is causing the problem. So to make it easier to also look at the test I duplicated the test but then did not do the conversion to codes and left them as the letter, digits, etc. this way I could see both test at the same time and it made it easier to find the character. In extreme cases I would put the letters, digits, etc. as characters above the codes as a comment line. That was time consuming and tedious work but it always worked to find the character causing the issue.

HTH

@EricGT I am pretty much stopping to that now…but not happy about it…it is causing serious delays and making me wonder why??? the ONLY thing I can think of now you mention it (the change that makes the change) is that I started using SciTe whilst I wrote it…

hang on… (&^%$&()_ editors!!!

The default code-page in SciTe was NOT utf-8 …I changed it and re-saved the file but somehow it made no difference, the damage has been done…I guess using “od” at the command line would reveal something… it didn’t.

Then I switched back to the internal (trusty) editor and still failed SO then I re-typed one of the failing tests out from afresh, new keystrokes, no cut and paste of polluted characters etc and guess what, it passed.

Then I typed a fresh test, it failed!!! WTAF??

So then I ran it through iconv that strip any dodgy utf-8 characters;

iconv -f utf-8 -t utf-8 src/ast/ast.plt > src/ast/ast.plt2

and the files were the same size afterwards so it didn’t seem to find any utf-8 errors. I renamed the file anyway and then restarted a new session same tests failing, without any obvious utf-8 issues in the file content.

Thanks Eric. I continue to dig at it but TBH it’s pretty much taken the wind out of my sails right now…now what I was expecting! :expressionless:

The things that don’t kill you make you stronger.

Yup! HAHAHA :rofl:After 35 years at it I should be like He-Man by now!

I have chosen a single test to focus on…I will report back my findings when I have some as I am dying to know what the Eureka moment will feel like.

1 Like

Tried it with character code lists:

madness :-
    LHS = [defun((0,1,0),tk((7,1,7),`foo`),[tk((12,1,12),`xyx`)],[])],
    RHS = [defun((0,1,0),tk((7,1,7),`foo`),[tk((12,1,12),`xyz`)],[])],
    assertion(LHS == RHS).

ERROR: Assertion failed: user:([defun((0,1,0),tk((7,1,7),[102,111,111]),[tk((12,1,12),[120,121,120])],[])]==[defun((0,1,0),tk((7,1,7),[102,111,111]),[tk((12,1,12),[120,121,122])],[])])

and as string objects:

?- madness.
madness :-
    LHS = [defun((0,1,0),tk((7,1,7),"foo"),[tk((12,1,12),"xyx")],[])],
    RHS = [defun((0,1,0),tk((7,1,7),"foo"),[tk((12,1,12),"xyz")],[])],
    assertion(LHS == RHS).

ERROR: Assertion failed: user:([defun((0,1,0),tk((7,1,7),"foo"),[tk((12,1,12),"xyx")],[])]==[defun((0,1,0),tk((7,1,7),"foo"),[tk((12,1,12),"xyz")],[])])

This is in a separate scratch file, loaded in isolation in a new session. I just can’t figure out why it works some times and not others.I did notice that one of the passing tests was using “=” instead of “==”, so I changed that (= is bad) and it failed as well! LMAO

I looked in other files for similar tests, this is a test that passes just fine, using the same “string” objects etc:

test(all_token_types, [true(Out==Exp)]) :-
    Exp = [ o_paren( (0,1,0)),
             token(  (1,1,1),"HELLO"),
             c_paren((6,1,6)),
             o_list( (7,1,7)),
             token(  (8,1,8),"WORLD"),
             c_list( (13,1,13)),
             o_map(  (14,1,14)),
             token(  (15,1,15),"AGAIN"),
             c_map(  (20,1,20)),
             comn(   (21,1,21),"THIS"),
             comn(   (29,1,29),"IS"),
             token(  (35,1,35),":A"),
             str2(   (37,1,37),"TEST"),
             str1(   (43,1,43),"OF"),
             token(  (47,1,47),"#f:TOKENISATION")
           ],
    tokenise(
        "(HELLO)[WORLD]{AGAIN}/*THIS*//*IS*/:A\"TEST\"'OF'#f:TOKENISATION",
        Out,
        []).

Still digging…

Immediately after posting I noticed “xyx” and “xyz”… :astonished: what idiot typed that?
Anyway, that fixed that test then…

…and then I noticed it in the second test too, and in the first test that passed with “=” and failed with “==” , that test hadn’t fully specified the token positions, I was rather expecting this to work:

but it didn’t I had to be fully explicit to make the test pass…maybe I have misunderstood what “==” is doing …but I guess that’s why it passed with “=” because unification …!

Basically, I have been a total slap head and the only problem was PEBKAC as usual.

But…I became even better at perseverance…again… :expressionless:

PS. I love Prolog really! Actually, it’s got me now to the point where I don’t ever want to work again if I have to use anything else, Erlang I will make an exception for!

All my tests are green, but not as green as I am right now…

1 Like

When I noted character code list I meant to run the string through string_codes/2, e.g.

?- string_codes("xyx",Codes).
Codes = [120, 121, 120].

See the “xyz” klurking there…it’s a monster! :smiley:

1 Like

Ideally, if two terms do not match it should highlight the location of the mismatch … Anyone with a good term-diff around?

1 Like

In Emacs, split the window into two, position your cursor in one window to the beginning of one of the terms and the cursor in the other window to the beginning of the other term; then execute M-x compare-windows. (I learned years ago that my “eye-grep” is very fallible.)

2 Likes

WOW Peter…I’ve used emacs for 25+ years and never even knew that feature existed!

My working assumption with emacs is that if I wonder whether something is possible, it is … but might require a bit of searching to find.

BTW, I use the *compilation* window a lot; in a situation where a comparison failed, I’d see the error messages in the *compilation* window and would then do the window-split / compare trick.

Also: I highly recommend updating to the latest version of Emacs (28.0.50 or so) at git://git.sv.gnu.org/emacs.git and building it locally. Or install from the later snapshots at EmacsWiki: Emacs Snapshot And Debian . There are big performance improvements for handling large files, amongst other things (I generate large files of Prolog facts, so this really helps me).

I used to always build my own but in the last decade, well, lazy! I will do that this very evening and see how I fare! I mean, if I can get SWI to build locally emacs ought to be easy! :wink:

I’ve yet to use Prolog for anything in my day job but I cannot bear to think of a day job not using it! But…hens teeth and rocking horse pooh.

Done1 Got my own build running just fine thanks Peter. I’ll spend the rest of the evening with it now and try out compare-windows too!

:slight_smile: and of course :+1: