Do you think it would be feasible to simply copy the root of the tree to be operated on? Then the undo would entail pointing the tree's original parent to the copy and then redrawing. I don't know about copy performance (I suppose that a deep copy would be needed) on Leo nodes, but as a naive idea it seems simple.
First of all I must say that testing with hypothesis is really great way to discover hidden bugs. Several bugs were found in the previous implementation that are very hard to imagine as a possible scenario. Of course most of these bugs were related to clones. Hypothesis did find them really quickly and I had to think hard how to solve them. After several iterations of running hypothesis and solving found bugs, prototype is now able to survive 5000 test sessions. At first I have started each test with the complete LeoPyRef.leo outline, test would choose and select a random position in this outline, and then it would perform a random sequence of commands, checking after each command that both models (v-nodes and tree widget items) are in sync. It used to take several minutes for a series of 500 tests.To speed up tests, I have changed test to use a smaller outline as starting position. At start it inserts just five ordinary nodes interspersed with five cloned nodes (total of 15 node). Now hypothesis runs 5000 tests in about minute. After several executions no bug has been found.
It is highly unlikely that a new bug will be discovered using this test. That means we can be pretty sure that no matter what operations and in whichever order user executes both models: v-nodes and tree widget items will always remain in sync. The outline represented by each of them is exactly the same.
I looked at the code but I don't understand how to run the hypothesis tests. I would love to see it in action. Could you share the steps?
Have you also considered using the property of random operation + undo = original tree widget state? And random operation + undo + redo = 2nd state? I'm not sure that would reveal anything from what you are already testing. Just a thought.Brian
First of all I must say that testing with hypothesis is really great way to discover hidden bugs.
Now the question of executing scriptsHow should we re-synchronize tree widget with the possible changes in the outline made by user script? The more I think about this problem, the more I am sure that my initial plan of using diff algorithm won't work.
I can't speak for everyone else but I would gladly accept this delay on each executeScript command and in return have an insurance that no error in my script will destroy my outline irrecoverably. I would like to be sure that in case of an error in script I still can undo the whole operation and return to the previous state. I know for certain that on more than one occasion I've missed this undo ability very much.
QTreeWidgetItem class has a clone method which runs quite fast.
Cloning entire tree using this method is not problem at all. The problem is that if a script changes vnodes we need to synchronize them after script has finished. This synchronization can drop some items that are required for undoing earlier operations. To avoid this Leo should add to the undo list a new step which contains the copy of the tree items before executing script. All these operations are pretty cheap. The time will be spent in the redrawing tree from scratch after the script execution.
As I write this I've just realize that it would be possible to use diffing algorithm to update tree after the script. The only thing that is necessary is to make execute script undoable. Updating the tree using the diff algorithm will have exactly the same tree items as they were before the script. Nothing would be lost. All changes that must be made can be easily recorded in the undo bead for later undo/redo. This has a chance to make things a lot faster.
-from hypothesis import given, settings+from hypothesis import given, settings, Verbosity-@settings(max_examples=5000, deadline=timedelta(seconds=4))+@settings(max_examples=5000, deadline=timedelta(seconds=4), verbosity=Verbosity.verbose)
--
You received this message because you are subscribed to the Google Groups "leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leo-editor+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/leo-editor/0f5bb32d-20a9-49ea-ac86-bdc2b845e4f0%40googlegroups.com.
...
meth = getattr(app, name)
meth()
app.processEvents() # <--- add this line
...
If you want to have visual feedback add the following line in the test_select_and_commands function:
...
meth = getattr(app, name)
meth()
app.processEvents() # <--- add this line
...
Tests will run about 3 times slower, so you might want to change max_examples=5000 in the decorator to something less.
In last few days I've been working on tests to be sure that all commands in new prototype are working correctly and that no crash will ever occur. I am pretty sure now that the implementation is correct and there are no remaining bugs in the prototype.
Traceback (most recent call last):File "leo/extensions/myleoqt.py", line 333, in select_itemv = newitem.data(0, 1024)AttributeError: 'NoneType' object has no attribute 'data'Fatal Python error: AbortedCurrent thread 0x00007fad45034740 (most recent call first):File "leo/extensions/myleoqt.py", line 1227 in move_just_treeitemFile "leo/extensions/myleoqt.py", line 1213 in move_treeitemFile "leo/extensions/myleoqt.py", line 430 in domoveFile "leo/extensions/myleoqt.py", line 449 in make_undoable_moveFile "leo/extensions/myleoqt.py", line 557 in move_node_rightFile "leo/extensions/myleoqt.py", line 1594 in mainFile "leo/extensions/myleoqt.py", line 1597 in <module>Aborted (core dumped)
import faulthandler; faulthandler.enable()
Good catch Brian. Revision 8184a2023e5f9 contains the fix for this issue. Now hoist/dehoist commands are also tested using hypothesis.Vitalije
--
You received this message because you are subscribed to the Google Groups "leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leo-editor+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/leo-editor/ede74c56-e1b8-44e7-adb5-85a07b9355e8%40googlegroups.com.
It no longer crashes for me, thanks.While it doesn't crash, it is still possible to move a node left out of a hoist and the node "disappears". If it is the last node then it disappears and the outline pane becomes empty. The existing leo doesn't behave this way. Another behavior difference. Leo doesn't allow a top-level sibling to be inserted while a node is hoisted. Instead all top-level insert operations are forced to be child insertions.
data.draw(lists(sampled_from(method_names),...)I didn't find that hypothesis was slowing me down during development. When a bug combination is found, hypothesis checks this combination early. It means that until you fix the bug running hypothesis is almost exactly as running a special hand-written test for just this sequence of commands. If the bug is fixed then you'll have to wait more to see if there is another one.Almost all serious bugs were found in less than 10s, and each next run until bug was fixed took less than a second. If there is no more bugs you'll have to wait a lot for the test to finish, but for me it is a pleasure waiting and knowing that thousands of tests are passing.