gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet-go-plugins] 02/04: example-c: Initial revision.


From: gnunet
Subject: [gnunet-go-plugins] 02/04: example-c: Initial revision.
Date: Sun, 30 Oct 2022 18:22:42 +0100

This is an automated email from the git hooks/post-receive script.

bernd-fix pushed a commit to branch master
in repository gnunet-go-plugins.

commit 2894297101501604134d91ade6765357d73687e2
Author: Bernd Fix <brf@hoi-polloi.org>
AuthorDate: Sun Oct 30 18:08:48 2022 +0100

    example-c: Initial revision.
---
 example-c/Makefile       |  30 ++++++++
 example-c/gui.htpl       | 111 +++++++++++++++++++++++++++++
 example-c/main.go        | 179 +++++++++++++++++++++++++++++++++++++++++++++++
 example-c/plugin.c       | 155 ++++++++++++++++++++++++++++++++++++++++
 example-c/plugin.h       |  44 ++++++++++++
 example-c/plugin_test.go | 109 +++++++++++++++++++++++++++++
 6 files changed, 628 insertions(+)

diff --git a/example-c/Makefile b/example-c/Makefile
new file mode 100644
index 0000000..d954b84
--- /dev/null
+++ b/example-c/Makefile
@@ -0,0 +1,30 @@
+# This file is part of gnunet-go-plugins, a collection of plugins for
+# the GNUnet-implementation in Golang (gnunet.go). Plugins are used to
+# implement type-specific processing of resource records (e.g. GUI).
+# Copyright (C) 2022 by the authors:
+#
+# * Bernd Fix <brf@hoi-polloi.org>  >Y<
+#
+# gnunet-go-plugins is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License,
+# or (at your option) any later version.
+#
+# gnunet-go 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
+# Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# SPDX-License-Identifier: AGPL3.0-or-later
+
+
+all: ${GOPATH}/bin/plugin_example_c.so
+
+clean: ${GOPATH}/bin/plugin_example_c.so
+       rm -f $^
+
+${GOPATH}/bin/plugin_example_c.so: main.go gui.htpl plugin.h plugin.c
+       go build -buildmode=plugin -trimpath -gcflags="-N -l" -o $@ ./...
diff --git a/example-c/gui.htpl b/example-c/gui.htpl
new file mode 100644
index 0000000..8317a72
--- /dev/null
+++ b/example-c/gui.htpl
@@ -0,0 +1,111 @@
+{{define "new_myrecords"}}
+    <!-- DEBUG: show template parameters -->
+    <div>
+        <h3>Template data:</h3>
+       <p>Ref = {{.Ref}}</p>
+           <p>Action = {{.Action}}</p>
+           <p>Button = {{.Button}}</p>
+        <p>Names: {{range $i,$v := .Names}}'{{$v}}',{{end}}</p>
+        <p>RRSpecs:</p>
+        <ul>
+            {{range $i,$s := .RRspecs}}
+            <li>Type = {{$s.Type}}, Flags = {{$s.Flags}}</li>
+            {{end}}
+        </ul>
+        <p>Params:</p>
+        <ul>
+        {{range $k,$v := .Params}}
+            <li>'{{$k}}' = '{{$v}}'</li>
+        {{end}}
+        </ul>
+    </div>
+
+    {{$data := .}}
+    <div>
+        <h3>Creating a new custom resource record for label "{{index .Params 
"label"}}":</h3>
+        <div class="tabset">
+            {{range $i, $type := .RRspecs}}
+            <input type="radio" name="tabset" id="tab{{$i}}" 
aria-controls="tab{{$i}}" {{if eq $i 0}}checked{{end}}>
+            <label for="tab{{$i}}">{{rrtype $type.Type}}</label>
+            {{end}}
+            <div class="tab-panels">
+                {{range $i, $spec := .RRspecs}}
+                <section id="tab{{$i}}" class="tab-panel">
+                    {{$t := rrtype $spec.Type}}
+                    {{$pf := setspecs $data.Params $spec}}
+                    {{if eq $t "MYRECTYPE1"}}{{template "MYRECTYPE1" 
$data}}{{end}}
+                    {{if eq $t "MYRECTYPE2"}}{{template "MYRECTYPE2" 
$data}}{{end}}
+                </section>
+                {{end}}
+            </div>
+        </div>
+        <a href="/"><button>Leave</button></a>
+    </div>
+{{end}}
+
+{{define "edit_myrecords"}}
+    <!-- DEBUG: show template parameters -->
+    <div>
+        <h3>Template data:</h3>
+       <p>Ref = {{.Ref}}</p>
+           <p>Action = {{.Action}}</p>
+           <p>Button = {{.Button}}</p>
+        <p>Names: {{range $i,$v := .Names}}'{{$v}}',{{end}}</p>
+        <ul>
+        {{range $k,$v := .Params}}
+            <li>'{{$k}}' = '{{$v}}'</li>
+        {{end}}
+        </ul>
+    </div>
+
+    <div>
+        <h3>Edit a resource record for label {{index .Params "label"}}:</h3>
+        <p><small>(Created: {{index .Params "created"}}, Last edited: {{index 
.Params "modified"}})</small></p>
+        {{$t := rritype (index .Params "type")}}
+        {{if eq $t "MYRECTYPE1"}}{{template "MYRECTYPE1" .}}{{end}}
+        {{if eq $t "MYRECTYPE2"}}{{template "MYRECTYPE2" .}}{{end}}
+    </div>
+    <a href="/"><button>Leave</button></a>
+{{end}}
+
+{{define "MYRECTYPE1"}}
+    <h3>RECTYPE1</h3>
+    <form action="/action/{{.Action}}/rr/{{.Ref}}" {{if eq .Action 
"upd"}}method="post"{{end}}>
+        <input type="hidden" name="type" value="{{index .Params "type"}}">
+        <table>
+            <tr>
+                <td align="right"><b>Attribute1:</b></td>
+                <td>
+                    <input type="text" name="myrec1_text"
+                        maxlength="63" size="63"
+                        autofocus required
+                        value="{{index .Params "myrec1_text"}}"
+                    >
+                </td>
+            </tr>
+            {{template "RRCommon" .}}
+            <tr><td/><td><button id="submit">{{.Button}} 
record</button></td></tr>
+        </table>
+    </form>
+{{end}}
+
+{{define "MYRECTYPE2"}}
+    <h3>RECTYPE2</h3>
+    <form action="/action/{{.Action}}/rr/{{.Ref}}" {{if eq .Action 
"upd"}}method="post"{{end}}>
+        <input type="hidden" name="type" value="{{index .Params "type"}}">
+        <table>
+            <tr>
+                <td align="right"><b>Attribute1:</b></td>
+                <td>
+                    <input type="text" name="myrec2_text"
+                        maxlength="63" size="63"
+                        autofocus required
+                        value="{{index .Params "myrec2_text"}}"
+                    >
+                </td>
+            </tr>
+            {{template "RRCommon" .}}
+            <tr><td/><td><button id="submit">{{.Button}} 
record</button></td></tr>
+        </table>
+    </form>
+{{end}}
diff --git a/example-c/main.go b/example-c/main.go
new file mode 100644
index 0000000..dcec5a3
--- /dev/null
+++ b/example-c/main.go
@@ -0,0 +1,179 @@
+// This file is part of gnunet-go-plugins, a collection of plugins for
+// the GNUnet-implementation in Golang (gnunet.go). Plugins are used to
+// implement type-specific processing of resource records (e.g. GUI).
+// Copyright (C) 2022 by the authors:
+//
+// * Bernd Fix <brf@hoi-polloi.org>  >Y<
+//
+// gnunet-go-plugins is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// gnunet-go 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
+// Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+// SPDX-License-Identifier: AGPL3.0-or-later
+
+package main
+
+// #cgo CFLAGS: -g -Wall
+// #include "plugin.h"
+import "C"
+
+import (
+       "bytes"
+       _ "embed"
+       "strings"
+       "unsafe"
+)
+
+//======================================================================
+//   C U S T O M I Z A T I O N
+//======================================================================
+
+//----------------------------------------------------------------------
+// Interface implementation
+//----------------------------------------------------------------------
+
+// Name returns the plugin name (sub-system name)
+//
+// TODO: customize name of the plugin
+func (p *CustomPlugin) Name() string {
+       return "Example-C"
+}
+
+// TemplateNames returns the names of the new / edit template
+// TODO: customize template names (see gui.htpl)
+func (p *CustomPlugin) TemplateNames() (string, string) {
+       return "new_myrecords", "edit_myrecords"
+}
+
+//======================================================================
+// No need to customize code beond this point...
+//======================================================================
+
+// Plugin is the instance of a custom implementation accessed by the
+// gnunet-go framework
+var Plugin = NewCustomPlugin()
+
+// ExamplePlugin is an example plugin for custom records that implements
+// the zonemaster.Plugin interface.
+type CustomPlugin struct {
+       num int // number of managed resource record types
+}
+
+// NewCustomPlugin creates an initialized plugin instance
+func NewCustomPlugin() CustomPlugin {
+       return CustomPlugin{}
+}
+
+//go:embed gui.htpl
+var tpl []byte
+
+// Template returns the new / edit template for resource record types
+// handled by the plugin.
+func (p *CustomPlugin) Template() string {
+       return string(tpl)
+}
+
+// CanHandle returns a list of resource record types that are handled
+// by the plugin. Calls the a C function from 'plugin.c'
+func (p *CustomPlugin) CanHandle() (list []uint32) {
+       var out *C.uint32_t
+       num := C.can_handle(out)
+       p.num = int(num)
+       out = (*C.uint32_t)(C.malloc(C.ulong(p.num * 4)))
+       defer C.free(unsafe.Pointer(out))
+       C.can_handle(out)
+       clist := unsafe.Slice(out, p.num)
+       for _, v := range clist {
+               list = append(list, uint32(v))
+       }
+       return
+}
+
+// Compute a set of record specs allowed under a label with existing records.
+// Calls a C-function from 'plugin.c'
+func (p *CustomPlugin) Compatible(label string, rrSpecs [][2]uint32) (rrOut 
[][2]uint32) {
+       // the result array can't be larger than the number of types managed
+       out := (*C.uint32_t)(C.malloc(C.ulong(p.num * 8)))
+       defer C.free(unsafe.Pointer(out))
+       // get label
+       labelC := C.CString(label)
+       defer C.free(unsafe.Pointer(labelC))
+       // get incoming RR specs
+       inNum := len(rrSpecs)
+       in := (*C.uint32_t)(C.malloc(C.ulong(inNum * 8)))
+       defer C.free(unsafe.Pointer(in))
+
+       // call plugin and assemble result
+       outNum := C.compatible(labelC, in, out)
+       clist := unsafe.Slice(out, 2*outNum)
+       for i := 0; i < p.num; i++ {
+               rrt := uint32(clist[2*i])
+               rrf := uint32(clist[2*i+1])
+               rrOut = append(rrOut, [2]uint32{rrt, rrf})
+       }
+       return
+}
+
+// Prefix returns the prefix for record attributes in map
+// Calls a C-function from 'plugin.c'
+func (p *CustomPlugin) Prefix(t uint32) string {
+       cs := C.prefix(C.uint32_t(t))
+       return C.GoString(cs)
+}
+
+// Value returns a human-readable description of RR data
+// Calls a C-function from 'plugin.c'
+func (p *CustomPlugin) Value(t uint32, rr []byte) (string, error) {
+       cs := C.value(C.uint32_t(t), (*C.char)(unsafe.Pointer(&rr[0])))
+       return C.GoString(cs), nil
+}
+
+// ToMap converts resource record data into GUI template variables
+// Calls a C-function from 'plugin.c'
+func (p *CustomPlugin) ToMap(t uint32, rr []byte) (params map[string]string, 
err error) {
+       var res *C.char
+       num := C.to_map(C.uint32_t(t), (*C.char)(unsafe.Pointer(&rr[0])), &res)
+       defer C.free(unsafe.Pointer(res))
+       b := make([]byte, num)
+       slice := unsafe.Slice(res, num)
+       for i := range b {
+               b[i] = byte(slice[i])
+       }
+       list := strings.Split(string(b), "\000")
+       params = make(map[string]string)
+       for i := 0; i < len(list)/2; i++ {
+               params[list[2*i]] = list[2*i+1]
+       }
+       return
+}
+
+// FromMap converts a GUI template variables into resource record data
+// Calls a C-function from 'plugin.c'
+func (p *CustomPlugin) FromMap(t uint32, vars map[string]string) ([]byte, 
error) {
+       buf := new(bytes.Buffer)
+       for k, v := range vars {
+               buf.WriteString(k)
+               buf.WriteByte(0)
+               buf.WriteString(v)
+               buf.WriteByte(0)
+       }
+       buf.WriteByte(0)
+       params := buf.Bytes()
+       var out *C.char
+       num := C.from_map(C.uint32_t(t), (*C.char)(unsafe.Pointer(&params[0])), 
&out)
+       b := make([]byte, num)
+       slice := unsafe.Slice(out, num)
+       for i := range b {
+               b[i] = byte(slice[i])
+       }
+       return b, nil
+}
diff --git a/example-c/plugin.c b/example-c/plugin.c
new file mode 100644
index 0000000..9ab8198
--- /dev/null
+++ b/example-c/plugin.c
@@ -0,0 +1,155 @@
+// This file is part of gnunet-go-plugins, a collection of plugins for
+// the GNUnet-implementation in Golang (gnunet.go). Plugins are used to
+// implement type-specific processing of resource records (e.g. GUI).
+// Copyright (C) 2022 by the authors:
+//
+// * Bernd Fix <brf@hoi-polloi.org>  >Y<
+//
+// gnunet-go-plugins is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// gnunet-go 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
+// Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+// SPDX-License-Identifier: AGPL3.0-or-later
+
+#include "plugin.h"
+
+#define RECTYPE1 90666
+#define RECTYPE2 90667
+
+const char* rectype1 = "rectype1";
+const char* rectype2 = "rectype2";
+
+typedef struct {
+    uint16_t text_len;
+    // followed by string (NOT \0 terminated!)
+} REC1;
+
+typedef struct {
+    uint32_t var1;
+    uint16_t var2;
+} REC2;
+
+
+int can_handle(uint32_t* out) {
+    if (out != NULL) {
+        // TODO: customize record type list
+        out[0] = RECTYPE1;
+        out[1] = RECTYPE2;
+    }
+    return 2;
+}
+
+int compatible(const char* label, uint32_t* in, uint32_t* out) {
+    // simple case: no restrictions (all handled types allowed, no enforced 
flags)
+    out[0] = RECTYPE1;  // type #1
+    out[1] = 0;         // flags #1
+    out[2] = RECTYPE2;  // type #2
+    out[3] = 0;         // flags #2
+    return 2;
+}
+
+const char* prefix(uint32_t rr) {
+    // TODO: customize record type list
+    if (rr == RECTYPE1)
+        return rectype1;
+    if (rr == RECTYPE2)
+        return rectype2;
+    return NULL;
+}
+
+char* value(uint32_t rrType, char* rrData) {
+    char* out = (char*)malloc(1024);
+    // TODO: customize record type list
+    if (rrType == RECTYPE1) {
+        REC1* rec = (REC1*)rrData;
+        if (rec->text_len == 0) {
+            out[0] = 0;
+        } else {
+            strcpy(out, rrData+2);
+        }
+    } else if (rrType == RECTYPE2) {
+        REC2* rec = (REC2*)rrData;
+        sprintf(out, "var1=%d,<br>var2=%d", ntohl(rec->var1), 
ntohs(rec->var2));
+    }
+    return out;
+}
+
+int to_map(uint32_t rrType, char* rrData, char** res) {
+    *res = (char*)malloc(1024);
+    char* out = *res;
+    // TODO: customize record type list
+    if (rrType == RECTYPE1) {
+        REC1* rec = (REC1*)rrData;
+        const char* key = "rectype1_text";
+        strcpy(out, key);
+        out += strlen(key)+1;
+        if (rec->text_len == 0) {
+            *out = 0;
+            out++;
+        } else {
+            const char* value = rrData+2;
+            strncpy(out, value, rec->text_len);
+            out += strlen(value);
+        }
+    } else if (rrType == RECTYPE2) {
+        REC2* rec = (REC2*)rrData;
+        char* key = "rectype2_var1";
+        strcpy(out, key);
+        out += strlen(key)+1;
+        sprintf(out, "%d", ntohl(rec->var1));
+        out += strlen(out)+1;
+        key = "rectype2_var2";
+        strcpy(out, key);
+        out += strlen(key)+1;
+        sprintf(out, "%d", ntohs(rec->var2));
+        out += strlen(out)+1;
+    }
+    return out-*res;
+}
+
+int from_map(uint32_t rrType, char* params, char** rrData) {
+    *rrData = (char*)malloc(1024);
+    char* res = *rrData;
+    // TODO: customize record type list
+    if (rrType == RECTYPE1) {
+        printf("*** key='%s'\n", params);
+        if (strcmp(params, "rectype1_text") == 0) {
+            int n = strlen(params);
+            char* value = params+n+1;
+            n = strlen(value);
+            *(uint16_t*)res = htons(n);
+            strcpy(res+2, value);
+            return n+3;
+        }
+    } else if (rrType == RECTYPE2) {
+        char* ptr = params;
+        REC2* rec = (REC2*)(res);
+        int val;
+        for (int i = 0; ; i++) {
+            int n = strlen(ptr);
+            if (n == 0)
+                break;
+            char* value = ptr+n+1;
+            n = strlen(value);
+            if (strcmp(ptr, "rectype2_var1") == 0) {
+                sscanf(value, "%d", &val);
+                rec->var1 = htonl(val);
+            } else if (strcmp(ptr, "rectype2_var2") == 0) {
+                sscanf(value, "%d", &val);
+                rec->var2 = htons((uint16_t)(val));
+            }
+            ptr = value+n+1;
+        }
+        return 6;
+    }
+    return 0;
+}
diff --git a/example-c/plugin.h b/example-c/plugin.h
new file mode 100644
index 0000000..f73e43b
--- /dev/null
+++ b/example-c/plugin.h
@@ -0,0 +1,44 @@
+// This file is part of gnunet-go-plugins, a collection of plugins for
+// the GNUnet-implementation in Golang (gnunet.go). Plugins are used to
+// implement type-specific processing of resource records (e.g. GUI).
+// Copyright (C) 2022 by the authors:
+//
+// * Bernd Fix <brf@hoi-polloi.org>  >Y<
+//
+// gnunet-go-plugins is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// gnunet-go 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
+// Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+// SPDX-License-Identifier: AGPL3.0-or-later
+
+#ifndef _PLUGIN_H
+#define _PLUGIN_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+int can_handle(uint32_t*);
+
+int compatible(const char* label, uint32_t* in, uint32_t* out);
+
+const char* prefix(uint32_t rr);
+
+char* value(uint32_t rrType, char* rrData);
+
+int to_map(uint32_t rrType, char* rrData, char** params);
+
+int from_map(uint32_t rrType, char* params, char** rrData);
+
+#endif
diff --git a/example-c/plugin_test.go b/example-c/plugin_test.go
new file mode 100644
index 0000000..f0962e2
--- /dev/null
+++ b/example-c/plugin_test.go
@@ -0,0 +1,109 @@
+// This file is part of gnunet-go-plugins, a collection of plugins for
+// the GNUnet-implementation in Golang (gnunet.go). Plugins are used to
+// implement type-specific processing of resource records (e.g. GUI).
+// Copyright (C) 2022 by the authors:
+//
+// * Bernd Fix <brf@hoi-polloi.org>  >Y<
+//
+// gnunet-go-plugins is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// gnunet-go 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
+// Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+// SPDX-License-Identifier: AGPL3.0-or-later
+
+package main
+
+import (
+       "bytes"
+       "encoding/hex"
+       "testing"
+)
+
+func TestPluginCanHandle(t *testing.T) {
+       list := Plugin.CanHandle()
+       if len(list) == 0 {
+               t.Fatal("no type list received from plugin")
+       }
+       for _, rr := range list {
+               t.Logf("Can handle %d\n", rr)
+       }
+}
+
+func TestPluginCompatible(t *testing.T) {
+       in := make([][2]uint32, 0)
+       out := Plugin.Compatible("@", in)
+       for _, s := range out {
+               t.Logf("Compatible: type=%d, flags=%d\n", s[0], s[1])
+       }
+}
+
+func TestPluginPrefix(t *testing.T) {
+       t.Logf("Prefix: '%s' (%d)\n", Plugin.Prefix(90666), 90666)
+       t.Logf("Prefix: '%s' (%d)\n", Plugin.Prefix(90667), 90667)
+}
+
+var (
+       rec1 = []byte{0x00, 0x03, 0x66, 0x6f, 0x6f, 0x00}
+       rec2 = []byte{0x00, 0x00, 0x00, 0x23, 0x00, 0x42}
+)
+
+func TestPluginValue(t *testing.T) {
+       s1, err := Plugin.Value(90666, rec1)
+       if err != nil {
+               t.Fatal(err)
+       }
+       t.Logf("rec1: text='%s'\n", s1)
+
+       s2, err := Plugin.Value(90667, rec2)
+       if err != nil {
+               t.Fatal(err)
+       }
+       t.Logf("rec2: '%s'\n", s2)
+}
+
+func TestPluginToMap(t *testing.T) {
+       params, err := Plugin.ToMap(90666, rec1)
+       if err != nil {
+               t.Fatal(err)
+       }
+       t.Logf("ToMap: rec1 -> %v\n", params)
+
+       if params, err = Plugin.ToMap(90667, rec2); err != nil {
+               t.Fatal(err)
+       }
+       t.Logf("ToMap: rec2 -> %v\n", params)
+}
+
+func TestPluginFromMap(t *testing.T) {
+       params := map[string]string{
+               "rectype1_text": "foo",
+       }
+       rr, err := Plugin.FromMap(90666, params)
+       if err != nil {
+               t.Fatal(err)
+       }
+       t.Logf("FromMap: rr=%s\n", hex.EncodeToString(rr))
+       if !bytes.Equal(rr, rec1) {
+               t.Fatal("FromMap for rectype1 failed")
+       }
+       params = map[string]string{
+               "rectype2_var1": "35",
+               "rectype2_var2": "66",
+       }
+       if rr, err = Plugin.FromMap(90667, params); err != nil {
+               t.Fatal(err)
+       }
+       t.Logf("FromMap: rr=%s\n", hex.EncodeToString(rr))
+       if !bytes.Equal(rr, rec2) {
+               t.Fatal("FromMap for rectype2 failed")
+       }
+}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]