From e6258977665b5f8345bc9bdf6f03cd1a66c6a529 Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Date: Mon, 13 Mar 2023 12:17:28 +0100 Subject: [PATCH] Add CHAN_IGNORE_DUP to ignore duplicates --- src/emu/chan.c | 48 ++++++++++++++++++++++++++---------------------- src/emu/chan.h | 1 + test/unit/chan.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 69 insertions(+), 25 deletions(-) diff --git a/src/emu/chan.c b/src/emu/chan.c index 092ed9b..ed6d8bb 100644 --- a/src/emu/chan.c +++ b/src/emu/chan.c @@ -63,22 +63,6 @@ set_dirty(struct chan *chan) return 0; } -static int -check_duplicates(struct chan *chan, struct value *v) -{ - /* If duplicates are allowed just skip the check */ - if (chan->prop[CHAN_ALLOW_DUP]) - return 0; - - if (value_is_equal(&chan->last_value, v)) { - err("%s: same value as last_value %s", - chan->name, value_str(chan->last_value)); - return -1; - } - - return 0; -} - int chan_set(struct chan *chan, struct value value) { @@ -92,9 +76,19 @@ chan_set(struct chan *chan, struct value value) return -1; } - if (check_duplicates(chan, &value) != 0) { - err("%s: cannot set duplicated value", chan->name); - return -1; + /* If duplicates are allowed just skip the check */ + if (!chan->prop[CHAN_ALLOW_DUP]) { + if (value_is_equal(&chan->last_value, &value)) { + if (chan->prop[CHAN_IGNORE_DUP]) { + dbg("%s: value already set to %s", + chan->name, value_str(value)); + return 0; + } else { + err("%s: same value as last_value %s", + chan->name, value_str(chan->last_value)); + return -1; + } + } } dbg("%s: sets value to %s", chan->name, value_str(value)); @@ -127,9 +121,19 @@ chan_push(struct chan *chan, struct value value) return -1; } - if (check_duplicates(chan, &value) != 0) { - err("%s: cannot push a duplicated value", chan->name); - return -1; + /* If duplicates are allowed just skip the check */ + if (!chan->prop[CHAN_ALLOW_DUP]) { + if (value_is_equal(&chan->last_value, &value)) { + if (chan->prop[CHAN_IGNORE_DUP]) { + dbg("%s: value already set to %s", + chan->name, value_str(value)); + return 0; + } else { + err("%s: same value as last_value %s", + chan->name, value_str(chan->last_value)); + return -1; + } + } } struct chan_stack *stack = &chan->data.stack; diff --git a/src/emu/chan.h b/src/emu/chan.h index 1ef377e..7b6a63d 100644 --- a/src/emu/chan.h +++ b/src/emu/chan.h @@ -19,6 +19,7 @@ enum chan_type { enum chan_prop { CHAN_DIRTY_WRITE = 0, CHAN_ALLOW_DUP, + CHAN_IGNORE_DUP, CHAN_MAXPROP, }; diff --git a/test/unit/chan.c b/test/unit/chan.c index 1fbbe2a..8d10d30 100644 --- a/test/unit/chan.c +++ b/test/unit/chan.c @@ -41,6 +41,8 @@ test_dirty(void) if (chan_flush(&chan) != 0) die("chan_flush failed\n"); + + err("OK"); } static void @@ -72,10 +74,14 @@ test_single(void) if (!value_is_equal(&value, &one)) die("chan_read returned unexpected value\n"); + + err("OK"); } +/* Test that writting the same value to a channel raises an error, but not if we + * set the CHAN_ALLOW_DUP flag */ static void -test_duplicate(void) +test_allow_dup(void) { struct chan chan; chan_init(&chan, CHAN_SINGLE, "testchan"); @@ -90,12 +96,44 @@ test_duplicate(void) if (chan_set(&chan, value_int64(1)) == 0) die("chan_set didn't fail\n"); - /* Now enable duplicates */ + /* Allow duplicates */ chan_prop_set(&chan, CHAN_ALLOW_DUP, 1); /* Then it should allow writting the same value */ if (chan_set(&chan, value_int64(1)) != 0) die("chan_set failed\n"); + + /* Also ensure the channel is dirty */ + if (!chan.is_dirty) + die("chan is not dirty"); + + err("OK"); +} + +/* Test that writting the same value to a channel with the flag CHAN_IGNORE_DUP, + * causes the channel to remain clean (without the is_dirty flag set) */ +static void +test_ignore_dup(void) +{ + struct chan chan; + chan_init(&chan, CHAN_SINGLE, "testchan"); + chan_prop_set(&chan, CHAN_IGNORE_DUP, 1); + + if (chan_set(&chan, value_int64(1)) != 0) + die("chan_set failed\n"); + + if (chan_flush(&chan) != 0) + die("chan_flush failed\n"); + + /* Write the same value */ + if (chan_set(&chan, value_int64(1)) != 0) + die("chan_set failed"); + + /* And ensure the channel is not dirty */ + if (chan.is_dirty) + die("chan is dirty"); + + err("OK"); } //static void @@ -159,7 +197,8 @@ int main(void) { test_single(); test_dirty(); - test_duplicate(); + test_allow_dup(); + test_ignore_dup(); //test_stack(); return 0; }