schema compile CHANGE support for RPC/action in deviations and additional tests
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index bbf0d9b..37439dc 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -4888,6 +4888,7 @@
     struct ly_set targets = {0};
     struct lysc_node *target; /* target target of the deviation */
     struct lysc_node_list *list;
+    struct lysc_action *actions;
     struct lysp_deviation *dev;
     struct lysp_deviate *d, **dp_new;
     struct lysp_deviate_add *d_add;
@@ -4930,7 +4931,19 @@
         /* resolve the target */
         LY_CHECK_GOTO(lys_resolve_schema_nodeid(ctx, dev->nodeid, 0, NULL, ctx->mod, 0, 1,
                                                 (const struct lysc_node**)&target, &flags), cleanup);
-
+        if (target->nodetype == LYS_ACTION) {
+            /* move the target pointer to input/output to make them different from the action and
+             * between them. Before the devs[] item is being processed, the target pointer must be fixed
+             * back to the RPC/action node due to a better compatibility and decision code in this function.
+             * The LYSC_OPT_INTERNAL is used as a flag to this change. */
+            if (flags & LYSC_OPT_RPC_INPUT) {
+                target = (struct lysc_node*)&((struct lysc_action*)target)->input;
+                flags |= LYSC_OPT_INTERNAL;
+            } else if (flags & LYSC_OPT_RPC_OUTPUT) {
+                target = (struct lysc_node*)&((struct lysc_action*)target)->output;
+                flags |= LYSC_OPT_INTERNAL;
+            }
+        }
         /* insert into the set of targets with duplicity detection */
         i = ly_set_add(&targets, target, 0);
         if (!devs[i]) {
@@ -5030,15 +5043,55 @@
 
     /* apply deviations */
     for (u = 0; u < devs_p.count && devs[u]; ++u) {
+        if (devs[u]->flags & LYSC_OPT_INTERNAL) {
+            /* fix the target pointer in case of RPC's/action's input/output */
+            if (devs[u]->flags & LYSC_OPT_RPC_INPUT) {
+                devs[u]->target = (struct lysc_node*)((char*)devs[u]->target - offsetof(struct lysc_action, input));
+            } else if (devs[u]->flags & LYSC_OPT_RPC_OUTPUT) {
+                devs[u]->target = (struct lysc_node*)((char*)devs[u]->target - offsetof(struct lysc_action, output));
+            }
+        }
+
         /* not-supported */
         if (devs[u]->not_supported) {
             if (LY_ARRAY_SIZE(devs[u]->deviates) > 1) {
                 LOGWRN(ctx->ctx, "Useless multiple (%u) deviates on node \"%s\" since the node is not-supported.",
                        LY_ARRAY_SIZE(devs[u]->deviates), devs[u]->nodeid);
             }
-            /* remove the target node */
-            lysc_disconnect(devs[u]->target);
-            lysc_node_free(ctx->ctx, devs[u]->target);
+            if (devs[u]->target->nodetype == LYS_ACTION) {
+                if (devs[u]->flags & LYSC_OPT_RPC_INPUT) {
+                    /* remove RPC's/action's input */
+                    lysc_action_inout_free(ctx->ctx, &((struct lysc_action*)devs[u]->target)->input);
+                    memset(&((struct lysc_action*)devs[u]->target)->input, 0, sizeof ((struct lysc_action*)devs[u]->target)->input);
+                } else if (devs[u]->flags & LYSC_OPT_RPC_OUTPUT) {
+                    /* remove RPC's/action's output */
+                    lysc_action_inout_free(ctx->ctx, &((struct lysc_action*)devs[u]->target)->output);
+                    memset(&((struct lysc_action*)devs[u]->target)->output, 0, sizeof ((struct lysc_action*)devs[u]->target)->output);
+                } else {
+                    /* remove RPC/action */
+                    if (devs[u]->target->parent) {
+                        actions = (struct lysc_action*)lysc_node_actions(devs[u]->target->parent);
+                    } else {
+                        actions = devs[u]->target->module->compiled->rpcs;
+                    }
+                    LY_ARRAY_FOR(actions, x) {
+                        if (&actions[x] == (struct lysc_action*)devs[u]->target) {
+                            break;
+                        }
+                    }
+                    if (x < LY_ARRAY_SIZE(actions)) {
+                        lysc_action_free(ctx->ctx, &actions[x]);
+                        memmove(&actions[x], &actions[x + 1], (LY_ARRAY_SIZE(actions) - (x + 1)) * sizeof *actions);
+                        LY_ARRAY_DECREMENT(actions);
+                    }
+                }
+            } else if (devs[u]->target->nodetype == LYS_NOTIF) {
+                /* TODO Notification */
+            } else {
+                /* remove the target node */
+                lysc_disconnect(devs[u]->target);
+                lysc_node_free(ctx->ctx, devs[u]->target);
+            }
 
             continue;
         }