diff --git a/src/test/fixtures/syntax-error/deny-expecting-allow/Main.hp b/src/test/fixtures/syntax-error/deny-expecting-allow/Main.hp new file mode 100644 index 0000000..6cbf471 --- /dev/null +++ b/src/test/fixtures/syntax-error/deny-expecting-allow/Main.hp @@ -0,0 +1,12 @@ +import Syntax; + +main = + DENY + EXCEPT { + ALLOW { + Actors: Analyst + Resources + Actions + } + DENY Syntax::alice + }; \ No newline at end of file diff --git a/src/test/fixtures/syntax-error/deny-expecting-allow/Syntax.hp b/src/test/fixtures/syntax-error/deny-expecting-allow/Syntax.hp new file mode 100644 index 0000000..1876ce0 --- /dev/null +++ b/src/test/fixtures/syntax-error/deny-expecting-allow/Syntax.hp @@ -0,0 +1,21 @@ +export Syntax where + +data Actors = + Looker(Analyst), + Analyst(Alice, Bob), + Intern(Bob, Jeff), + Alice, Bob, Jeff; + +data Actions = Reads, Deletes, Updates; + +data Resources = + Claims(Finance), + Finance(Customers, Companies), + Customers(CCN), Companies(EMAIL, SSN), + CCN, EMAIL, SSN; + +alice = DENY { + Actors: Alice + Resources: CCN + Actions: Reads + }; \ No newline at end of file diff --git a/src/test/fixtures/syntax-error/imported-variable/ImportedVariableError.hp b/src/test/fixtures/syntax-error/imported-variable/ImportedVariableError.hp new file mode 100644 index 0000000..c746773 --- /dev/null +++ b/src/test/fixtures/syntax-error/imported-variable/ImportedVariableError.hp @@ -0,0 +1,21 @@ +export ImportedVariableError where + +data Actors = + Looker(Analyst), + Analyst(Alice, Bob), + Intern(Bob, Jeff), + Alice, Bob, Jeff; + +data Actions = Reads, Deletes, Updates; + +data Resources = + Claims(Finance), + Finance(Customers, Companies), + Customers(CCN), Companies(EMAIL, SSN), + CCN, EMAIL, SSN; + +alice = DENY { + Actors: Alice + Resources: CCN + Actions: Reads + }; \ No newline at end of file diff --git a/src/test/fixtures/syntax-error/imported-variable/Main.hp b/src/test/fixtures/syntax-error/imported-variable/Main.hp new file mode 100644 index 0000000..0ea31fe --- /dev/null +++ b/src/test/fixtures/syntax-error/imported-variable/Main.hp @@ -0,0 +1,19 @@ +import ImportedVariableError; + +main = + DENY + EXCEPT { + ALLOW { + Actors: Analyst + Resources + Actions + } + EXCEPT { + DENY { + Actors: Bob + Resources: EMAIL + Actions: Deletes, Updates, Reads + } + } + ALLOW ImportedVariableError::alice + }; \ No newline at end of file diff --git a/src/test/fixtures/visitor/nested-excepts/Main.hp b/src/test/fixtures/visitor/nested-excepts/Main.hp new file mode 100644 index 0000000..7e495ae --- /dev/null +++ b/src/test/fixtures/visitor/nested-excepts/Main.hp @@ -0,0 +1,18 @@ +import NestedExcepts; + +main = + DENY + EXCEPT { + ALLOW { + Actors: Analyst + Resources + Actions + } + EXCEPT { + DENY { + Actors: Bob + Resources: EMAIL + Actions: Deletes, Updates, Reads + } + } + }; \ No newline at end of file diff --git a/src/test/fixtures/visitor/nested-excepts/NestedExcepts.hp b/src/test/fixtures/visitor/nested-excepts/NestedExcepts.hp new file mode 100644 index 0000000..1d550b8 --- /dev/null +++ b/src/test/fixtures/visitor/nested-excepts/NestedExcepts.hp @@ -0,0 +1,15 @@ +export NestedExcepts where + +data Actors = + Looker(Analyst), + Analyst(Alice, Bob), + Intern(Bob, Jeff), + Alice, Bob, Jeff; + +data Actions = Reads, Deletes, Updates; + +data Resources = + Claims(Finance), + Finance(Customers, Companies), + Customers(CCN), Companies(EMAIL, SSN), + CCN, EMAIL, SSN; diff --git a/src/test/fixtures/wrong-name/undefined-attribute/Main.hp b/src/test/fixtures/wrong-name/undefined-attribute/Main.hp new file mode 100644 index 0000000..b58e1e9 --- /dev/null +++ b/src/test/fixtures/wrong-name/undefined-attribute/Main.hp @@ -0,0 +1,12 @@ +import UndefinedAttribute; + +main = + DENY + EXCEPT { + ALLOW { + Actors: Analyst + Resources + Actions + } + ALLOW Syntax::jeff + }; \ No newline at end of file diff --git a/src/test/fixtures/wrong-name/undefined-attribute/UndefinedAttribute.hp b/src/test/fixtures/wrong-name/undefined-attribute/UndefinedAttribute.hp new file mode 100644 index 0000000..59b1add --- /dev/null +++ b/src/test/fixtures/wrong-name/undefined-attribute/UndefinedAttribute.hp @@ -0,0 +1,21 @@ +export UndefinedAttribute where + +data Actors = + Looker(Analyst), + Analyst(Alice, Bob), + Intern(Bob, Jeff), + Alice, Bob, Jeff; + +data Actions = Reads, Deletes, Updates; + +data Resources = + Claims(Finance), + Finance(Customers, Companies), + Customers(CCN), Companies(EMAIL, SSN), + CCN, EMAIL, SSN; + +jeff = ALLOW { + Actors: Jefa // Undefined attribute error + Resources: CCN + Actions: Reads + }; \ No newline at end of file diff --git a/src/test/kotlin/unit/IRVisitorTest.kt b/src/test/kotlin/unit/IRVisitorTest.kt index 3f526a0..ec10ae2 100644 --- a/src/test/kotlin/unit/IRVisitorTest.kt +++ b/src/test/kotlin/unit/IRVisitorTest.kt @@ -88,5 +88,39 @@ class IRVisitorTest { val exception = assertFailsWith{ irFromString(programs.get(i), listOf("Prop")) } assertEquals(messages.get(i), exception.message) } + + @Test + @DisplayName("Should receive an undefined attribute error") + fun shouldReceiveUndefinedAttributeError() { + val file = "src/test/fixtures/wrong-name/undefined-attribute/Main.hp" + val priority = listOf("Actors", "Actions", "Resources") + val exception = assertFailsWith { irFromFile(file, priority) } + assertEquals("undefined attribute: Syntax::jeff::Actors = Jefa", exception.message) + } + + @Test + @DisplayName("Should return a syntax error on imported variable: DENY after an ALLOW") + fun shouldReturnSyntaxErrorImportedVariable() { + val file = "src/test/fixtures/syntax-error/imported-variable/Main.hp" + val priority = listOf("Actors", "Actions", "Resources") + + val exception = assertFailsWith { + irFromFile(file, priority) + } + + assertEquals("line 29:10 syntax error 'DENY' after an 'ALLOW'", exception.message) + + } + + @Test + @DisplayName("Should generate the correct IR even with multiple 'EXCEPT' nested") + fun shouldDenyBobActionsOnEmail() { + val file = "src/test/fixtures/visitor/nested-excepts/Main.hp" + val priority = listOf("Actors", "Actions", "Resources") + val castelo = "teste" + val ir = irFromFile(file, priority) + val expectedIRString = "{Bob={Updates=[SSN, CCN], Deletes=[SSN, CCN], Reads=[SSN, CCN]}, Alice={Updates=[SSN, EMAIL, CCN], Deletes=[SSN, EMAIL, CCN], Reads=[SSN, EMAIL, CCN]}}" + assertThat(ir.toString()).isEqualTo(expectedIRString) + } } } \ No newline at end of file diff --git a/src/test/kotlin/unit/ParsingTest.kt b/src/test/kotlin/unit/ParsingTest.kt index 8d90dc3..f55a2e1 100644 --- a/src/test/kotlin/unit/ParsingTest.kt +++ b/src/test/kotlin/unit/ParsingTest.kt @@ -39,7 +39,7 @@ class ParsingTest { } @Test - @DisplayName("Should throw ParseCancellationException on syntax rrror") + @DisplayName("Should throw ParseCancellationException on syntax error") fun shouldThrowParseCancellationExceptionOnSyntaxError(){ val program = """ @@ -55,6 +55,15 @@ class ParsingTest { val error = "line 6:10 mismatched input 'INVALID' expecting 'ALLOW'" assertFailsWith(error) { parse(tokenize(program)) } } + + @Test + @DisplayName("Should return 'mismatched input' on syntax error: input 'DENY' expecting 'ALLOW' or 'EXCEPT'") + fun shouldReturnSyntaxErrorDenyExpectingAllow() { + val file = "src/test/fixtures/syntax-error/deny-expecting-allow/Main.hp" + val error = "line 24:4 mismatched input 'DENY' expecting 'ALLOW'" + assertFailsWith(error) { parse(tokenize(file)) } + } + @Test @DisplayName("Should parse valid attribute expressions") fun shouldParseValidAttributeExpression(){