| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <limits.h> |
| |
| #include <ddk/binding.h> |
| #include <ddk/debug.h> |
| #include <ddk/device.h> |
| #include <ddk/driver.h> |
| #include <zxtest/zxtest.h> |
| |
| namespace { |
| |
| zx_device_t* ddk_test_dev; |
| |
| const char* TEST_STRING = "testing 1 2 3"; |
| |
| TEST(MetadataTest, AddMetadata) { |
| char buffer[32] = {}; |
| zx_status_t status; |
| size_t actual; |
| |
| status = device_get_metadata(ddk_test_dev, 1, buffer, sizeof(buffer), &actual); |
| ASSERT_EQ(status, ZX_ERR_NOT_FOUND, "device_get_metadata did not return ZX_ERR_NOT_FOUND"); |
| |
| status = device_get_metadata_size(ddk_test_dev, 1, &actual); |
| ASSERT_EQ(status, ZX_ERR_NOT_FOUND, "device_get_metadata_size should return ZX_ERR_NOT_FOUND"); |
| |
| status = device_add_metadata(ddk_test_dev, 1, TEST_STRING, strlen(TEST_STRING) + 1); |
| ASSERT_EQ(status, ZX_OK, "device_add_metadata failed"); |
| |
| status = device_get_metadata_size(ddk_test_dev, 1, &actual); |
| ASSERT_EQ(strlen(TEST_STRING) + 1, actual, "Incorrect output length was returned."); |
| status = device_get_metadata(ddk_test_dev, 1, buffer, sizeof(buffer), &actual); |
| ASSERT_EQ(status, ZX_OK, "device_get_metadata failed"); |
| ASSERT_EQ(actual, strlen(TEST_STRING) + 1, ""); |
| ASSERT_EQ(strcmp(buffer, TEST_STRING), 0, ""); |
| } |
| |
| TEST(MetadataTest, AddMetadataLargeInput) { |
| size_t large_len = 1024u * 16; |
| auto large = std::make_unique<char[]>(large_len); |
| zx_status_t status = device_add_metadata(ddk_test_dev, 1, large.get(), large_len); |
| EXPECT_EQ(status, ZX_ERR_INVALID_ARGS, "device_add_metadata shoud return ZX_ERR_INVALID_ARGS"); |
| } |
| |
| TEST(MetadataTest, PublishMetadata) { |
| char buffer[32] = {}; |
| zx_status_t status; |
| size_t actual; |
| |
| // This should fail since the path does not match us or our potential children. |
| status = device_publish_metadata(ddk_test_dev, "/dev/misc/null", 2, TEST_STRING, |
| strlen(TEST_STRING) + 1); |
| ASSERT_EQ(status, ZX_ERR_ACCESS_DENIED, ""); |
| |
| // We are allowed to add metadata to own path. |
| status = device_publish_metadata(ddk_test_dev, "/dev/test/test", 2, TEST_STRING, |
| strlen(TEST_STRING) + 1); |
| ASSERT_EQ(status, ZX_OK, ""); |
| |
| status = device_get_metadata(ddk_test_dev, 2, buffer, sizeof(buffer), &actual); |
| ASSERT_EQ(status, ZX_OK, "device_get_metadata failed"); |
| ASSERT_EQ(actual, strlen(TEST_STRING) + 1, ""); |
| ASSERT_EQ(strcmp(buffer, TEST_STRING), 0, ""); |
| |
| // We are allowed to add metadata to our potential children. |
| status = device_publish_metadata(ddk_test_dev, "/dev/test/test/child", 2, TEST_STRING, |
| strlen(TEST_STRING) + 1); |
| ASSERT_EQ(status, ZX_OK, ""); |
| } |
| |
| TEST(MetadataTest, PublishMetadataLargeInput) { |
| size_t large_len = 1024u * 16; |
| auto large = std::make_unique<char[]>(large_len); |
| zx_status_t status = |
| device_publish_metadata(ddk_test_dev, "/dev/test/test/child", 2, large.get(), large_len); |
| EXPECT_EQ(status, ZX_ERR_INVALID_ARGS, "device_add_metadata shoud return ZX_ERR_INVALID_ARGS"); |
| } |
| |
| TEST(MetadataTest, GetMetadataWouldOverflow) { |
| char buffer[32] = {}; |
| zx_status_t status; |
| size_t actual; |
| |
| status = device_publish_metadata(ddk_test_dev, "/dev/test/test", 2, TEST_STRING, |
| strlen(TEST_STRING) + 1); |
| ASSERT_EQ(status, ZX_OK, ""); |
| |
| status = device_get_metadata(ddk_test_dev, 2, buffer, 1, &actual); |
| ASSERT_EQ(status, ZX_ERR_BUFFER_TOO_SMALL, "device_get_metadata overflowed buffer"); |
| } |
| |
| // A special LogSink that just redirects all output to zxlogf |
| class LogSink : public zxtest::LogSink { |
| public: |
| void Write(const char* format, ...) override { |
| std::array<char, 1024> line_buf; |
| va_list args; |
| va_start(args, format); |
| vsnprintf(line_buf.data(), line_buf.size(), format, args); |
| va_end(args); |
| line_buf[line_buf.size() - 1] = 0; |
| zxlogf(INFO, "%s", line_buf.data()); |
| } |
| void Flush() override {} |
| }; |
| |
| zx_status_t metadata_test_bind(void* ctx, zx_device_t* parent) { |
| zxlogf(ERROR, "HERE IN BIND"); |
| zxtest::Runner::GetInstance()->mutable_reporter()->set_log_sink(std::make_unique<LogSink>()); |
| ddk_test_dev = parent; |
| if (RUN_ALL_TESTS(0, nullptr) != 0) { |
| return ZX_ERR_BAD_STATE; |
| } |
| return ZX_OK; |
| } |
| |
| static zx_driver_ops_t metadata_test_driver_ops = { |
| .version = DRIVER_OPS_VERSION, |
| .bind = metadata_test_bind, |
| }; |
| |
| } // namespace |
| |
| // clang-format off |
| ZIRCON_DRIVER_BEGIN(metadata_test, metadata_test_driver_ops, "zircon", "0.1", 2) |
| BI_ABORT_IF_AUTOBIND, |
| BI_MATCH(), |
| ZIRCON_DRIVER_END(metadata_test) |