From 7640704945240d8c3fd608607cc45348fdc7f712 Mon Sep 17 00:00:00 2001
From: Anders Blomdell <anders.blomdell@control.lth.se>
Date: Thu, 21 May 2015 14:54:48 +0200
Subject: [PATCH] Implementation of renaming encoder. Typedef trees are not
 correctly encoded!

---
 lib/c/2014/Makefile                       |  12 +-
 lib/c/2014/labcomm2014_renaming.c         |  49 ++++
 lib/c/2014/labcomm2014_renaming.h         |  34 +++
 lib/c/2014/labcomm2014_renaming_encoder.c | 232 ++++++++++++++++++
 lib/c/2014/labcomm2014_renaming_encoder.h |  32 +++
 lib/c/2014/test/test_labcomm_renaming.c   | 283 ++++++++++++++++++++++
 6 files changed, 639 insertions(+), 3 deletions(-)
 create mode 100644 lib/c/2014/labcomm2014_renaming.c
 create mode 100644 lib/c/2014/labcomm2014_renaming.h
 create mode 100644 lib/c/2014/labcomm2014_renaming_encoder.c
 create mode 100644 lib/c/2014/labcomm2014_renaming_encoder.h
 create mode 100644 lib/c/2014/test/test_labcomm_renaming.c

diff --git a/lib/c/2014/Makefile b/lib/c/2014/Makefile
index 0e7aca5..6065992 100644
--- a/lib/c/2014/Makefile
+++ b/lib/c/2014/Makefile
@@ -20,9 +20,11 @@ OBJS=labcomm$(VERSION).o \
      labcomm$(VERSION)_decoder.o \
      labcomm$(VERSION)_dynamic_buffer_writer.o \
      labcomm$(VERSION)_fd_reader.o \
-	 labcomm$(VERSION)_type_signature.o \
+     labcomm$(VERSION)_type_signature.o \
      labcomm$(VERSION)_fd_writer.o \
-     labcomm$(VERSION)_pthread_scheduler.o 
+     labcomm$(VERSION)_pthread_scheduler.o \
+     labcomm$(VERSION)_renaming.o \
+     labcomm$(VERSION)_renaming_encoder.o
 
 # Enable experimental objects by `make LABCOMM_EXPERIMENTAL=true`
 ifeq ($(LABCOMM_EXPERIMENTAL),true)
@@ -46,7 +48,8 @@ TESTS=test_labcomm_basic_type_encoding \
       test_signature_numbers \
       test_labcomm \
       test_labcomm_pthread_scheduler \
-      test_labcomm_copy
+      test_labcomm_copy \
+      test_labcomm_renaming
 #FIXME: test_labcomm_errors
 
 TEST_DIR=test
@@ -169,3 +172,6 @@ $(TEST_DIR)/gen/test_labcomm_copy: \
 	$(TEST_DIR)/gen/generated_encoding.o \
 	$(TEST_DIR)/gen/test_sample.o \
 	$(TEST_DIR)/gen/more_types.o
