How to test model-wise Non-Typesystem rule?

Hi!
I have a root concept named "Page". It extends "AbstractRoot".
I also have a Non-Typesystem rule that there may not be two roots with the same name:

check_Root_has_unique_name_in_model
if (root.parent.isNull) { 
  root.model.roots(INamedConcept).forEach({~it => 
    if (it != root && it.name.equals(root.name)) { 
      error String.format("There's already a %s element with this name!", it.concept.getName()) -> root; 
    } 
  }); 
}
prettyPrint();

Now I'm trying to test this feature.
So I created a solution named "tests" and created a model in it, named "tests@tests".
I imported my language, "baseLanguage.unitTest", and "mps.lang.test".
Then I created new "NodesTestCase" that looks like this:

page_test.png


But this test fails, cuz there's no error.
It seems that two pages created in the test are not in the same model.
What I do wrong?
Is it possible to test cross-node rules?

Thanks in advance!

P.S.
I already have a similar test case for two stories with the same name in one page,
and it passes. So all imports seems to be fine.
5 comments
I guess this is because your page nodes are nested within a test case node, so they are not really roots when in tests, so the condition root.parent.isNull is never true.

Vaclav
0
Thanks for clarification!

So, it is possible to test the feature if I rewrite it to look for all nodes, and not only roots? )

I think I could rewrite the rule so it would look for all nodes, instead of only roots, and then it would explicitly filter out the nodes that shouldn't be checked (for example, I have a "story" concept that may be both a root and a page child, but it should be checked only if it's a root). But I fear it will overcomplicate with time, or I'll just forgot to add some new "exception" to the rule.

Is there currently any way to mark tested nodes to be treated as roots?
0
I would perhaps try to change the initial condition to check for an ancestor instead of a parent:

if (root.ancestor<concept = AbstractRoot>.isNull) {
...
0
Great thanks for the answers!
It works now )

I finally remembered about "Node Explorer" and this thing helps immensely )

page_test_2.png


So yeah, I've changed rule to look like this:

check_Root_has_unique_name_in_model
if (root.ancestor<concept = AbstractRoot>.isNull) { 
  root.model.nodes(AbstractRoot).forEach({~it => 
    if (it != root && it.name :eq: root.name) { 
      error String.format("There's already a %s element with this name!", it.concept.getName()) -> root; 
    } 
  }); 
}
prettyPrint();

So now it checks any "my root" that isn't part of another "my root".
Only need to remember now that any concept that will be compiled as separate java class should extend my "AbstractRoot".

Thanks again!
0
Quick fix:
I also had to add filter for iterated nodes in the model.
So top "abstract roots" is compared only to other top "abstract roots":

check_Root_has_unique_name_in_model
if (root.ancestor<concept = AbstractRoot>.isNull) { 
  root.model.nodes(AbstractRoot).where({~it => it.ancestor<concept = AbstractRoot>.isNull; }).forEach({~it => 
    if (it != root && it.name :eq: root.name) { 
      error String.format("There's already a %s element with this name!", it.concept.getName()) -> root; 
    } 
  }); 
}
prettyPrint();

Now it works perfectly )
0

Please sign in to leave a comment.