Mercurial > louis > mq > lightsd
changeset 199:55031f07152b
wip, need test on SET_TAG_LABELS triggers by refcount
author | Louis Opter <kalessin@kalessin.fr> |
---|---|
date | Sun, 19 Jul 2015 17:39:41 -0700 |
parents | 5609a782e502 |
children | 623a0664aecb |
files | tag_untag_testing_wip.patch |
diffstat | 1 files changed, 608 insertions(+), 72 deletions(-) [+] |
line wrap: on
line diff
--- a/tag_untag_testing_wip.patch Sun Jul 19 16:14:17 2015 -0700 +++ b/tag_untag_testing_wip.patch Sun Jul 19 17:39:41 2015 -0700 @@ -1,5 +1,5 @@ # HG changeset patch -# Parent 952ee0ab36a1500722322ef4720723279f9bee77 +# Parent ce5c778a6562f80ec8f2476632920dc738b67903 diff --git a/core/proto.c b/core/proto.c --- a/core/proto.c @@ -13,7 +13,13 @@ // the list of affected gateways so we can do SET_TAG_LABELS: SLIST_FOREACH(device, devices, link) { struct lgtd_lifx_gateway *gw = device->device->gw; -@@ -283,6 +283,7 @@ +@@ -279,10 +279,12 @@ + // SET_TAG_LABELS, this is idempotent, do it everytime so we can recover + // from any bad state: + LIST_FOREACH(site, &tag->sites, link) { +- int tag_id = lgtd_lifx_gateway_get_tag_id(site->gw, tag); ++ int tag_id = site->tag_id; ++ assert(tag_id > -1 && tag_id < LGTD_LIFX_GATEWAY_MAX_TAGS); struct lgtd_lifx_packet_tag_labels pkt = { .tags = 0 }; pkt.tags = LGTD_LIFX_WIRE_TAG_ID_TO_VALUE(tag_id); strncpy(pkt.label, tag_label, sizeof(pkt.label) - 1); @@ -21,15 +27,24 @@ bool enqueued = lgtd_lifx_gateway_send_to_site( site->gw, LGTD_LIFX_SET_TAG_LABELS, &pkt, sizeof(pkt) ); -@@ -302,6 +303,7 @@ +@@ -300,9 +302,13 @@ + struct lgtd_lifx_bulb *bulb = device->device; + int tag_id = lgtd_lifx_gateway_get_tag_id(bulb->gw, tag); assert(tag_id > -1 && tag_id < LGTD_LIFX_GATEWAY_MAX_TAGS); - struct lgtd_lifx_packet_tags pkt; - pkt.tags = bulb->state.tags | LGTD_LIFX_WIRE_TAG_ID_TO_VALUE(tag_id); -+ lgtd_lifx_wire_encode_tags(&pkt); - lgtd_router_send_to_device(bulb, LGTD_LIFX_SET_TAGS, &pkt); +- struct lgtd_lifx_packet_tags pkt; +- pkt.tags = bulb->state.tags | LGTD_LIFX_WIRE_TAG_ID_TO_VALUE(tag_id); +- lgtd_router_send_to_device(bulb, LGTD_LIFX_SET_TAGS, &pkt); ++ int tag_value = LGTD_LIFX_WIRE_TAG_ID_TO_VALUE(tag_id); ++ if (!(bulb->state.tags & tag_value)) { ++ struct lgtd_lifx_packet_tags pkt; ++ pkt.tags = bulb->state.tags | tag_value; ++ lgtd_lifx_wire_encode_tags(&pkt); ++ lgtd_router_send_to_device(bulb, LGTD_LIFX_SET_TAGS, &pkt); ++ } } -@@ -360,6 +362,7 @@ + SEND_RESULT(client, true); +@@ -360,6 +366,7 @@ if (bulb->state.tags & tag_value) { struct lgtd_lifx_packet_tags pkt; pkt.tags = bulb->state.tags & ~tag_value; @@ -289,7 +304,7 @@ #include "tests_utils.h" #define MOCKED_ROUTER_TARGETS_TO_DEVICES -@@ -8,33 +11,11 @@ +@@ -8,32 +11,12 @@ #define MOCKED_ROUTER_DEVICE_LIST_FREE #include "tests_proto_utils.h" @@ -297,7 +312,7 @@ + static struct lgtd_router_device_list devices = SLIST_HEAD_INITIALIZER(&devices); - +- -static bool device_list_free_called = false; - -void @@ -321,11 +336,12 @@ - - return &devices; -} -- ++static struct lgtd_router_device_list device_1_only = ++ SLIST_HEAD_INITIALIZER(&device_1_only); + static bool send_to_device_called = false; - void -@@ -64,17 +45,121 @@ +@@ -64,17 +47,129 @@ errx(1, "missing SET_TAGS payload"); } @@ -358,7 +374,7 @@ + + if (pkt_type != LGTD_LIFX_SET_TAG_LABELS) { + errx( -+ 1, "got packet type %#x (expected %#hx)", ++ 1, "got packet type %#x (expected %#x)", + pkt_type, LGTD_LIFX_SET_TAG_LABELS + ); + } @@ -420,10 +436,487 @@ + ); + } + ++ tag_id = 0; ++ ++ struct lgtd_lifx_tag *tag = lgtd_lifx_tagging_find_tag(tag_label); ++ if (!tag) { ++ errx(1, "tag %s wasn't found", tag_label); ++ } ++ lgtd_tests_add_tag_to_gw(tag, gw, tag_id); ++ + gateway_allocate_tag_id_called = true; + ++ return tag_id; ++} ++ ++static bool device_list_free_called = false; ++ ++void ++lgtd_router_device_list_free(struct lgtd_router_device_list *devices) ++{ ++ if (!devices) { ++ lgtd_errx(1, "the device list must be passed"); ++ } ++ ++ device_list_free_called = true; ++} ++ ++struct lgtd_router_device_list * ++lgtd_router_targets_to_devices(const struct lgtd_proto_target_list *targets) ++{ ++ if (targets != FAKE_TARGET_LIST) { ++ lgtd_errx(1, "unexpected targets list"); ++ } ++ ++ return &device_1_only; ++} ++ + static void + setup_devices(void) + { +@@ -96,6 +191,7 @@ + }; + static struct lgtd_router_device device_1 = { .device = &bulb_1 }; + SLIST_INSERT_HEAD(&devices, &device_1, link); ++ SLIST_INSERT_HEAD(&device_1_only, &device_1, link); + + struct lgtd_lifx_tag *gw_2_tag_1 = lgtd_tests_insert_mock_tag("vapor"); + struct lgtd_lifx_tag *gw_2_tag_2 = lgtd_tests_insert_mock_tag("d^-^b"); +@@ -127,15 +223,13 @@ + int + main(void) + { +- struct lgtd_client client; +- memset(&client, 0, sizeof(client)); ++ struct lgtd_client client = { .io = FAKE_BUFFEREVENT }; + + setup_devices(); + +- lgtd_proto_tag(&client, targets, "dub"); ++ lgtd_proto_tag(&client, FAKE_TARGET_LIST, "dub"); + + const char expected[] = "true"; +- + if (client_write_buf_idx != sizeof(expected) - 1) { + lgtd_errx( + 1, +@@ -145,7 +239,6 @@ + client_write_buf_idx, client_write_buf, expected + ); + } +- + if (memcmp(expected, client_write_buf, sizeof(expected) - 1)) { + lgtd_errx( + 1, "got %.*s instead of %s", +@@ -153,11 +246,14 @@ + ); + } + ++ if (!gateway_send_to_site_called) { ++ lgtd_errx(1, "SET_TAG_LABELS wasn't sent"); ++ } + if (!device_list_free_called) { + lgtd_errx(1, "the list of devices hasn't been freed"); + } + if (!send_to_device_called) { +- lgtd_errx(1, "nothing was send to any device"); ++ lgtd_errx(1, "SET_TAGS wasn't send to any device"); + } + + return 0; +diff --git a/tests/core/proto/test_proto_tag_create_lifx_gw_tag_ids_full.c b/tests/core/proto/test_proto_tag_create_lifx_gw_tag_ids_full.c +--- a/tests/core/proto/test_proto_tag_create_lifx_gw_tag_ids_full.c ++++ b/tests/core/proto/test_proto_tag_create_lifx_gw_tag_ids_full.c +@@ -0,0 +1,210 @@ ++#include "proto.c" ++ ++#include "mock_client_buf.h" ++#define MOCKED_LIFX_GATEWAY_SEND_TO_SITE ++#define MOCKED_LIFX_GATEWAY_ALLOCATE_TAG_ID ++#include "tests_shims.h" ++#include "tests_utils.h" ++ ++#define MOCKED_CLIENT_SEND_ERROR ++#define MOCKED_ROUTER_TARGETS_TO_DEVICES ++#define MOCKED_ROUTER_SEND_TO_DEVICE ++#define MOCKED_ROUTER_DEVICE_LIST_FREE ++#include "tests_proto_utils.h" ++ ++#define FAKE_TARGET_LIST (void *)0x2a ++ ++static struct lgtd_router_device_list devices = ++ SLIST_HEAD_INITIALIZER(&devices); ++static struct lgtd_router_device_list device_1_only = ++ SLIST_HEAD_INITIALIZER(&device_1_only); ++ ++static bool client_send_error_called = false; ++ ++void ++lgtd_client_send_error(struct lgtd_client *client, ++ enum lgtd_client_error_code error, ++ const char *msg) ++{ ++ if (!client) { ++ errx(1, "client_send_error called without a client"); ++ } ++ ++ if (!error) { ++ errx(1, "client_send_error called without an error code"); ++ } ++ ++ if (!msg) { ++ errx(1, "client_send_error called without an error message"); ++ } ++ ++ client_send_error_called = true; ++} ++ ++static bool send_to_device_called = false; ++ ++void ++lgtd_router_send_to_device(struct lgtd_lifx_bulb *bulb, ++ enum lgtd_lifx_packet_type pkt_type, ++ void *pkt) ++{ ++ (void)bulb; ++ (void)pkt_type; ++ (void)pkt; ++ ++ send_to_device_called = true; ++} ++ ++static bool gateway_send_to_site_called = false; ++ ++bool ++lgtd_lifx_gateway_send_to_site(struct lgtd_lifx_gateway *gw, ++ enum lgtd_lifx_packet_type pkt_type, ++ const void *pkt, ++ int pkt_size) ++{ ++ (void)gw; ++ (void)pkt_type; ++ (void)pkt; ++ (void)pkt_size; ++ ++ gateway_send_to_site_called = true; ++ ++ return true; ++} ++ ++static bool gateway_allocate_tag_id_called = false; ++ ++int ++lgtd_lifx_gateway_allocate_tag_id(struct lgtd_lifx_gateway *gw, ++ int tag_id, ++ const char *tag_label) ++{ ++ if (gateway_allocate_tag_id_called) { ++ errx( ++ 1, "lgtd_lifx_gateway_allocate_tag_id " ++ "should have been called once only" ++ ); ++ } ++ ++ if (tag_id != -1) { ++ errx( ++ 1, "lgtd_lifx_gateway_allocate_tag_id " ++ "tag_id %d (expected -1)", tag_id ++ ); ++ } ++ ++ if (!gw) { ++ errx( ++ 1, "lgtd_lifx_gateway_allocate_tag_id " ++ "must be called with gateway" ++ ); ++ } ++ ++ if (!tag_label) { ++ errx( ++ 1, "lgtd_lifx_gateway_allocate_tag_id " ++ "must be called with a tag_label" ++ ); ++ } ++ ++ return -1; // no more tag id available ++} ++ ++static bool device_list_free_called = false; ++ ++void ++lgtd_router_device_list_free(struct lgtd_router_device_list *devices) ++{ ++ if (!devices) { ++ lgtd_errx(1, "the device list must be passed"); ++ } ++ ++ device_list_free_called = true; ++} ++ ++struct lgtd_router_device_list * ++lgtd_router_targets_to_devices(const struct lgtd_proto_target_list *targets) ++{ ++ if (targets != FAKE_TARGET_LIST) { ++ lgtd_errx(1, "unexpected targets list"); ++ } ++ ++ return &device_1_only; ++} ++ ++static void ++setup_devices(void) ++{ ++ static struct lgtd_lifx_gateway gw_bulb_1 = { ++ .bulbs = LIST_HEAD_INITIALIZER(&gw_bulb_1.bulbs) ++ }; ++ static struct lgtd_lifx_bulb bulb_1 = { ++ .addr = { 1, 2, 3, 4, 5 }, ++ .state = { ++ .hue = 0xaaaa, ++ .saturation = 0xffff, ++ .brightness = 0xbbbb, ++ .kelvin = 3600, ++ .label = "wave", ++ .power = LGTD_LIFX_POWER_ON, ++ .tags = 0 ++ }, ++ .gw = &gw_bulb_1 ++ }; ++ static struct lgtd_router_device device_1 = { .device = &bulb_1 }; ++ SLIST_INSERT_HEAD(&devices, &device_1, link); ++ SLIST_INSERT_HEAD(&device_1_only, &device_1, link); ++ ++ struct lgtd_lifx_tag *gw_2_tag_1 = lgtd_tests_insert_mock_tag("vapor"); ++ struct lgtd_lifx_tag *gw_2_tag_2 = lgtd_tests_insert_mock_tag("d^-^b"); ++ struct lgtd_lifx_tag *gw_2_tag_3 = lgtd_tests_insert_mock_tag("wave~"); ++ static struct lgtd_lifx_gateway gw_bulb_2 = { ++ .bulbs = LIST_HEAD_INITIALIZER(&gw_bulb_2.bulbs), ++ .tag_ids = 0x7 ++ }; ++ lgtd_tests_add_tag_to_gw(gw_2_tag_1, &gw_bulb_2, 0); ++ lgtd_tests_add_tag_to_gw(gw_2_tag_2, &gw_bulb_2, 1); ++ lgtd_tests_add_tag_to_gw(gw_2_tag_3, &gw_bulb_2, 2); ++ static struct lgtd_lifx_bulb bulb_2 = { ++ .addr = { 5, 4, 3, 2, 1 }, ++ .state = { ++ .hue = 0x0000, ++ .saturation = 0x0000, ++ .brightness = 0xffff, ++ .kelvin = 4000, ++ .label = "", ++ .power = LGTD_LIFX_POWER_OFF, ++ .tags = 0x3 ++ }, ++ .gw = &gw_bulb_2 ++ }; ++ static struct lgtd_router_device device_2 = { .device = &bulb_2 }; ++ SLIST_INSERT_HEAD(&devices, &device_2, link); ++} ++ ++int ++main(void) ++{ ++ struct lgtd_client client = { .io = FAKE_BUFFEREVENT }; ++ ++ setup_devices(); ++ ++ lgtd_proto_tag(&client, FAKE_TARGET_LIST, "dub"); ++ ++ ++ if (gateway_send_to_site_called) { ++ lgtd_errx(1, "SET_TAG_LABELS shouldn't have been sent"); ++ } ++ if (!device_list_free_called) { ++ lgtd_errx(1, "the list of devices hasn't been freed"); ++ } ++ if (send_to_device_called) { ++ lgtd_errx(1, "SET_TAGS shouldn't have been to any device"); ++ } ++ if (!client_send_error_called) { ++ lgtd_errx(1, "client_send_error should have been called"); ++ } ++ + return 0; +} +diff --git a/tests/core/proto/test_proto_tag_update.c b/tests/core/proto/test_proto_tag_update.c +--- a/tests/core/proto/test_proto_tag_update.c ++++ b/tests/core/proto/test_proto_tag_update.c +@@ -0,0 +1,290 @@ ++#include "proto.c" ++ ++#include "mock_client_buf.h" ++#define MOCKED_LIFX_GATEWAY_SEND_TO_SITE ++#define MOCKED_LIFX_GATEWAY_ALLOCATE_TAG_ID ++#include "tests_shims.h" ++#include "tests_utils.h" ++ ++#define MOCKED_ROUTER_TARGETS_TO_DEVICES ++#define MOCKED_ROUTER_SEND_TO_DEVICE ++#define MOCKED_ROUTER_DEVICE_LIST_FREE ++#include "tests_proto_utils.h" ++ ++#define FAKE_TARGET_LIST (void *)0x2a ++ ++static struct lgtd_router_device_list devices = ++ SLIST_HEAD_INITIALIZER(&devices); ++ ++static bool send_to_device_called = false; ++ ++void ++lgtd_router_send_to_device(struct lgtd_lifx_bulb *bulb, ++ enum lgtd_lifx_packet_type pkt_type, ++ void *pkt) ++{ ++ if (send_to_device_called) { ++ errx(1, "lgtd_router_send_to_device should have been called once only"); ++ } ++ ++ if (!bulb) { ++ errx(1, "lgtd_router_send_to_device must be called with a bulb"); ++ } ++ ++ uint8_t expected_addr[LGTD_LIFX_ADDR_LENGTH] = { 5, 4, 3, 2, 1 }; ++ if (memcmp(bulb->addr, expected_addr, LGTD_LIFX_ADDR_LENGTH)) { ++ errx( ++ 1, "got bulb with addr %s (expected %s)", ++ lgtd_addrtoa(bulb->addr), lgtd_addrtoa(expected_addr) ++ ); ++ } ++ ++ if (pkt_type != LGTD_LIFX_SET_TAGS) { ++ errx( ++ 1, "got packet type %d (expected %d)", pkt_type, LGTD_LIFX_SET_TAGS ++ ); ++ } ++ ++ if (!pkt) { ++ errx(1, "missing SET_TAGS payload"); ++ } ++ ++ const struct lgtd_lifx_packet_tags *pkt_tags = pkt; ++ uint64_t tags = le64toh(pkt_tags->tags); ++ ++ if (tags != 0x7) { ++ errx( ++ 1, "invalid SET_TAGS payload=%#jx (expected %#x)", ++ (uintmax_t)tags, 0x7 ++ ); ++ } ++ ++ send_to_device_called = true; ++} ++ ++static bool gateway_send_to_site_called_for_gw_1 = false; ++static bool gateway_send_to_site_called_for_gw_2 = false; ++ ++bool ++lgtd_lifx_gateway_send_to_site(struct lgtd_lifx_gateway *gw, ++ enum lgtd_lifx_packet_type pkt_type, ++ const void *pkt, ++ int pkt_size) ++{ ++ if (!gw) { ++ errx(1, "missing gateway"); ++ } ++ ++ if (pkt_type != LGTD_LIFX_SET_TAG_LABELS) { ++ errx( ++ 1, "got packet type %#x (expected %#x)", ++ pkt_type, LGTD_LIFX_SET_TAG_LABELS ++ ); ++ } ++ ++ const struct lgtd_lifx_packet_tag_labels *pkt_tag_labels = pkt; ++ uint64_t tags = le64toh(pkt_tag_labels->tags); ++ ++ if (strcmp(pkt_tag_labels->label, "dub")) { ++ errx(1, "got label %s (expected dub)", pkt_tag_labels->label); ++ } ++ ++ if (pkt_size != sizeof(*pkt_tag_labels)) { ++ errx( ++ 1, "got pkt_size %d (expected %d)", ++ pkt_size, (int)sizeof(*pkt_tag_labels) ++ ); ++ } ++ ++ if (gw->site.as_integer == 42) { ++ if (tags != 0x1) { ++ errx(1, "got tags %#jx (expected %#x)", (uintmax_t)tags, 0x1); ++ } ++ if (gateway_send_to_site_called_for_gw_1) { ++ errx(1, "LGTD_LIFX_SET_TAG_LABELS already called for gw 1"); ++ } ++ gateway_send_to_site_called_for_gw_1 = true; ++ } else if (gw->site.as_integer == 44) { ++ if (tags != 0x4) { ++ errx(1, "got tags %#jx (expected %#x)", (uintmax_t)tags, 0x4); ++ } ++ if (gateway_send_to_site_called_for_gw_2) { ++ errx(1, "LGTD_LIFX_SET_TAG_LABELS already called for gw 2"); ++ } ++ gateway_send_to_site_called_for_gw_2 = true; ++ } else { ++ errx(1, "LGTD_LIFX_SET_TAG_LABELS received an invalid gateway"); ++ } ++ ++ return true; ++} ++ ++static bool gateway_allocate_tag_id_called = false; ++ ++int ++lgtd_lifx_gateway_allocate_tag_id(struct lgtd_lifx_gateway *gw, ++ int tag_id, ++ const char *tag_label) ++{ ++ if (gateway_allocate_tag_id_called) { ++ errx( ++ 1, "lgtd_lifx_gateway_allocate_tag_id " ++ "should have been called once only" ++ ); ++ } ++ ++ if (tag_id != -1) { ++ errx( ++ 1, "lgtd_lifx_gateway_allocate_tag_id " ++ "tag_id %d (expected -1)", tag_id ++ ); ++ } ++ ++ if (!gw) { ++ errx( ++ 1, "lgtd_lifx_gateway_allocate_tag_id " ++ "must be called with gateway" ++ ); ++ } ++ ++ if (!tag_label) { ++ errx( ++ 1, "lgtd_lifx_gateway_allocate_tag_id " ++ "must be called with a tag_label" ++ ); ++ } ++ ++ if (gw->site.as_integer != 44) { ++ errx( ++ 1, "lgtd_lifx_gateway_allocate_tag_id got the wrong gateway " ++ "%#jx (expected %d)", (uintmax_t)gw->site.as_integer, 44 ++ ); ++ } ++ ++ tag_id = 2; ++ ++ struct lgtd_lifx_tag *tag = lgtd_lifx_tagging_find_tag(tag_label); ++ if (!tag) { ++ errx(1, "tag %s wasn't found", tag_label); ++ } ++ lgtd_tests_add_tag_to_gw(tag, gw, tag_id); ++ ++ gateway_allocate_tag_id_called = true; ++ ++ return tag_id; ++} + +static bool device_list_free_called = false; + @@ -447,68 +940,96 @@ + return &devices; +} + - static void - setup_devices(void) - { -@@ -127,15 +212,13 @@ - int - main(void) - { -- struct lgtd_client client; -- memset(&client, 0, sizeof(client)); -+ struct lgtd_client client = { .io = FAKE_BUFFEREVENT }; - - setup_devices(); - -- lgtd_proto_tag(&client, targets, "dub"); -+ lgtd_proto_tag(&client, FAKE_TARGET_LIST, "dub"); - - const char expected[] = "true"; -- - if (client_write_buf_idx != sizeof(expected) - 1) { - lgtd_errx( - 1, -@@ -145,7 +228,6 @@ - client_write_buf_idx, client_write_buf, expected - ); - } -- - if (memcmp(expected, client_write_buf, sizeof(expected) - 1)) { - lgtd_errx( - 1, "got %.*s instead of %s", -@@ -153,11 +235,14 @@ - ); - } - -+ if (!gateway_send_to_site_called) { -+ lgtd_errx(1, "SET_TAG_LABELS wasn't sent"); -+ } - if (!device_list_free_called) { - lgtd_errx(1, "the list of devices hasn't been freed"); - } - if (!send_to_device_called) { -- lgtd_errx(1, "nothing was send to any device"); -+ lgtd_errx(1, "SET_TAGS wasn't send to any device"); - } - - return 0; -diff --git a/tests/core/proto/test_proto_tag_create_lifx_gw_tag_ids_full.c b/tests/core/proto/test_proto_tag_create_lifx_gw_tag_ids_full.c ---- a/tests/core/proto/test_proto_tag_create_lifx_gw_tag_ids_full.c -+++ b/tests/core/proto/test_proto_tag_create_lifx_gw_tag_ids_full.c -@@ -0,0 +1,6 @@ ++static void ++setup_devices(void) ++{ ++ static struct lgtd_lifx_gateway gw_bulb_1 = { ++ .bulbs = LIST_HEAD_INITIALIZER(&gw_bulb_1.bulbs), ++ .site = { .as_integer = 42 } ++ }; ++ static struct lgtd_lifx_bulb bulb_1 = { ++ .addr = { 1, 2, 3, 4, 5 }, ++ .state = { ++ .hue = 0xaaaa, ++ .saturation = 0xffff, ++ .brightness = 0xbbbb, ++ .kelvin = 3600, ++ .label = "wave", ++ .power = LGTD_LIFX_POWER_ON, ++ .tags = 1 ++ }, ++ .gw = &gw_bulb_1 ++ }; ++ static struct lgtd_router_device device_1 = { .device = &bulb_1 }; ++ SLIST_INSERT_HEAD(&devices, &device_1, link); ++ struct lgtd_lifx_tag *gw_1_tag_1 = lgtd_tests_insert_mock_tag("dub"); ++ lgtd_tests_add_tag_to_gw(gw_1_tag_1, &gw_bulb_1, 0); ++ ++ struct lgtd_lifx_tag *gw_2_tag_1 = lgtd_tests_insert_mock_tag("vapor"); ++ struct lgtd_lifx_tag *gw_2_tag_2 = lgtd_tests_insert_mock_tag("d^-^b"); ++ static struct lgtd_lifx_gateway gw_bulb_2 = { ++ .bulbs = LIST_HEAD_INITIALIZER(&gw_bulb_2.bulbs), ++ .site = { .as_integer = 44 }, ++ .tag_ids = 0x3 ++ }; ++ lgtd_tests_add_tag_to_gw(gw_2_tag_1, &gw_bulb_2, 0); ++ lgtd_tests_add_tag_to_gw(gw_2_tag_2, &gw_bulb_2, 1); ++ static struct lgtd_lifx_bulb bulb_2 = { ++ .addr = { 5, 4, 3, 2, 1 }, ++ .state = { ++ .hue = 0x0000, ++ .saturation = 0x0000, ++ .brightness = 0xffff, ++ .kelvin = 4000, ++ .label = "", ++ .power = LGTD_LIFX_POWER_OFF, ++ .tags = 0x3 ++ }, ++ .gw = &gw_bulb_2 ++ }; ++ static struct lgtd_router_device device_2 = { .device = &bulb_2 }; ++ SLIST_INSERT_HEAD(&devices, &device_2, link); ++} ++ +int +main(void) +{ ++ struct lgtd_client client = { .io = FAKE_BUFFEREVENT }; + -+ return 0; -+} -diff --git a/tests/core/proto/test_proto_tag_update.c b/tests/core/proto/test_proto_tag_update.c ---- a/tests/core/proto/test_proto_tag_update.c -+++ b/tests/core/proto/test_proto_tag_update.c -@@ -0,0 +1,5 @@ -+int -+main(void) -+{ ++ setup_devices(); ++ ++ lgtd_proto_tag(&client, FAKE_TARGET_LIST, "dub"); ++ ++ const char expected[] = "true"; ++ if (client_write_buf_idx != sizeof(expected) - 1) { ++ lgtd_errx( ++ 1, ++ "%d bytes written, expected %lu " ++ "(got %.*s instead of %s)", ++ client_write_buf_idx, sizeof(expected) - 1UL, ++ client_write_buf_idx, client_write_buf, expected ++ ); ++ } ++ if (memcmp(expected, client_write_buf, sizeof(expected) - 1)) { ++ lgtd_errx( ++ 1, "got %.*s instead of %s", ++ client_write_buf_idx, client_write_buf, expected ++ ); ++ } ++ ++ if (!gateway_send_to_site_called_for_gw_1) { ++ lgtd_errx(1, "SET_TAG_LABELS wasn't sent to gw 1"); ++ } ++ if (!gateway_send_to_site_called_for_gw_2) { ++ lgtd_errx(1, "SET_TAG_LABELS wasn't sent to gw 2"); ++ } ++ if (!device_list_free_called) { ++ lgtd_errx(1, "the list of devices hasn't been freed"); ++ } ++ if (!send_to_device_called) { ++ lgtd_errx(1, "SET_TAGS wasn't send to any device"); ++ } ++ + return 0; +} diff --git a/tests/core/proto/test_proto_untag.c b/tests/core/proto/test_proto_untag.c @@ -638,3 +1159,18 @@ + return -1; +} +#endif +diff --git a/tests/core/tests_utils.c b/tests/core/tests_utils.c +--- a/tests/core/tests_utils.c ++++ b/tests/core/tests_utils.c +@@ -105,7 +105,10 @@ + struct lgtd_lifx_site *site = calloc(1, sizeof(*site)); + site->gw = gw; + site->tag_id = tag_id; ++ LIST_INSERT_HEAD(&tag->sites, site, link); ++ + gw->tags[tag_id] = tag; +- LIST_INSERT_HEAD(&tag->sites, site, link); ++ gw->tag_ids |= LGTD_LIFX_WIRE_TAG_ID_TO_VALUE(tag_id); ++ + return site; + }