Commit 196d679b authored by Peter Hutterer's avatar Peter Hutterer
Browse files

test: remove glib dependency



The few features from the glib test suite we used can be replaced with
assert and printf. This patch is a simple replacement for these two
    g_assert → assert
    g_test_message → printf

g_test_init is removed and so is g_test_bug_base. g_test_run replaced with a
simple return 0.
Signed-off-by: Peter Hutterer's avatarPeter Hutterer <peter.hutterer@who-t.net>
Acked-by: default avatarTiago Vignatti <tiago.vignatti@nokia.com>
Acked-by: Gaetan Nadon's avatarGaetan Nadon <memsize@videotron.ca>
parent 071a6ac4
......@@ -44,7 +44,6 @@ XORG_ENABLE_DEVEL_DOCS
XORG_WITH_XMLTO(0.0.20)
XORG_WITH_FOP
XORG_ENABLE_UNIT_TESTS
XORG_WITH_GLIB
XORG_LD_WRAP
m4_ifndef([XORG_FONT_MACROS_VERSION], [m4_fatal([must install fontutil 1.1 or later before running autoconf/autogen])])
......@@ -791,7 +790,6 @@ LIBXFONT="xfont >= 1.4.2"
LIBXI="xi >= 1.2.99.1"
LIBXTST="xtst >= 1.0.99.2"
LIBPCIACCESS="pciaccess >= 0.8.0"
LIBGLIB="glib-2.0 >= 2.16"
LIBUDEV="libudev >= 143"
LIBSELINUX="libselinux >= 2.0.86"
LIBDBUS="dbus-1 >= 1.0"
......
if ENABLE_UNIT_TESTS
if HAVE_GLIB
if HAVE_LD_WRAP
SUBDIRS= . xi2
noinst_PROGRAMS = xkb input xtest list
......@@ -7,9 +6,9 @@ check_LTLIBRARIES = libxservertest.la
TESTS=$(noinst_PROGRAMS)
AM_CFLAGS = $(DIX_CFLAGS) $(GLIB_CFLAGS) @XORG_CFLAGS@
AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@
INCLUDES = @XORG_INCS@
TEST_LDADD=libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS) $(GLIB_LIBS)
TEST_LDADD=libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS)
if SPECIAL_DTRACE_OBJECTS
TEST_LDADD += $(OS_LIB) $(DIX_LIB)
......@@ -38,7 +37,6 @@ libxservertest_la_LIBADD = \
@XORG_LIBS@
endif
endif
endif
CLEANFILES=libxservertest.c
......
This diff is collapsed.
......@@ -28,7 +28,7 @@
#include <X11/Xlib.h>
#include <list.h>
#include <string.h>
#include <glib.h>
#include <assert.h>
struct parent {
int a;
......@@ -56,10 +56,10 @@ test_list_init(void)
list_init(&parent.children);
/* test we haven't touched anything else. */
g_assert(parent.a == tmp.a);
g_assert(parent.b == tmp.b);
assert(parent.a == tmp.a);
assert(parent.b == tmp.b);
g_assert(list_is_empty(&parent.children));
assert(list_is_empty(&parent.children));
}
static void
......@@ -72,19 +72,19 @@ test_list_add(void)
list_init(&parent.children);
list_add(&child[0].node, &parent.children);
g_assert(!list_is_empty(&parent.children));
assert(!list_is_empty(&parent.children));
c = list_first_entry(&parent.children, struct child, node);
g_assert(memcmp(c, &child[0], sizeof(struct child)) == 0);
assert(memcmp(c, &child[0], sizeof(struct child)) == 0);
/* note: list_add prepends */
list_add(&child[1].node, &parent.children);
c = list_first_entry(&parent.children, struct child, node);
g_assert(memcmp(c, &child[1], sizeof(struct child)) == 0);
assert(memcmp(c, &child[1], sizeof(struct child)) == 0);
list_add(&child[2].node, &parent.children);
c = list_first_entry(&parent.children, struct child, node);
g_assert(memcmp(c, &child[2], sizeof(struct child)) == 0);
assert(memcmp(c, &child[2], sizeof(struct child)) == 0);
};
static void
......@@ -97,40 +97,40 @@ test_list_del(void)
list_init(&parent.children);
list_add(&child[0].node, &parent.children);
g_assert(!list_is_empty(&parent.children));
assert(!list_is_empty(&parent.children));
list_del(&parent.children);
g_assert(list_is_empty(&parent.children));
assert(list_is_empty(&parent.children));
list_add(&child[0].node, &parent.children);
list_del(&child[0].node);
g_assert(list_is_empty(&parent.children));
assert(list_is_empty(&parent.children));
list_add(&child[0].node, &parent.children);
list_add(&child[1].node, &parent.children);
c = list_first_entry(&parent.children, struct child, node);
g_assert(memcmp(c, &child[1], sizeof(struct child)) == 0);
assert(memcmp(c, &child[1], sizeof(struct child)) == 0);
/* delete first node */
list_del(&child[1].node);
g_assert(!list_is_empty(&parent.children));
g_assert(list_is_empty(&child[1].node));
assert(!list_is_empty(&parent.children));
assert(list_is_empty(&child[1].node));
c = list_first_entry(&parent.children, struct child, node);
g_assert(memcmp(c, &child[0], sizeof(struct child)) == 0);
assert(memcmp(c, &child[0], sizeof(struct child)) == 0);
/* delete last node */
list_add(&child[1].node, &parent.children);
list_del(&child[0].node);
c = list_first_entry(&parent.children, struct child, node);
g_assert(memcmp(c, &child[1], sizeof(struct child)) == 0);
assert(memcmp(c, &child[1], sizeof(struct child)) == 0);
/* delete list head */
list_add(&child[0].node, &parent.children);
list_del(&parent.children);
g_assert(list_is_empty(&parent.children));
g_assert(!list_is_empty(&child[1].node));
g_assert(!list_is_empty(&child[2].node));
assert(list_is_empty(&parent.children));
assert(!list_is_empty(&child[1].node));
assert(!list_is_empty(&child[2].node));
}
static void
......@@ -148,29 +148,26 @@ test_list_for_each(void)
list_add(&child[0].node, &parent.children);
list_for_each_entry(c, &parent.children, node) {
g_assert(memcmp(c, &child[i], sizeof(struct child)) == 0);
assert(memcmp(c, &child[i], sizeof(struct child)) == 0);
i++;
}
/* foreach on empty list */
list_del(&parent.children);
g_assert(list_is_empty(&parent.children));
assert(list_is_empty(&parent.children));
list_for_each_entry(c, &parent.children, node) {
g_assert(0); /* we must not get here */
assert(0); /* we must not get here */
}
}
int main(int argc, char** argv)
{
g_test_init(&argc, &argv,NULL);
g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
test_list_init();
test_list_add();
test_list_del();
test_list_for_each();
g_test_add_func("/list/init", test_list_init);
g_test_add_func("/list/add", test_list_add);
g_test_add_func("/list/del", test_list_del);
g_test_add_func("/list/for_each", test_list_for_each);
return g_test_run();
return 0;
}
if ENABLE_UNIT_TESTS
if HAVE_GLIB
if HAVE_LD_WRAP
noinst_PROGRAMS = \
protocol-xiqueryversion \
......@@ -15,9 +14,9 @@ noinst_PROGRAMS = \
TESTS=$(noinst_PROGRAMS)
AM_CFLAGS = $(DIX_CFLAGS) $(GLIB_CFLAGS) @XORG_CFLAGS@
AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@
INCLUDES = @XORG_INCS@
TEST_LDADD=../libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS) $(GLIB_LIBS)
TEST_LDADD=../libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS)
COMMON_SOURCES=protocol-common.h protocol-common.c
if SPECIAL_DTRACE_OBJECTS
......@@ -56,4 +55,3 @@ protocol_xipassivegrabdevice_SOURCES=$(COMMON_SOURCES) protocol-xipassivegrabdev
protocol_xiwarppointer_SOURCES=$(COMMON_SOURCES) protocol-xiwarppointer.c
endif
endif
endif
......@@ -29,7 +29,6 @@
#include "extinit.h" /* for XInputExtensionInit */
#include "exglobals.h"
#include "xkbsrv.h" /* for XkbInitPrivates */
#include <glib.h>
#include "protocol-common.h"
......@@ -134,7 +133,7 @@ void init_window(WindowPtr window, WindowPtr parent, int id)
}
window->parent = parent;
window->optional = calloc(1, sizeof(WindowOptRec));
g_assert(window->optional);
assert(window->optional);
}
extern DevPrivateKeyRec miPointerScreenKeyRec;
......@@ -171,7 +170,7 @@ void init_simple(void)
void __wrap_WriteToClient(ClientPtr client, int len, void *data)
{
g_assert(reply_handler != NULL);
assert(reply_handler != NULL);
(*reply_handler)(client, len, data, userdata);
}
......
......@@ -29,6 +29,7 @@
#include "windowstr.h"
#include "scrnintstr.h"
#include "exevents.h"
#include <assert.h>
#ifndef PROTOCOL_COMMON_H
#define PROTOCOL_COMMON_H
......@@ -38,11 +39,11 @@ extern int BadDevice;
/* Check default values in a reply */
#define reply_check_defaults(rep, len, type) \
{ \
g_assert((len) >= sz_x##type##Reply); \
g_assert((rep)->repType == X_Reply); \
g_assert((rep)->RepType == X_##type); \
g_assert((rep)->sequenceNumber == CLIENT_SEQUENCE); \
g_assert((rep)->length >= (sz_x##type##Reply - 32)/4); \
assert((len) >= sz_x##type##Reply); \
assert((rep)->repType == X_Reply); \
assert((rep)->RepType == X_##type); \
assert((rep)->sequenceNumber == CLIENT_SEQUENCE); \
assert((rep)->length >= (sz_x##type##Reply - 32)/4); \
}
/* initialise default values for request */
......
......@@ -25,7 +25,6 @@
#endif
#include <stdint.h>
#include <glib.h>
#include "inputstr.h"
#include "eventstr.h"
......@@ -33,7 +32,6 @@
#include "exevents.h"
#include <X11/extensions/XI2proto.h>
static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out,
BOOL swap)
{
......@@ -58,21 +56,21 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out,
}
g_assert(out->type == GenericEvent);
g_assert(out->extension == 0); /* IReqCode defaults to 0 */
g_assert(out->evtype == GetXI2Type((InternalEvent*)in));
g_assert(out->time == in->time);
g_assert(out->detail == in->detail.button);
g_assert(out->deviceid == in->deviceid);
g_assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(sizeof(in->valuators.mask))));
g_assert(out->flags == 0); /* FIXME: we don't set the flags yet */
assert(out->type == GenericEvent);
assert(out->extension == 0); /* IReqCode defaults to 0 */
assert(out->evtype == GetXI2Type((InternalEvent*)in));
assert(out->time == in->time);
assert(out->detail == in->detail.button);
assert(out->deviceid == in->deviceid);
assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(sizeof(in->valuators.mask))));
assert(out->flags == 0); /* FIXME: we don't set the flags yet */
ptr = (unsigned char*)&out[1];
bits_set = 0;
for (i = 0; out->valuators_len && i < sizeof(in->valuators.mask) * 8; i++)
{
g_assert (XIMaskIsSet(in->valuators.mask, i) == XIMaskIsSet(ptr, i));
assert (XIMaskIsSet(in->valuators.mask, i) == XIMaskIsSet(ptr, i));
if (XIMaskIsSet(in->valuators.mask, i))
bits_set++;
}
......@@ -81,13 +79,13 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out,
* set. Each bit set represents 2 8-byte values, hence the
* 'bits_set * 4' */
len = out->valuators_len + bits_set * 4;
g_assert(out->length == len);
assert(out->length == len);
nvals = 0;
for (i = 0; out->valuators_len && i < MAX_VALUATORS; i++)
{
g_assert (XIMaskIsSet(in->valuators.mask, i) == XIMaskIsSet(ptr, i));
assert (XIMaskIsSet(in->valuators.mask, i) == XIMaskIsSet(ptr, i));
if (XIMaskIsSet(in->valuators.mask, i))
{
FP3232 vi, vo;
......@@ -106,8 +104,8 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out,
swapl(&vo.frac, n);
}
g_assert(vi.integral == vo.integral);
g_assert(vi.frac == vo.frac);
assert(vi.integral == vo.integral);
assert(vi.frac == vo.frac);
raw_value = value + bits_set;
......@@ -123,8 +121,8 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out,
swapl(&vo.frac, n);
}
g_assert(vi.integral == vo.integral);
g_assert(vi.frac == vo.frac);
assert(vi.integral == vo.integral);
assert(vi.frac == vo.frac);
nvals++;
}
......@@ -137,7 +135,7 @@ static void test_XIRawEvent(RawDeviceEvent *in)
int rc;
rc = EventToXI2((InternalEvent*)in, (xEvent**)&out);
g_assert(rc == Success);
assert(rc == Success);
test_values_XIRawEvent(in, out, FALSE);
......@@ -158,24 +156,24 @@ static void test_convert_XIFocusEvent(void)
in.header = ET_Internal;
in.type = ET_Enter;
rc = EventToXI2((InternalEvent*)&in, &out);
g_assert(rc == Success);
g_assert(out == NULL);
assert(rc == Success);
assert(out == NULL);
in.header = ET_Internal;
in.type = ET_FocusIn;
rc = EventToXI2((InternalEvent*)&in, &out);
g_assert(rc == Success);
g_assert(out == NULL);
assert(rc == Success);
assert(out == NULL);
in.header = ET_Internal;
in.type = ET_FocusOut;
rc = EventToXI2((InternalEvent*)&in, &out);
g_assert(rc == BadImplementation);
assert(rc == BadImplementation);
in.header = ET_Internal;
in.type = ET_Leave;
rc = EventToXI2((InternalEvent*)&in, &out);
g_assert(rc == BadImplementation);
assert(rc == BadImplementation);
}
......@@ -186,7 +184,7 @@ static void test_convert_XIRawEvent(void)
memset(&in, 0, sizeof(in));
g_test_message("Testing all event types");
printf("Testing all event types\n");
in.header = ET_Internal;
in.type = ET_RawMotion;
test_XIRawEvent(&in);
......@@ -207,7 +205,7 @@ static void test_convert_XIRawEvent(void)
in.type = ET_RawButtonRelease;
test_XIRawEvent(&in);
g_test_message("Testing details and other fields");
printf("Testing details and other fields\n");
in.detail.button = 1L;
test_XIRawEvent(&in);
in.detail.button = 1L << 8;
......@@ -239,7 +237,7 @@ static void test_convert_XIRawEvent(void)
in.deviceid = ~0 & 0xFF;
test_XIRawEvent(&in);
g_test_message("Testing valuator masks");
printf("Testing valuator masks\n");
for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
{
XISetMask(in.valuators.mask, i);
......@@ -301,14 +299,14 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
swapl(&out->flags, n);
}
g_assert(out->extension == 0); /* IReqCode defaults to 0 */
g_assert(out->evtype == GetXI2Type((InternalEvent*)in));
g_assert(out->time == in->time);
g_assert(out->detail == in->detail.button);
g_assert(out->length >= 12);
assert(out->extension == 0); /* IReqCode defaults to 0 */
assert(out->evtype == GetXI2Type((InternalEvent*)in));
assert(out->time == in->time);
assert(out->detail == in->detail.button);
assert(out->length >= 12);
g_assert(out->deviceid == in->deviceid);
g_assert(out->sourceid == in->sourceid);
assert(out->deviceid == in->deviceid);
assert(out->sourceid == in->sourceid);
switch (in->type) {
case ET_KeyPress:
......@@ -318,41 +316,41 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
flagmask = 0;
break;
}
g_assert((out->flags & ~flagmask) == 0);
assert((out->flags & ~flagmask) == 0);
g_assert(out->root == in->root);
g_assert(out->event == None); /* set in FixUpEventFromWindow */
g_assert(out->child == None); /* set in FixUpEventFromWindow */
assert(out->root == in->root);
assert(out->event == None); /* set in FixUpEventFromWindow */
assert(out->child == None); /* set in FixUpEventFromWindow */
g_assert(out->mods.base_mods == in->mods.base);
g_assert(out->mods.latched_mods == in->mods.latched);
g_assert(out->mods.locked_mods == in->mods.locked);
g_assert(out->mods.effective_mods == in->mods.effective);
assert(out->mods.base_mods == in->mods.base);
assert(out->mods.latched_mods == in->mods.latched);
assert(out->mods.locked_mods == in->mods.locked);
assert(out->mods.effective_mods == in->mods.effective);
g_assert(out->group.base_group == in->group.base);
g_assert(out->group.latched_group == in->group.latched);
g_assert(out->group.locked_group == in->group.locked);
g_assert(out->group.effective_group == in->group.effective);
assert(out->group.base_group == in->group.base);
assert(out->group.latched_group == in->group.latched);
assert(out->group.locked_group == in->group.locked);
assert(out->group.effective_group == in->group.effective);
g_assert(out->event_x == 0); /* set in FixUpEventFromWindow */
g_assert(out->event_y == 0); /* set in FixUpEventFromWindow */
assert(out->event_x == 0); /* set in FixUpEventFromWindow */
assert(out->event_y == 0); /* set in FixUpEventFromWindow */
g_assert(out->root_x == FP1616(in->root_x, in->root_x_frac));
g_assert(out->root_y == FP1616(in->root_y, in->root_y_frac));
assert(out->root_x == FP1616(in->root_x, in->root_x_frac));
assert(out->root_y == FP1616(in->root_y, in->root_y_frac));
buttons = 0;
for (i = 0; i < bits_to_bytes(sizeof(in->buttons)); i++)
{
if (XIMaskIsSet(in->buttons, i))
{
g_assert(out->buttons_len >= bytes_to_int32(bits_to_bytes(i)));
assert(out->buttons_len >= bytes_to_int32(bits_to_bytes(i)));
buttons++;
}
}
ptr = (unsigned char*)&out[1];
for (i = 0; i < sizeof(in->buttons) * 8; i++)
g_assert(XIMaskIsSet(in->buttons, i) == XIMaskIsSet(ptr, i));
assert(XIMaskIsSet(in->buttons, i) == XIMaskIsSet(ptr, i));
valuators = 0;
......@@ -360,7 +358,7 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
if (XIMaskIsSet(in->valuators.mask, i))
valuators++;
g_assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(valuators)));
assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(valuators)));
ptr += out->buttons_len * 4;
values = (FP3232*)(ptr + out->valuators_len * 4);
......@@ -368,11 +366,11 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
i < (out->valuators_len * 4) * 8; i++)
{
if (i > sizeof(in->valuators.mask) * 8)
g_assert(!XIMaskIsSet(ptr, i));
assert(!XIMaskIsSet(ptr, i));
else if (i > out->valuators_len * 4 * 8)
g_assert(!XIMaskIsSet(in->valuators.mask, i));
assert(!XIMaskIsSet(in->valuators.mask, i));
else {
g_assert(XIMaskIsSet(in->valuators.mask, i) ==
assert(XIMaskIsSet(in->valuators.mask, i) ==
XIMaskIsSet(ptr, i));
if (XIMaskIsSet(ptr, i))
......@@ -392,8 +390,8 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
}
g_assert(vi.integral == vo.integral);
g_assert(vi.frac == vo.frac);
assert(vi.integral == vo.integral);
assert(vi.frac == vo.frac);
values++;
}
}
......@@ -406,7 +404,7 @@ static void test_XIDeviceEvent(DeviceEvent *in)
int rc;
rc = EventToXI2((InternalEvent*)in, (xEvent**)&out);
g_assert(rc == Success);
assert(rc == Success);
test_values_XIDeviceEvent(in, out, FALSE);
......@@ -425,7 +423,7 @@ static void test_convert_XIDeviceEvent(void)
memset(&in, 0, sizeof(in));
g_test_message("Testing simple field values");
printf("Testing simple field values\n");
in.header = ET_Internal;
in.type = ET_Motion;
in.length = sizeof(DeviceEvent);
......@@ -449,7 +447,7 @@ static void test_convert_XIDeviceEvent(void)
test_XIDeviceEvent(&in);
g_test_message("Testing field ranges");
printf("Testing field ranges\n");
/* 32 bit */
in.detail.button = 1L;
test_XIDeviceEvent(&in);
......@@ -597,7 +595,7 @@ static void test_convert_XIDeviceEvent(void)
in.mods.effective = ~0 & 0xFF;
test_XIDeviceEvent(&in);
g_test_message("Testing button masks");
printf("Testing button masks\n");
for (i = 0; i < sizeof(in.buttons) * 8; i++)
{
XISetMask(in.buttons, i);
......@@ -611,7 +609,7 @@ static void test_convert_XIDeviceEvent(void)
test_XIDeviceEvent(&in);
}
g_test_message("Testing valuator masks");
printf("Testing valuator masks\n");
for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
{
XISetMask(in.valuators.mask, i);
......@@ -656,12 +654,12 @@ static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
swaps(&out->num_classes, n);
}
g_assert(out->type == GenericEvent);
g_assert(out->extension == 0); /* IReqCode defaults to 0 */
g_assert(out->evtype == GetXI2Type((InternalEvent*)in));
g_assert(out->time == in->time);
g_assert(out->deviceid == in->deviceid);
g_assert(out->sourceid == in->sourceid);
assert(out->type == GenericEvent);
assert(out->extension == 0); /* IReqCode defaults to 0 */
assert(out->evtype == GetXI2Type((InternalEvent*)in));
assert(out->time == in->time);
assert(out->deviceid == in->deviceid);
assert(out->sourceid == in->sourceid);
ptr = (unsigned char*)&out[1];
for (i = 0; i < out->num_classes; i++)
......@@ -689,11 +687,11 @@ static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
swaps(&b->num_buttons, n);
}
g_assert(b->length ==
assert(b->length ==
bytes_to_int32(sizeof(xXIButtonInfo)) +
bytes_to_int32(bits_to_bytes(b->num_buttons)) +
b->num_buttons);
g_assert(b->num_buttons == in->buttons.num_buttons);
assert(b->num_buttons == in->buttons.num_buttons);
names = (Atom*)((char*)&b[1] +
pad_to_int32(bits_to_bytes(b->num_buttons)));
......@@ -704,7 +702,7 @@ static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
char n;
swapl(&names[j], n);
}
g_assert(names[j] == in->buttons.names[j]);
assert(names[j] == in->buttons.names[j]);
}
}
break;
......@@ -719,10 +717,10 @@ static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
swaps(&k->num_keycodes, n);
}
g_assert(k->length ==
assert(k->length ==
bytes_to_int32(sizeof(xXIKeyInfo)) +
k->num_keycodes);
g_assert(k->num_keycodes == in->keys.max_keycode -
assert(k->num_keycodes == in->keys.max_keycode -
in->