static char* test_api_assertion()
{
  lsb_lua_sandbox *sb = lsb_create(NULL, "lua/counter.lua", "", NULL);
  lsb_err_value ret = lsb_init(sb, NULL);
  mu_assert(!ret, "lsb_init() received: %s", ret);

  lsb_stop_sandbox(NULL);
  mu_assert(lsb_destroy(NULL) == NULL, "not null");
  mu_assert(lsb_usage(NULL, 0, 0) == 0, "not 0");
  mu_assert(lsb_usage(sb, LSB_UT_MAX, 0) == 0, "not 0");
  mu_assert(lsb_usage(sb, 0, LSB_US_MAX) == 0, "not 0");
  mu_assert(strcmp(lsb_get_error(NULL), "") == 0, "not empty");
  lsb_set_error(NULL, "foo");
  mu_assert(lsb_get_lua(NULL) == NULL, "not null");
  mu_assert(lsb_get_lua_file(NULL) == NULL, "not null");
  mu_assert(lsb_get_parent(NULL) == NULL, "not null");
  mu_assert(lsb_get_logger(NULL) == NULL, "not null");
  mu_assert(lsb_get_state(NULL) == LSB_UNKNOWN, "not unknown");
  lsb_add_function(NULL, lsb_test_write_output, "foo");
  lsb_add_function(sb, NULL, "foo");
  lsb_add_function(sb, lsb_test_write_output, NULL);
  mu_assert(lsb_pcall_setup(NULL, "foo") == LSB_ERR_UTIL_NULL, "not null");
  mu_assert(lsb_pcall_setup(sb, NULL) == LSB_ERR_UTIL_NULL, "not null");
  lsb_add_function(NULL, NULL, NULL);
  lsb_pcall_teardown(NULL);
  lsb_terminate(NULL, NULL);
  lsb_terminate(sb, NULL);
  lsb_add_function(sb, lsb_test_write_output, "write_output");

  e = lsb_destroy(sb);
  mu_assert(!e, "lsb_destroy() received: %s", e);
  return NULL;
}
static char* test_restore()
{
  const char *output_file = "restore.preserve";

  remove(output_file);
  lsb_lua_sandbox *sb = lsb_create(NULL, "lua/restore.lua", test_cfg, NULL);
  mu_assert(sb, "lsb_create() received: NULL");
  lsb_err_value ret = lsb_init(sb, output_file);
  mu_assert(!ret, "lsb_init() received: %s", ret);
  lsb_add_function(sb, &lsb_test_write_output, "write_output");
  int result = lsb_test_process(sb, 0);
  mu_assert(result == 0, "process() received: %d %s", result,
            lsb_get_error(sb));
  mu_assert(strcmp("101", lsb_test_output) == 0, "test: initial load received: %s",
            lsb_test_output);
  e = lsb_destroy(sb);
  mu_assert(!e, "lsb_destroy() received: %s", e);

  // re-load to test the preserved data
  sb = lsb_create(NULL, "lua/restore.lua", test_cfg, NULL);
  mu_assert(sb, "lsb_create() received: NULL");
  ret = lsb_init(sb, output_file);
  mu_assert(!ret, "lsb_init() received: %s", ret);
  lsb_add_function(sb, &lsb_test_write_output, "write_output");
  result = lsb_test_process(sb, 0);
  mu_assert(result == 0, "process() received: %d %s", result,
            lsb_get_error(sb));
  mu_assert(strcmp("102", lsb_test_output) == 0, "test: reload received: %s",
            lsb_test_output);
  result = lsb_test_report(sb, 2); // change the preservation version
  mu_assert(result == 0, "report() received: %d", result);
  e = lsb_destroy(sb);
  mu_assert(!e, "lsb_destroy() received: %s", e);

  // re-load to test the preserved data with a version change
  sb = lsb_create(NULL, "lua/restore.lua", test_cfg, NULL);
  mu_assert(sb, "lsb_create() received: NULL");
  ret = lsb_init(sb, output_file);
  mu_assert(!ret, "lsb_init() received: %s", ret);
  lsb_add_function(sb, &lsb_test_write_output, "write_output");
  result = lsb_test_process(sb, 0);
  mu_assert(result == 0, "process() received: %d %s", result,
            lsb_get_error(sb));
  mu_assert(strcmp("101", lsb_test_output) == 0,
            "test: reload with version change received: %s", lsb_test_output);
  e = lsb_destroy(sb);
  mu_assert(!e, "lsb_destroy() received: %s", e);

  return NULL;
}
static char* test_output_errors()
{
  const char *tests[] =
  {
    "process() lua/output_errors.lua:10: bad argument #1 to 'output' (unsupported type)"
    , "process() lua/output_errors.lua:16: output_limit exceeded"
    , "process() lua/output_errors.lua:18: bad argument #1 to 'write_output' (unknown userdata type)"
    , NULL
  };

  for (int i = 0; tests[i]; ++i) {
    lsb_lua_sandbox *sb = lsb_create(NULL, "lua/output_errors.lua",
                                     MODULE_PATH "output_limit = 128", NULL);
    mu_assert(sb, "lsb_create() received: NULL");

    lsb_err_value ret = lsb_init(sb, NULL);
    mu_assert(!ret, "lsb_init() received: %s", ret);
    lsb_add_function(sb, &lsb_test_write_output, "write_output");

    int result = lsb_test_process(sb, i);
    mu_assert(result == 1, "test: %d received: %d", i, result);

    const char *le = lsb_get_error(sb);
    mu_assert(le, "test: %d received NULL", i);
    mu_assert(strcmp(tests[i], le) == 0, "test: %d received: %s", i, le);

    e = lsb_destroy(sb);
    mu_assert(!e, "lsb_destroy() received: %s", e);
  }

  return NULL;
}
static char* test_output()
{
  const char *outputs[] = {
    "1.2 string nil true false",
    "foo",
    NULL
  };

  lsb_lua_sandbox *sb = lsb_create(NULL, "lua/output.lua", test_cfg, NULL);
  mu_assert(sb, "lsb_create() received: NULL");
  add_ud_module(sb);

  lsb_err_value ret = lsb_init(sb, NULL);
  mu_assert(!ret, "lsb_init() received: %s", ret);
  lsb_add_function(sb, &lsb_test_write_output, "write_output");

  for (int x = 0; outputs[x]; ++x) {
    int result = lsb_test_process(sb, x);
    mu_assert(!result, "process() test: %d failed: %d %s", x, result,
              lsb_get_error(sb));
    if (outputs[x][0]) {
      mu_assert(strcmp(outputs[x], lsb_test_output) == 0,
                "test: %d received: %s", x, lsb_test_output);
    }
  }

  e = lsb_destroy(sb);
  mu_assert(!e, "lsb_destroy() received: %s", e);

  return NULL;
}
Beispiel #5
0
static hs_output_plugin* create_output_plugin(const hs_config* cfg,
                                              hs_sandbox_config* sbc)
{
  hs_output_plugin* p = calloc(1, sizeof(hs_output_plugin));
  if (!p) return NULL;
  p->list_index = -1;

  if (pthread_mutex_init(&p->cp_lock, NULL)) {
    perror("cp_lock pthread_mutex_init failed");
    exit(EXIT_FAILURE);
  }

  p->sb = hs_create_output_sandbox(p, cfg, sbc);
  if (!p->sb) {
    free(p);
    hs_log(g_module, 3, "lsb_create_custom failed: %s/%s", sbc->dir,
           sbc->filename);
    return NULL;
  }

  if (sbc->async_buffer_size > 0) {
    p->async_len = sbc->async_buffer_size;
    p->async_cp = calloc(p->async_len, sizeof(hs_checkpoint_pair));
    if (!p->async_cp) {
      hs_free_sandbox(p->sb);
      free(p);
      hs_log(g_module, 3, "failed allocating the async buffer");
      return NULL;
    }
    lsb_add_function(p->sb->lsb, &async_checkpoint_update,
                     "async_checkpoint_update");
  }
  return p;
}
static char* test_cbuf()
{
  const char* outputs[] = {
    "{\"time\":0,\"rows\":3,\"columns\":3,\"seconds_per_row\":1,\"column_info\":[{\"name\":\"Add_column\",\"unit\":\"count\",\"aggregation\":\"sum\"},{\"name\":\"Set_column\",\"unit\":\"count\",\"aggregation\":\"sum\"},{\"name\":\"Get_column\",\"unit\":\"count\",\"aggregation\":\"sum\"}]}\n0\t0\t0\n0\t0\t0\n0\t0\t0\n"
    , "{\"time\":0,\"rows\":3,\"columns\":3,\"seconds_per_row\":1,\"column_info\":[{\"name\":\"Add_column\",\"unit\":\"count\",\"aggregation\":\"sum\"},{\"name\":\"Set_column\",\"unit\":\"count\",\"aggregation\":\"sum\"},{\"name\":\"Get_column\",\"unit\":\"count\",\"aggregation\":\"sum\"}]}\n1\t1\t1\n2\t1\t2\n3\t1\t3\n"
    , "{\"time\":2,\"rows\":3,\"columns\":3,\"seconds_per_row\":1,\"column_info\":[{\"name\":\"Add_column\",\"unit\":\"count\",\"aggregation\":\"sum\"},{\"name\":\"Set_column\",\"unit\":\"count\",\"aggregation\":\"sum\"},{\"name\":\"Get_column\",\"unit\":\"count\",\"aggregation\":\"sum\"}]}\n3\t1\t3\n0\t0\t0\n1\t1\t1\n"
    , "{\"time\":8,\"rows\":3,\"columns\":3,\"seconds_per_row\":1,\"column_info\":[{\"name\":\"Add_column\",\"unit\":\"count\",\"aggregation\":\"sum\"},{\"name\":\"Set_column\",\"unit\":\"count\",\"aggregation\":\"sum\"},{\"name\":\"Get_column\",\"unit\":\"count\",\"aggregation\":\"sum\"}]}\n0\t0\t0\n0\t0\t0\n1\t1\t1\n"
    , NULL
  };

  lua_sandbox* sb = lsb_create(NULL, "lua/circular_buffer.lua", 32767,
                               1000, 32767);
  mu_assert(sb, "lsb_create() received: NULL");

  int result = lsb_init(sb, NULL);
  mu_assert(result == 0, "lsb_init() received: %d %s", result,
            lsb_get_error(sb));
  lsb_add_function(sb, &write_output, "write");

  result = report(sb, 0);
  mu_assert(lsb_get_state(sb) == LSB_RUNNING, "error %s",
            lsb_get_error(sb));
  mu_assert(strcmp(outputs[0], written_data) == 0, "received: %s",
            written_data);

  process(sb, 0);
  process(sb, 1e9);
  process(sb, 1e9);
  process(sb, 2e9);
  process(sb, 2e9);
  process(sb, 2e9);
  result = report(sb, 0);
  mu_assert(result == 0, "report() received: %d", result);
  mu_assert(strcmp(outputs[1], written_data) == 0, "received: %s",
            written_data);

  process(sb, 4e9);
  result = report(sb, 0);
  mu_assert(result == 0, "report() received: %d", result);
  mu_assert(strcmp(outputs[2], written_data) == 0, "received: %s",
            written_data);

  process(sb, 10e9);
  result = report(sb, 0);
  mu_assert(result == 0, "report() received: %d", result);
  mu_assert(strcmp(outputs[3], written_data) == 0, "received: %s",
            written_data);

  result = report(sb, 1);
  mu_assert(result == 0, "report() received: %d", result);

  result = report(sb, 3);
  mu_assert(result == 0, "report() received: %d", result);

  e = lsb_destroy(sb, "circular_buffer.preserve");
  mu_assert(!e, "lsb_destroy() received: %s", e);

  return NULL;
}
Beispiel #7
0
int hs_init_analysis_sandbox(hs_sandbox* sb, lua_CFunction im_fp)
{
  if (!im_fp) return -1;

  lsb_add_function(sb->lsb, &read_message, "read_message");
  lsb_add_function(sb->lsb, im_fp, "inject_message");
  lsb_add_function(sb->lsb, &inject_payload, "inject_payload");

  int ret = lsb_init(sb->lsb, sb->state);
  if (ret) return ret;

  lua_State* lua = lsb_get_lua(sb->lsb);
  // rename output to add_to_payload
  lua_getglobal(lua, "output");
  lua_setglobal(lua, "add_to_payload");
  lua_pushnil(lua);
  lua_setglobal(lua, "output");
  return 0;
}
Beispiel #8
0
int hs_init_output_sandbox(hs_sandbox* sb)
{
  lsb_add_function(sb->lsb, &read_message, "read_message");

  int ret = lsb_init(sb->lsb, sb->state);
  if (ret) return ret;

  lua_State* lua = lsb_get_lua(sb->lsb);
  // remove output function
  lua_pushnil(lua);
  lua_setglobal(lua, "output");

  return 0;
}
static char* benchmark_lua_types_output()
{
  int iter = 1000000;

  lsb_lua_sandbox *sb = lsb_create(NULL, "lua/output.lua", test_cfg, NULL);
  mu_assert(sb, "lsb_create() received: NULL");
  lsb_err_value ret = lsb_init(sb, NULL);
  mu_assert(!ret, "lsb_init() received: %s", ret);
  lsb_add_function(sb, &lsb_test_write_output, "write_output");

  clock_t t = clock();
  for (int x = 0; x < iter; ++x) {
    mu_assert(0 == lsb_test_process(sb, 0), "%s", lsb_get_error(sb));
  }
  t = clock() - t;
  e = lsb_destroy(sb);
  mu_assert(!e, "lsb_destroy() received: %s", e);
  printf("benchmark_lua_types_output() %g seconds\n", ((double)t)
         / CLOCKS_PER_SEC / iter);

  return NULL;
}
static char* benchmark_table_output()
{
  int iter = 100000;

  lua_sandbox* sb = lsb_create(NULL, "lua/output.lua", 100000, 1000,
                               1024 * 63);
  mu_assert(sb, "lsb_create() received: NULL");
  int result = lsb_init(sb, NULL);
  mu_assert(result == 0, "lsb_init() received: %d %s", result,
            lsb_get_error(sb));
  lsb_add_function(sb, &write_output, "write");

  clock_t t = clock();
  for (int x = 0; x < iter; ++x) {
    process(sb, 2);
  }
  t = clock() - t;
  e = lsb_destroy(sb, NULL);
  mu_assert(!e, "lsb_destroy() received: %s", e);
  printf("benchmark_table_output() %g seconds\n", ((float)t) / CLOCKS_PER_SEC / iter);

  return NULL;
}
static char* test_lpeg()
{
  const char* expected = "{\"table\":[\"1\",\"string with spaces\","
    "\"quoted string, with comma and \\\"quoted\\\" text\"]}\n";

  lua_sandbox* sb = lsb_create(NULL, "lua/lpeg_csv.lua", 100000, 1000,
                               8000);
  mu_assert(sb, "lsb_create() received: NULL");

  int result = lsb_init(sb, NULL);
  mu_assert(result == 0, "lsb_init() received: %d %s", result,
            lsb_get_error(sb));
  lsb_add_function(sb, &write_output, "write");

  result = process(sb, 0);
  mu_assert(result == 0, "process() received: %d %s", result,
            lsb_get_error(sb));
  mu_assert(strcmp(expected, written_data) == 0, "received: %s", written_data);

  e = lsb_destroy(sb, NULL);
  mu_assert(!e, "lsb_destroy() received: %s", e);

  return NULL;
}
Beispiel #12
0
lsb_heka_sandbox* lsb_heka_create_output(void *parent,
                                         const char *lua_file,
                                         const char *state_file,
                                         const char *lsb_cfg,
                                         lsb_logger logger,
                                         lsb_heka_update_checkpoint ucp)
{
  if (!lua_file) {
    if (logger) logger(__FUNCTION__, 3, "lua_file must be specified");
    return NULL;
  }

  if (!ucp) {
    if (logger) logger(__FUNCTION__, 3, "update_checkpoint callback must be "
                       "specified");
    return NULL;
  }


  lsb_heka_sandbox *hsb = calloc(1, sizeof(lsb_heka_sandbox));
  if (!hsb) {
    if (logger) logger(__FUNCTION__, 3, "memory allocation failed");
    return NULL;
  }

  hsb->type = 'o';
  hsb->parent = parent;
  hsb->msg = NULL;
  hsb->cb.ucp = ucp;
  hsb->name = NULL;
  hsb->hostname = NULL;

  hsb->lsb = lsb_create(hsb, lua_file, lsb_cfg, logger);
  if (!hsb->lsb) {
    free(hsb);
    return NULL;
  }

  lua_State *lua = lsb_get_lua(hsb->lsb);
  set_restrictions(lua, hsb);

// todo link print to the logger or a no-op
  lsb_add_function(hsb->lsb, heka_decode_message, "decode_message");
  lsb_add_function(hsb->lsb, heka_encode_message, "encode_message");
  lsb_add_function(hsb->lsb, update_checkpoint, "update_checkpoint");

  if (lsb_init(hsb->lsb, state_file)) {
    if (logger) logger(hsb->name, 3, lsb_get_error(hsb->lsb));
    lsb_destroy(hsb->lsb);
    free(hsb->hostname);
    free(hsb->name);
    free(hsb);
    return NULL;
  }

// remove output function
  lua_pushnil(lua);
  lua_setglobal(lua, "output");

  return hsb;
}
Beispiel #13
0
lsb_heka_sandbox* lsb_heka_create_analysis(void *parent,
                                           const char *lua_file,
                                           const char *state_file,
                                           const char *lsb_cfg,
                                           lsb_logger logger,
                                           lsb_heka_im_analysis im)
{
  if (!lua_file) {
    if (logger) logger(__FUNCTION__, 3, "lua_file must be specified");
    return NULL;
  }

  if (!im) {
    if (logger) logger(__FUNCTION__, 3, "inject_message callback must be "
                       "specified");
    return NULL;
  }


  lsb_heka_sandbox *hsb = calloc(1, sizeof(lsb_heka_sandbox));
  if (!hsb) {
    if (logger) logger(__FUNCTION__, 3, "memory allocation failed");
    return NULL;
  }

  hsb->type = 'a';
  hsb->parent = parent;
  hsb->msg = NULL;
  hsb->cb.aim = im;
  hsb->name = NULL;
  hsb->hostname = NULL;

  hsb->lsb = lsb_create(hsb, lua_file, lsb_cfg, logger);
  if (!hsb->lsb) {
    free(hsb);
    return NULL;
  }

  lua_State *lua = lsb_get_lua(hsb->lsb);
  set_restrictions(lua, hsb);

// todo link print to the logger or a no-op
  lsb_add_function(hsb->lsb, heka_decode_message, "decode_message");
  lsb_add_function(hsb->lsb, read_message, "read_message");
  lsb_add_function(hsb->lsb, inject_message_analysis, "inject_message");
  lsb_add_function(hsb->lsb, inject_payload, "inject_payload");
// rename output to add_to_payload
  lua_getglobal(lua, "output");
  lua_setglobal(lua, "add_to_payload");
  lua_pushnil(lua);
  lua_setglobal(lua, "output");

  if (lsb_init(hsb->lsb, state_file)) {
    if (logger) logger(hsb->name, 3, lsb_get_error(hsb->lsb));
    lsb_destroy(hsb->lsb);
    free(hsb->hostname);
    free(hsb->name);
    free(hsb);
    return NULL;
  }
  return hsb;
}
Beispiel #14
0
lsb_heka_sandbox* lsb_heka_create_input(void *parent,
                                        const char *lua_file,
                                        const char *state_file,
                                        const char *lsb_cfg,
                                        lsb_logger logger,
                                        lsb_heka_im_input im)
{
  if (!lua_file) {
    if (logger) logger(__FUNCTION__, 3, "lua_file must be specified");
    return NULL;
  }

  if (!im) {
    if (logger) logger(__FUNCTION__, 3, "inject_message callback must be "
                       "specified");
    return NULL;
  }

  lsb_heka_sandbox *hsb = calloc(1, sizeof(lsb_heka_sandbox));
  if (!hsb) {
    if (logger) logger(__FUNCTION__, 3, "memory allocation failed");
    return NULL;
  }

  hsb->type = 'i';
  hsb->parent = parent;
  hsb->msg = NULL;
  hsb->cb.iim = im;
  hsb->name = NULL;
  hsb->hostname = NULL;

  hsb->lsb = lsb_create(hsb, lua_file, lsb_cfg, logger);
  if (!hsb->lsb) {
    free(hsb);
    return NULL;
  }

  lua_State *lua = lsb_get_lua(hsb->lsb);
  set_restrictions(lua, hsb);

// todo link print to the logger or a no-op
  lsb_add_function(hsb->lsb, heka_decode_message, "decode_message");
  lsb_add_function(hsb->lsb, read_message, "read_message");
  lsb_add_function(hsb->lsb, inject_message_input, "inject_message");
// inject_payload is intentionally excluded from input plugins
// you can construct whatever you need with inject_message

// preload the Heka stream reader module
  luaL_findtable(lua, LUA_REGISTRYINDEX, "_PRELOADED", 1);
  lua_pushstring(lua, mozsvc_heka_stream_reader_table);
  lua_pushcfunction(lua, luaopen_heka_stream_reader);
  lua_rawset(lua, -3);
  lua_pop(lua, 1); // remove the preloaded table

  if (lsb_init(hsb->lsb, state_file)) {
    if (logger) logger(hsb->name, 3, lsb_get_error(hsb->lsb));
    lsb_destroy(hsb->lsb);
    free(hsb->hostname);
    free(hsb->name);
    free(hsb);
    return NULL;
  }

// remove output function
  lua_pushnil(lua);
  lua_setglobal(lua, "output");

  return hsb;
}
static char* test_output()
{
  const char* outputs[] = {
    "{\"table\":{\"value\":1}}\n1.2 string nil true false"
    , ""
#ifdef LUA_JIT
    , "{\"table\":{\"Timestamp\":0,\"Value\":0,\"StatisticValues\":[{\"SampleCount\":0,\"Sum\":0,\"Maximum\":0,\"Minimum\":0},{\"SampleCount\":0,\"Sum\":0,\"Maximum\":0,\"Minimum\":0}],\"Unit\":\"s\",\"MetricName\":\"example\",\"Dimensions\":[{\"Name\":\"d1\",\"Value\":\"v1\"},{\"Name\":\"d2\",\"Value\":\"v2\"}]}}\n"
#else
    , "{\"table\":{\"StatisticValues\":[{\"Minimum\":0,\"SampleCount\":0,\"Sum\":0,\"Maximum\":0},{\"Minimum\":0,\"SampleCount\":0,\"Sum\":0,\"Maximum\":0}],\"Dimensions\":[{\"Name\":\"d1\",\"Value\":\"v1\"},{\"Name\":\"d2\",\"Value\":\"v2\"}],\"MetricName\":\"example\",\"Timestamp\":0,\"Value\":0,\"Unit\":\"s\"}}\n"
#endif
    , "{\"table\":{\"a\":{\"y\":2,\"x\":1}}}\n"
    , "{\"table\":[1,2,3]}\n"
    , "{\"table\":{\"x\":1}}\n"
    , "{\"array\":[1,2,3]}\n"
    , "{\"table\":{}}\n"
    , "{\"table\":{\"special\\tcharacters\":\"\\\"\\t\\r\\n\\b\\f\\\\\\/\"}}\n"
    , "\x10\x80\x94\xeb\xdc\x03\x1a\x04\x74\x79\x70\x65\x22\x06\x6c\x6f\x67\x67\x65\x72\x28\x09\x32\x07\x70\x61\x79\x6c\x6f\x61\x64\x3a\x0b\x65\x6e\x76\x5f\x76\x65\x72\x73\x69\x6f\x6e\x4a\x08\x68\x6f\x73\x74\x6e\x61\x6d\x65"
    , "\x10\x80\x94\xeb\xdc\x03\x52\x12\x0a\x05\x63\x6f\x75\x6e\x74\x10\x03\x39\x00\x00\x00\x00\x00\x00\xf0\x3f"
    , "\x10\x80\x94\xeb\xdc\x03\x52\x25\x0a\x06\x63\x6f\x75\x6e\x74\x73\x10\x03\x39\x00\x00\x00\x00\x00\x00\x00\x40\x39\x00\x00\x00\x00\x00\x00\x08\x40\x39\x00\x00\x00\x00\x00\x00\x10\x40"
    , "\x10\x80\x94\xeb\xdc\x03\x52\x19\x0a\x05\x63\x6f\x75\x6e\x74\x10\x03\x1a\x05\x63\x6f\x75\x6e\x74\x39\x00\x00\x00\x00\x00\x00\x14\x40"
    , "\x10\x80\x94\xeb\xdc\x03\x52\x2c\x0a\x06\x63\x6f\x75\x6e\x74\x73\x10\x03\x1a\x05\x63\x6f\x75\x6e\x74\x39\x00\x00\x00\x00\x00\x00\x18\x40\x39\x00\x00\x00\x00\x00\x00\x1c\x40\x39\x00\x00\x00\x00\x00\x00\x20\x40"
#ifdef LUA_JIT
    , "\x10\x80\x94\xeb\xdc\x03\x52\x13\x0a\x06\x6e\x75\x6d\x62\x65\x72\x10\x03\x39\x00\x00\x00\x00\x00\x00\xf0\x3f\x52\x0f\x0a\x05\x62\x6f\x6f\x6c\x73\x10\x04\x40\x01\x40\x00\x40\x00\x52\x10\x0a\x06\x73\x74\x72\x69\x6e\x67\x22\x06\x73\x74\x72\x69\x6e\x67\x52\x0a\x0a\x04\x62\x6f\x6f\x6c\x10\x04\x40\x01\x52\x2d\x0a\x07\x6e\x75\x6d\x62\x65\x72\x73\x10\x03\x1a\x05\x63\x6f\x75\x6e\x74\x39\x00\x00\x00\x00\x00\x00\xf0\x3f\x39\x00\x00\x00\x00\x00\x00\x00\x40\x39\x00\x00\x00\x00\x00\x00\x08\x40\x52\x15\x0a\x07\x73\x74\x72\x69\x6e\x67\x73\x22\x02\x73\x31\x22\x02\x73\x32\x22\x02\x73\x33"
#else
    , "\x10\x80\x94\xeb\xdc\x03\x52\x13\x0a\x06\x6e\x75\x6d\x62\x65\x72\x10\x03\x39\x00\x00\x00\x00\x00\x00\xf0\x3f\x52\x2d\x0a\x07\x6e\x75\x6d\x62\x65\x72\x73\x10\x03\x1a\x05\x63\x6f\x75\x6e\x74\x39\x00\x00\x00\x00\x00\x00\xf0\x3f\x39\x00\x00\x00\x00\x00\x00\x00\x40\x39\x00\x00\x00\x00\x00\x00\x08\x40\x52\x0f\x0a\x05\x62\x6f\x6f\x6c\x73\x10\x04\x40\x01\x40\x00\x40\x00\x52\x0a\x0a\x04\x62\x6f\x6f\x6c\x10\x04\x40\x01\x52\x10\x0a\x06\x73\x74\x72\x69\x6e\x67\x22\x06\x73\x74\x72\x69\x6e\x67\x52\x15\x0a\x07\x73\x74\x72\x69\x6e\x67\x73\x22\x02\x73\x31\x22\x02\x73\x32\x22\x02\x73\x33"
#endif
    , "\x10\x80\x94\xeb\xdc\x03\x52\x8d\x01\x0a\x06\x73\x74\x72\x69\x6e\x67\x22\x82\x01\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39"
    , NULL
  };

  lua_sandbox* sb = lsb_create(NULL, "lua/output.lua", 100000,
                               1000, 63 * 1024);
  mu_assert(sb, "lsb_create() received: NULL");

  int result = lsb_init(sb, NULL);
  mu_assert(result == 0, "lsb_init() received: %d %s", result,
            lsb_get_error(sb));
  lsb_add_function(sb, &write_output, "write");

  for (int x = 0; outputs[x]; ++x) {
    result = process(sb, x);
    mu_assert(!result, "process() failed: %d %s", result, lsb_get_error(sb));
    if (outputs[x][0]) {
      if (outputs[x][0] == 0x10) {
        size_t header = 18;
        if (memcmp(outputs[x], written_data + header, written_data_len - header) != 0) {
          char hex_data[LSB_OUTPUT + 1];
          size_t z = 0;
          for (size_t y = header; y < written_data_len; ++y, z += 3) {
            snprintf(hex_data + z, LSB_OUTPUT - z, "%02x ", (unsigned char)written_data[y]);
          }
          hex_data[z] = 0;
          mu_assert(0, "test: %d received: %s", x, hex_data);
        }
      } else {
        mu_assert(strcmp(outputs[x], written_data) == 0, "test: %d received: %s",
                  x, written_data);
      }
    }
  }

  e = lsb_destroy(sb, "circular_buffer.preserve");
  mu_assert(!e, "lsb_destroy() received: %s", e);

  return NULL;
}