Prolog Example Unit Tests

These small examples are designed to run quickly
with the Gerrit prolog-shell, but not depending
on a local Gerrit repository server.

Change-Id: I8f58a6740c6f2c79ae1314f2ae593409ee60440d
diff --git a/prologtests/examples/aosp_rules.pl b/prologtests/examples/aosp_rules.pl
new file mode 100644
index 0000000..18e8a73
--- /dev/null
+++ b/prologtests/examples/aosp_rules.pl
@@ -0,0 +1,148 @@
+% A simplified and mocked AOSP rules.pl
+
+%%%%% wrapper functions for unit tests
+
+change_branch(X) :- gerrit:change_branch(X).
+change_project(X) :- gerrit:change_project(X).
+commit_author(U,N,M) :- gerrit:commit_author(U,N,M).
+commit_delta(X) :- gerrit:commit_delta(X).
+commit_label(L,U) :- gerrit:commit_label(L,U).
+uploader(X) :- gerrit:uploader(X).
+
+%%%%% true/false conditions
+
+% Special auto-merger accounts.
+is_exempt_uploader :-
+  uploader(user(Id)),
+  memberchk(Id, [104, 106]).
+
+% Build cop overrides everything.
+has_build_cop_override :-
+  commit_label(label('Build-Cop-Override', 1), _).
+
+is_exempt_from_reviews :-
+  or(is_exempt_uploader, has_build_cop_override).
+
+% Some files in selected projects need API review.
+needs_api_review :-
+  commit_delta('^(.*/)?api/|^(system-api/)'),
+  change_project(Project),
+  memberchk(Project, [
+    'platform/external/apache-http',
+    'platform/frameworks/base',
+    'platform/frameworks/support',
+    'platform/packages/services/Car',
+    'platform/prebuilts/sdk'
+  ]).
+
+% Some branches need DrNo review.
+needs_drno_review :-
+  change_branch(Branch),
+  memberchk(Branch, [
+    'refs/heads/my-alpha-dev',
+    'refs/heads/my-beta-dev'
+  ]).
+
+% Some author email addresses need Qualcomm-Review.
+needs_qualcomm_review :-
+  commit_author(_, _, M),
+  regex_matches(
+'.*@(qti.qualcomm.com|qca.qualcomm.com|quicinc.com|qualcomm.com)', M).
+
+% Special projects, branches, user accounts
+% can opt out owners review.
+opt_out_find_owners :-
+  change_branch(Branch),
+  memberchk(Branch, [
+    'refs/heads/my-beta-testing',
+    'refs/heads/my-testing'
+  ]).
+
+% Special projects, branches, user accounts
+% can opt in owners review.
+% Note that opt_out overrides opt_in.
+opt_in_find_owners :- true.
+
+
+%%%%% Simple list filters.
+
+remove_label(X, In, Out) :-
+  gerrit:remove_label(In, label(X, _), Out).
+
+% Slow but simple for short input list.
+remove_review_categories(In, Out) :-
+  remove_label('API-Review', In, L1),
+  remove_label('Code-Review', L1, L2),
+  remove_label('DrNo-Review', L2, L3),
+  remove_label('Owner-Review-Vote', L3, L4),
+  remove_label('Qualcomm-Review', L4, L5),
+  remove_label('Verified', L5, Out).
+
+
+%%%%% Missing rules in Gerrit Prolog Cafe.
+
+or(InA, InB) :- once((A;B)).
+
+not(Goal) :- Goal -> false ; true.
+
+% memberchk(+Element, +List)
+memberchk(X, [H|T]) :-
+  (X = H -> true ; memberchk(X, T)).
+
+maplist(Functor, In, Out) :-
+  (In = []
+  -> Out = []
+  ;  (In = [X1|T1],
+      Out = [X2|T2],
+      Goal =.. [Functor, X1, X2],
+      once(Goal),
+      maplist(Functor, T1, T2)
+     )
+  ).
+
+
+%%%%% Conditional rules and filters.
+
+submit_filter(In, Out) :-
+  (is_exempt_from_reviews
+  -> remove_review_categories(In, Out)
+  ;  (check_review(needs_api_review,
+          'API_Review', In, L1),
+      check_review(needs_drno_review,
+          'DrNo-Review', L1, L2),
+      check_review(needs_qualcomm_review,
+          'Qualcomm-Review', L2, L3),
+      check_find_owners(L3, Out)
+     )
+  ).
+
+check_review(NeedReview, Label, In, Out) :-
+  (NeedReview
+  -> Out = In
+  ;  remove_label(Label, In, Out)
+  ).
+
+% If opt_out_find_owners is true,
+% remove all 'Owner-Review-Vote' label;
+% else if opt_in_find_owners is true,
+%      call find_owners:submit_filter;
+% else default to no find_owners filter.
+check_find_owners(In, Out) :-
+  (opt_out_find_owners
+  -> remove_label('Owner-Review-Vote', In, Temp)
+  ; (opt_in_find_owners
+    -> find_owners:submit_filter(In, Temp)
+    ; In = Temp
+    )
+  ),
+  Temp =.. [submit | L1],
+  remove_label('Owner-Approved', L1, L2),
+  maplist(owner_may_to_need, L2, L3),
+  Out =.. [submit | L3].
+
+% change may(_) to need(_) to block submit.
+owner_may_to_need(In, Out) :-
+  (In = label('Owner-Review-Vote', may(_))
+  -> Out = label('Owner-Review-Vote', need(_))
+  ;  Out = In
+  ).