+
+$(TEST_DIR)/gen/test_labcomm_renaming: \
+	$(TEST_DIR)/gen/generated_encoding.o
diff --git a/lib/c/2014/labcomm2014_renaming.c b/lib/c/2014/labcomm2014_renaming.c
new file mode 100644
index 0000000..aeaee53
--- /dev/null
+++ b/lib/c/2014/labcomm2014_renaming.c
@@ -0,0 +1,49 @@
+/*
+  labcomm2014_renaming.c -- functions intended for renaming
+                            encoders and decoders
+
+  Copyright 2015 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "labcomm2014_renaming.h"
+#include <string.h>
+#include <stdio.h>
+
+char *labcomm2014_renaming_prefix(struct labcomm2014_memory *m,
+                                  char *name, void *context)
+{
+  char *result, *prefix = context;
+  int length;
+
+  length = strlen(name) + strlen(prefix) + 1;
+  result = labcomm2014_memory_alloc(m, 0, length);
+  if (result != NULL) {
+    strcpy(result, prefix);
+    strcat(result, name);
+  }
+  fprintf(stderr, "%s + %s -> %s\n", prefix, name, result);
+  return result;
+  
+}
+
+char *labcomm2014_renaming_suffix(struct labcomm2014_memory *m,
+                                  char *name, void *context)
+{
+  return labcomm2014_renaming_prefix(m, context, name);
+}
+
diff --git a/lib/c/2014/labcomm2014_renaming.h b/lib/c/2014/labcomm2014_renaming.h
new file mode 100644
index 0000000..903010e
--- /dev/null
+++ b/lib/c/2014/labcomm2014_renaming.h
@@ -0,0 +1,34 @@
+/*
+  labcomm2014_renaming.h -- functions intended for renaming
+                            encoders and decoders
+
+  Copyright 2015 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __LABCOMM2014_RENAMING_H__
+#define __LABCOMM2014_RENAMING_H__
+
+#include "labcomm2014.h"
+
+char *labcomm2014_renaming_prefix(struct labcomm2014_memory *m,
+                                  char *name, void *context);
+
+char *labcomm2014_renaming_suffix(struct labcomm2014_memory *m,
+                                  char *name, void *context);
+
+#endif
diff --git a/lib/c/2014/labcomm2014_renaming_encoder.c b/lib/c/2014/labcomm2014_renaming_encoder.c
new file mode 100644
index 0000000..414702e
--- /dev/null
+++ b/lib/c/2014/labcomm2014_renaming_encoder.c
@@ -0,0 +1,232 @@
+/*
+  labcomm2014_renaming_encoder.c -- a stacked encoder that renames samples
+
+  Copyright 2015 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <errno.h>
+#include "labcomm2014_renaming_encoder.h"
+#include "labcomm2014.h"
+#include "labcomm2014_private.h"
+
+struct encoder {
+  struct labcomm2014_encoder encoder;
+  struct labcomm2014_encoder *next;
+  char *(*rename)(struct labcomm2014_memory *m, char *name, void *context);
+  void *context;
+  LABCOMM_SIGNATURE_ARRAY_DEF(renamed, struct labcomm2014_signature *);
+};
+
+static struct labcomm2014_signature *get_renamed(
+  struct labcomm2014_encoder *e,
+  const struct labcomm2014_signature *signature)
+{
+  struct labcomm2014_signature *result;
+  struct encoder *ie = e->context;
+  int index;
+
+  index = labcomm2014_get_local_index(signature);
+  labcomm2014_scheduler_writer_lock(e->scheduler);
+  result = LABCOMM_SIGNATURE_ARRAY_GET(ie->renamed,
+                                      struct labcomm2014_signature *,
+                                      index, NULL);
+  labcomm2014_scheduler_writer_unlock(e->scheduler);
+  return result;
+}
+  
+static struct labcomm2014_signature *set_renamed(
+  struct labcomm2014_encoder *e,
+  const struct labcomm2014_signature *signature)
+{
+  struct labcomm2014_signature *result;
+
+  result = get_renamed(e, signature);
+  if (result == NULL) {
+    /* create a renamed sample */
+    struct encoder *ie = e->context;
+    int index;
+    struct labcomm2014_signature **renamed;
+  
+    index = labcomm2014_get_local_index(signature);
+    if (index <= 0) { goto out; /*result already NULL */}
+    labcomm2014_scheduler_writer_lock(e->scheduler);
+    renamed = LABCOMM_SIGNATURE_ARRAY_REF(e->memory, ie->renamed,
+                                          struct labcomm2014_signature *,
+                                          index);
+    if (renamed == NULL) {
+      labcomm2014_error_warning(e->error,
+                                LABCOMM2014_ERROR_MEMORY,
+                                "Could not allocate rename slot: %s\n",
+                                signature->name);
+      goto unlock;
+    }
+    if (*renamed != NULL) {
+      /* Somebody beat as to allocation, this should never happen */
+      goto unlock;
+    }
+    result = labcomm2014_memory_alloc(e->memory, 0, sizeof(*result));
+    if (result == NULL) {
+      labcomm2014_error_warning(e->error,
+                                LABCOMM2014_ERROR_MEMORY,
+                                "Could not allocate rename signature: %s\n",
+                                signature->name);
+      goto unlock;
+    }
+    result->name = ie->rename(e->memory, signature->name, ie->context);
+    if (result->name == NULL) {
+      labcomm2014_error_warning(e->error,
+                                LABCOMM2014_ERROR_MEMORY,
+                                "Could not allocate rename name: %s\n",
+                                signature->name);
+      goto unlock_free_result;
+    }
+    result->encoded_size = signature->encoded_size;
+    result->size = signature->size;
+    result->signature = signature->signature; 
+    result->index = 0;
+#ifndef LABCOMM_NO_TYPEDECL
+    result->tdsize = signature->tdsize;
+    result->treedata = signature->treedata;
+#endif  
+    labcomm2014_set_local_index(result);
+    *renamed = result;
+    goto unlock;
+  unlock_free_result:
+    labcomm2014_memory_free(e->memory, 0, result);
+    result = NULL;
+  unlock:
+    labcomm2014_scheduler_writer_unlock(e->scheduler);
+  out:
+    ;
+  }
+  return result;
+}
+  
+static int do_type_register(struct labcomm2014_encoder *e,
+                            const struct labcomm2014_signature *signature)
+{
+  struct encoder *ie = e->context;
+  
+  return ie->next->type_register(ie->next, set_renamed(e, signature));
+}
+
+static int do_type_bind(struct labcomm2014_encoder *e,
+                        const struct labcomm2014_signature *signature,
+                        char has_deps)
+{
+  struct encoder *ie = e->context;
+  
+  return ie->next->type_bind(ie->next, set_renamed(e, signature), has_deps);
+}
+
+static int do_sample_register(struct labcomm2014_encoder *e, 
+                         const struct labcomm2014_signature *signature, 
+                         labcomm2014_encoder_function encode)
+{
+  struct encoder *ie = e->context;
+  
+  return ie->next->sample_register(ie->next, set_renamed(e, signature), encode);
+}
+
+static int do_ref_register(struct labcomm2014_encoder *e, 
+                      const struct labcomm2014_signature *signature)
+{
+  struct encoder *ie = e->context;
+  
+  return ie->next->ref_register(ie->next, set_renamed(e, signature));
+}
+
+static int do_encode(struct labcomm2014_encoder *e, 
+                     const struct labcomm2014_signature *signature, 
+                     labcomm2014_encoder_function encode,
+                     void *value)
+{
+  struct encoder *ie = e->context;
+  
+  return ie->next->encode(ie->next, get_renamed(e, signature), encode, value);
+}
+
+static int do_ioctl(struct labcomm2014_encoder *e, 
+                    const struct labcomm2014_signature *signature,
+                    uint32_t ioctl_action, va_list args)
+{
+  struct encoder *ie = e->context;
+  
+  return ie->next->ioctl(ie->next, get_renamed(e, signature),
+                         ioctl_action, args);
+}
+
+static int do_signature_to_index(struct labcomm2014_encoder *e,
+                                 const struct labcomm2014_signature *signature)
+{
+  struct encoder *ie = e->context;
+  
+  return ie->next->signature_to_index(ie->next, get_renamed(e, signature));
+}
+
+static void do_free(struct labcomm2014_encoder *e)
+{
+  struct encoder *ie = e->context;
+  int i;
+
+  LABCOMM_SIGNATURE_ARRAY_FOREACH(ie->renamed, struct labcomm2014_signature *,
+                                  i) {
+    struct labcomm2014_signature *s;
+    s = LABCOMM_SIGNATURE_ARRAY_GET(ie->renamed,
+                                    struct labcomm2014_signature *, i, NULL);
+    if (s) {
+      labcomm2014_memory_free(e->memory, 0, s->name);
+      labcomm2014_memory_free(e->memory, 0, s);
+    }
+  }
+  LABCOMM_SIGNATURE_ARRAY_FREE(e->memory, ie->renamed,
+                               struct labcomm2014_signature *);
+  labcomm2014_memory_free(e->memory, 0, ie);
+}
+
+struct labcomm2014_encoder *labcomm2014_renaming_encoder_new(
+  struct labcomm2014_encoder *e,
+  char *(*rename)(struct labcomm2014_memory *m, char *name, void *context),
+  void *context)
+{
+  struct encoder *result;
+  result = labcomm2014_memory_alloc(e->memory, 0, sizeof(*result));
+  if (!result) {
+    return NULL;
+  } else {
+      result->encoder.context = result;
+      result->encoder.writer = NULL;
+      result->encoder.error = e->error;
+      result->encoder.memory = e->memory;
+      result->encoder.scheduler = e->scheduler;
+      result->encoder.free = do_free;
+      result->encoder.type_register = do_type_register;
+      result->encoder.type_bind = do_type_bind;
+      result->encoder.sample_register = do_sample_register;
+      result->encoder.ref_register = do_ref_register;
+      result->encoder.encode = do_encode;
+      result->encoder.ioctl = do_ioctl;
+      result->encoder.signature_to_index = do_signature_to_index;
+      result->next = e;
+      result->rename = rename;
+      result->context = context;
+      LABCOMM_SIGNATURE_ARRAY_INIT(result->renamed,
+                                   struct labcomm2014_signature *);
+      return &(result->encoder);
+  }
+}
diff --git a/lib/c/2014/labcomm2014_renaming_encoder.h b/lib/c/2014/labcomm2014_renaming_encoder.h
new file mode 100644
index 0000000..acbcbae
--- /dev/null
+++ b/lib/c/2014/labcomm2014_renaming_encoder.h
@@ -0,0 +1,32 @@
+/*
+  labcomm2014_renaming_encoder.h -- a stacked encoder that renames samples
+
+  Copyright 2015 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __LABCOMM2014_RENAMING_ENCODER_H__
+#define __LABCOMM2014_RENAMING_ENCODER_H__
+
+#include "labcomm2014.h"
+
+struct labcomm2014_encoder *labcomm2014_renaming_encoder_new(
+  struct labcomm2014_encoder *e,
+  char *(*rename)(struct labcomm2014_memory *m, char *name, void *context),
+  void *context);
+
+#endif
diff --git a/lib/c/2014/test/test_labcomm_renaming.c b/lib/c/2014/test/test_labcomm_renaming.c
new file mode 100644
index 0000000..fc52e60
--- /dev/null
+++ b/lib/c/2014/test/test_labcomm_renaming.c
@@ -0,0 +1,283 @@
+/*
+  test_labcomm2014_renaming.c -- LabComm tests of renaming
+
+  Copyright 2015 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "labcomm2014_private.h"
+#include "labcomm2014_default_error_handler.h"
+#include "labcomm2014_default_memory.h"
+#include "labcomm2014_pthread_scheduler.h"
+#include "labcomm2014_renaming.h"
+#include "labcomm2014_renaming_encoder.h"
+#include "test/gen/generated_encoding.h"
+
+#define IOCTL_WRITER_ASSERT_BYTES 4096
+#define IOCTL_WRITER_RESET 4097
+
+#define EXPECT(...)							\
+  {                                                                     \
+    int expected[] = __VA_ARGS__;					\
+    labcomm2014_encoder_ioctl(encoder, IOCTL_WRITER_ASSERT_BYTES,       \
+			  __LINE__,					\
+			  sizeof(expected)/sizeof(expected[0]),		\
+			  expected);					\
+  }
+
+#define VARIABLE(i) -(i + 1)
+#define IS_VARIABLE(i) (i < 0)
+
+static unsigned char buffer[128];
+struct labcomm2014_writer *writer;
+static int seen_variable[1024];
+
+static int buf_writer_alloc(
+  struct labcomm2014_writer *w, 
+  struct labcomm2014_writer_action_context *action_context)
+{
+  writer = w; /* Hack */
+  w->data_size = sizeof(buffer);
+  w->count = w->data_size;
+  w->data = buffer;
+  w->pos = 0;
+  
+  return 0;
+}
+
+static int buf_writer_free(
+  struct labcomm2014_writer *w, 
+  struct labcomm2014_writer_action_context *action_context)
+{
+  return 0;
+}
+
+static int buf_writer_start(
+  struct labcomm2014_writer *w,
+  struct labcomm2014_writer_action_context *action_context,
+  int index,
+  const struct labcomm2014_signature *signature,
+  void *value)
+{
+  return 0;
+}
+
+static int buf_writer_end(
+  struct labcomm2014_writer *w, 
+  struct labcomm2014_writer_action_context *action_context)
+{
+  return 0;
+}
+
+static int buf_writer_flush(
+  struct labcomm2014_writer *w, 
+  struct labcomm2014_writer_action_context *action_context)
+{
+  fprintf(stderr, "Should not come here %s:%d\n", __FILE__, __LINE__);
+  exit(1);
+  
+  return 0;
+}
+
+static int buf_writer_ioctl(
+  struct labcomm2014_writer *w, 
+  struct labcomm2014_writer_action_context *action_context,
+  int signature_index, const struct labcomm2014_signature *signature,
+  uint32_t action, va_list arg)
+{
+  int result = -ENOTSUP;
+  switch (action) {
+    case IOCTL_WRITER_ASSERT_BYTES: {
+      int line = va_arg(arg, int);
+      int count = va_arg(arg, int);
+      int *expected = va_arg(arg, int *);
+      int i, mismatch;
+
+      mismatch = 0;
+      if (w->pos != count) {
+	fprintf(stderr, "Invalid length detected %d != %d (%s:%d)\n", 
+		w->pos, count, __FILE__, line);
+	mismatch = 1;
+      } 
+      for (i = 0 ; i < count ; i++) {
+        if (IS_VARIABLE(expected[i])) {
+          if (seen_variable[VARIABLE(expected[i])] == -1) {
+            seen_variable[VARIABLE(expected[i])] = buffer[i];
+          }
+          if (seen_variable[VARIABLE(expected[i])] != buffer[i]) {
+            fprintf(stderr, "Unexpected variable (%d:  != %d)\n",
+                    seen_variable[VARIABLE(expected[i])], buffer[i]);
+            mismatch = 1;
+          }
+        } else if (expected[i] != buffer[i]) {
+	  mismatch = 1;
+	}
+      }
+      if (mismatch) {
+	fprintf(stderr, "Encoder mismatch (%s:%d)\n",
+		__FILE__, line);
+
+	for (i = 0 ; i < w->pos ; i++) {
+	  printf("%2.2x ", w->data[i]);
+	}
+	printf("\n");
+	for (i = 0 ; i < count ; i++) {
+	  if (expected[i] < 0) {
+	    printf("v%d ", VARIABLE(expected[i]));
+	  } else {
+	    printf("%2.2x ", expected[i] );
+	  }
+	}
+	printf("\n");
+	exit(1);
+      }
+      result = 0;
+    } break;
+    case IOCTL_WRITER_RESET: {
+      w->pos = 0;
+      result = 0;
+    }
+  }
+  return result;
+}
+
+const struct labcomm2014_writer_action writer_action = {
+  .alloc = buf_writer_alloc,
+  .free = buf_writer_free,
+  .start = buf_writer_start,
+  .end = buf_writer_end,
+  .flush = buf_writer_flush,
+  .ioctl = buf_writer_ioctl
+};
+
+static struct labcomm2014_writer_action_context action_context = {
+  .next = NULL,
+  .action = &writer_action,
+  .context = NULL
+}; 
+static struct labcomm2014_writer buffer_writer = {
+  .action_context = &action_context,
+  .data = buffer,
+  .data_size = sizeof(buffer),
+  .count = sizeof(buffer),
+  .pos = 0,
+  .error = 0,
+};
+
+void dump_encoder(struct labcomm2014_encoder *encoder)
+{
+  int i;
+  
+  for (i = 0 ; i < writer->pos ; i++) {
+    printf("%2.2x ", writer->data[i]);
+  }
+  printf("\n");
+}
+
+int main(void)
+{
+  struct labcomm2014_encoder *encoder, *prefix, *suffix;
+  int i;
+
+  for (i = 0 ; i < sizeof(seen_variable)/sizeof(seen_variable[0]) ; i++) {
+    seen_variable[i] = -1;
+  }
+
+  encoder = labcomm2014_encoder_new(
+    &buffer_writer, 
+    labcomm2014_default_error_handler,
+    labcomm2014_default_memory,
+    labcomm2014_pthread_scheduler_new(labcomm2014_default_memory));
+  prefix = labcomm2014_renaming_encoder_new(encoder,
+                                            labcomm2014_renaming_prefix,
+                                            "p.");
+  suffix = labcomm2014_renaming_encoder_new(prefix,
+                                            labcomm2014_renaming_suffix,
+                                            ".s");
+  EXPECT({ 0x01, 0x0c, 0x0b, 
+           'L', 'a', 'b', 'C', 'o', 'm', 'm', '2','0', '1', '4' });
+
+  labcomm2014_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
+  /* Register twice to make sure that only one registration gets encoded */
+  labcomm2014_encoder_register_generated_encoding_V(encoder);
+  labcomm2014_encoder_register_generated_encoding_V(encoder);
+  EXPECT({ 0x02, 0x06, VARIABLE(0), 0x01, 'V', 0x02, 0x11, 0x00,
+           0x04, 0x08, VARIABLE(1), 0x03, 'v', '_', 't', 0x02, 0x11, 0x00,
+           0x04, 0x05, VARIABLE(2), 0x01, 'V', 0x01, VARIABLE(1),
+           0x05, 0x02, VARIABLE(0), VARIABLE(2) });
+
+  labcomm2014_encoder_ioctl(prefix, IOCTL_WRITER_RESET);
+  labcomm2014_encoder_register_generated_encoding_V(prefix);
+  labcomm2014_encoder_register_generated_encoding_V(prefix);
+  EXPECT({ 0x02, 0x08, VARIABLE(3), 0x03, 'p', '.', 'V', 0x02, 0x11, 0x00,
+           0x04, 0x0a, VARIABLE(4), 0x05, 'p', '.', 'v', '_', 't', 0x02, 0x11, 0x00,
+           0x04, 0x07, VARIABLE(5), 0x03, 'p', '.', 'V', 0x01, VARIABLE(1) /* WEIRD*/,
+           0x05, 0x02, VARIABLE(3), VARIABLE(5) });
+
+  labcomm2014_encoder_ioctl(suffix, IOCTL_WRITER_RESET);
+  labcomm2014_encoder_register_generated_encoding_V(suffix);
+  labcomm2014_encoder_register_generated_encoding_V(suffix);
+  EXPECT({ 0x02, 0x0a, VARIABLE(6), 0x05, 'p', '.', 'V', '.', 's', 0x02, 0x11, 0x00,
+           0x04, 0x0c, VARIABLE(7), 0x07, 'p', '.', 'v', '_', 't', '.', 's', 0x02, 0x11, 0x00,
+           0x04, 0x09, VARIABLE(8), 0x05, 'p', '.', 'V', '.', 's', 0x01, VARIABLE(1) /* WEIRD */,
+           0x05, 0x02, VARIABLE(6), VARIABLE(22) });
+
+
+  labcomm2014_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
+  /* Register twice to make sure that only one registration gets encoded */
+  labcomm2014_encoder_sample_ref_register(encoder, 
+                                          labcomm2014_signature_generated_encoding_V);
+  labcomm2014_encoder_sample_ref_register(encoder, 
+                                          labcomm2014_signature_generated_encoding_V);
+  EXPECT({0x03, 0x06, VARIABLE(9), 0x01, 'V', 0x02, 0x11, 0x00});
+
+  labcomm2014_encoder_ioctl(prefix, IOCTL_WRITER_RESET);
+  /* Register twice to make sure that only one registration gets encoded */
+  labcomm2014_encoder_sample_ref_register(prefix, 
+                                          labcomm2014_signature_generated_encoding_V);
+  labcomm2014_encoder_sample_ref_register(prefix, 
+                                          labcomm2014_signature_generated_encoding_V);
+  EXPECT({0x03, 0x08, VARIABLE(10), 0x03, 'p', '.', 'V', 0x02, 0x11, 0x00});
+
+  labcomm2014_encoder_ioctl(suffix, IOCTL_WRITER_RESET);
+  /* Register twice to make sure that only one registration gets encoded */
+  labcomm2014_encoder_sample_ref_register(suffix, 
+                                          labcomm2014_signature_generated_encoding_V);
+  labcomm2014_encoder_sample_ref_register(suffix, 
+                                          labcomm2014_signature_generated_encoding_V);
+  EXPECT({0x03, 0x0a, VARIABLE(11), 0x05, 'p', '.', 'V', '.', 's', 0x02, 0x11, 0x00});
+
+
+  labcomm2014_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
+  labcomm2014_encode_generated_encoding_V(encoder);
+  EXPECT({VARIABLE(0), 0x00 });
+
+  labcomm2014_encoder_ioctl(prefix, IOCTL_WRITER_RESET);
+  labcomm2014_encode_generated_encoding_V(prefix);
+  EXPECT({VARIABLE(3), 0x00 });
+
+  labcomm2014_encoder_ioctl(suffix, IOCTL_WRITER_RESET);
+  labcomm2014_encode_generated_encoding_V(suffix);
+  EXPECT({VARIABLE(6), 0x00 });
+
+  return 0;
+}
+
-- 
GitLab