text:
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/usb/cros_usb_detector.h"

#include <algorithm>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "ash/components/arc/arc_util.h"
#include "ash/constants/ash_switches.h"
#include "base/command_line.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/gmock_move_support.h"
#include "chrome/browser/ash/arc/arc_util.h"
#include "chrome/browser/ash/bruschetta/fake_bruschetta_features.h"
#include "chrome/browser/ash/crostini/crostini_manager.h"
#include "chrome/browser/ash/crostini/crostini_pref_names.h"
#include "chrome/browser/ash/crostini/crostini_test_helper.h"
#include "chrome/browser/ash/crostini/fake_crostini_features.h"
#include "chrome/browser/ash/guest_os/guest_id.h"
#include "chrome/browser/ash/plugin_vm/fake_plugin_vm_features.h"
#include "chrome/browser/ash/plugin_vm/plugin_vm_test_helper.h"
#include "chrome/browser/notifications/notification_display_service.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/browser/notifications/system_notification_helper.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/ash/components/dbus/chunneld/chunneld_client.h"
#include "chromeos/ash/components/dbus/cicerone/cicerone_client.h"
#include "chromeos/ash/components/dbus/cicerone/fake_cicerone_client.h"
#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
#include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h"
#include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
#include "chromeos/ash/components/dbus/vm_plugin_dispatcher/fake_vm_plugin_dispatcher_client.h"
#include "chromeos/ash/components/disks/disk.h"
#include "chromeos/ash/components/disks/disk_mount_manager.h"
#include "chromeos/ash/components/disks/mock_disk_mount_manager.h"
#include "services/device/public/cpp/test/fake_usb_device_info.h"
#include "services/device/public/cpp/test/fake_usb_device_manager.h"
#include "services/device/public/mojom/usb_device.mojom.h"
#include "services/device/public/mojom/usb_manager.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/message_center/public/cpp/notification.h"
#include "url/gurl.h"

namespace ash {

namespace {

using testing::_;
using MountCallback = ::base::OnceCallback<void(MountError)>;

const char* kProfileName = "test@example.com";
const char* kCrostiniTestContainerName = "test-container";

// USB device product name.
const char* kProductName_1 = "Google Product A";
const char* kProductName_2 = "Google Product B";
const char* kProductName_3 = "Google Product C";
const char* kUnknownProductName = "USB device";
const char* kManufacturerName = "Google";

const int kUsbConfigWithInterfaces = 1;

struct InterfaceCodes {
  InterfaceCodes(uint8_t device_class,
                 uint8_t subclass_code,
                 uint8_t protocol_code)
      : device_class(device_class),
        subclass_code(subclass_code),
        protocol_code(protocol_code) {}
  uint8_t device_class;
  uint8_t subclass_code;
  uint8_t protocol_code;
};

scoped_refptr<device::FakeUsbDeviceInfo> CreateTestDeviceFromCodes(
    uint8_t device_class,
    const std::vector<InterfaceCodes>& interface_codes) {
  auto config = device::mojom::UsbConfigurationInfo::New();
  config->configuration_value = kUsbConfigWithInterfaces;
  // The usb_utils do not filter by device class, only by configurations, and
  // the FakeUsbDeviceInfo does not set up configurations for a fake device's
  // class code. This helper sets up a configuration to match a devices class
  // code so that USB devices can be filtered out.
  for (size_t i = 0; i < interface_codes.size(); ++i) {
    auto alternate = device::mojom::UsbAlternateInterfaceInfo::New();
    alternate->alternate_setting = 0;
    alternate->class_code = interface_codes[i].device_class;
    alternate->subclass_code = interface_codes[i].subclass_code;
    alternate->protocol_code = interface_codes[i].protocol_code;

    auto interface = device::mojom::UsbInterfaceInfo::New();
    interface->interface_number = i;
    interface->alternates.push_back(std::move(alternate));

    config->interfaces.push_back(std::move(interface));
  }

  std::vector<device::mojom::UsbConfigurationInfoPtr> configs;
  configs.push_back(std::move(config));

  scoped_refptr<device::FakeUsbDeviceInfo> device =
      new device::FakeUsbDeviceInfo(/*vendor_id*/ 0, /*product_id*/ 1,
                                    device_class, std::move(configs));
  device->SetActiveConfig(kUsbConfigWithInterfaces);
  return device;
}

scoped_refptr<device::FakeUsbDeviceInfo> CreateTestDeviceOfClass(
    uint8_t device_class) {
  return CreateTestDeviceFromCodes(device_class,
                                   {InterfaceCodes(device_class, 0xff, 0xff)});
}

class TestCrosUsbDeviceObserver : public CrosUsbDeviceObserver {
 public:
  void OnUsbDevicesChanged() override { ++notify_count_; }

  int notify_count() const { return notify_count_; }

 private:
  int notify_count_ = 0;
};

}  // namespace

class CrosUsbDetectorTest : public BrowserWithTestWindowTest {
 public:
  CrosUsbDetectorTest() {
    // Needed for GuestOsStabilityMonitor.
    ChunneldClient::InitializeFake();
    ash::CiceroneClient::InitializeFake();
    ConciergeClient::InitializeFake();
    SeneschalClient::InitializeFake();
    VmPluginDispatcherClient::InitializeFake();
    fake_cicerone_client_ = ash::FakeCiceroneClient::Get();
    fake_concierge_client_ = FakeConciergeClient::Get();
    fake_vm_plugin_dispatcher_client_ =
        static_cast<FakeVmPluginDispatcherClient*>(
            VmPluginDispatcherClient::Get());

    mock_disk_mount_manager_ =
        new testing::NiceMock<disks::MockDiskMountManager>;
    disks::DiskMountManager::InitializeForTesting(mock_disk_mount_manager_);
  }

  CrosUsbDetectorTest(const CrosUsbDetectorTest&) = delete;
  CrosUsbDetectorTest& operator=(const CrosUsbDetectorTest&) = delete;

  ~CrosUsbDetectorTest() override {
    disks::DiskMountManager::Shutdown();
    VmPluginDispatcherClient::Shutdown();
    SeneschalClient::Shutdown();
    ConciergeClient::Shutdown();
    ash::CiceroneClient::Shutdown();
    ChunneldClient::Shutdown();
  }

  TestingProfile* CreateProfile() override {
    return profile_manager()->CreateTestingProfile(kProfileName);
  }

  void SetUp() override {
    cros_usb_detector_ = std::make_unique<CrosUsbDetector>();
    BrowserWithTestWindowTest::SetUp();
    crostini_test_helper_ =
        std::make_unique<crostini::CrostiniTestHelper>(profile());

    TestingBrowserProcess::GetGlobal()->SetSystemNotificationHelper(
        std::make_unique<SystemNotificationHelper>());
    display_service_ = std::make_unique<NotificationDisplayServiceTester>(
        nullptr /* profile */);

    // Set a fake USB device manager before ConnectToDeviceManager().
    mojo::PendingRemote<device::mojom::UsbDeviceManager> device_manager;
    device_manager_.AddReceiver(
        device_manager.InitWithNewPipeAndPassReceiver());
    CrosUsbDetector::Get()->SetDeviceManagerForTesting(
        std::move(device_manager));
    // Create a default VM instance which is running.
    crostini::CrostiniManager::GetForProfile(profile())->AddRunningVmForTesting(
        crostini::kCrostiniDefaultVmName);
  }

  void TearDown() override {
    crostini_test_helper_.reset();
    BrowserWithTestWindowTest::TearDown();
    cros_usb_detector_.reset();
  }

  void ConnectToDeviceManager() {
    CrosUsbDetector::Get()->ConnectToDeviceManager();
  }

  MOCK_METHOD1(OnAttach, void(bool success));

  void AttachDeviceToGuest(const guest_os::GuestId& guest_id,
                           const std::string& guid,
                           bool vm_success = true,
                           bool container_success = true) {
    absl::optional<vm_tools::concierge::AttachUsbDeviceResponse> response;
    response.emplace();
    response->set_success(vm_success);
    response->set_guest_port(0);
    fake_concierge_client_->set_attach_usb_device_response(response);

    if (vm_success && !guest_id.container_name.empty()) {
      vm_tools::cicerone::AttachUsbToContainerResponse response;
      response.set_status(
          container_success
              ? vm_tools::cicerone::AttachUsbToContainerResponse_Status_OK
              : vm_tools::cicerone::AttachUsbToContainerResponse_Status_FAILED);
      if (!container_success) {
        response.set_failure_reason("Expected failure");
      }
      fake_cicerone_client_->set_attach_usb_to_container_response(
          std::move(response));

      EXPECT_CALL(*this, OnAttach(container_success));
    } else {
      EXPECT_CALL(*this, OnAttach(vm_success));
    }

    cros_usb_detector_->AttachUsbDeviceToGuest(
        guest_id, guid,
        base::BindOnce(&CrosUsbDetectorTest::OnAttach, base::Unretained(this)));
    base::RunLoop().RunUntilIdle();
  }

  void DetachDeviceFromVm(const std::string& vm_name,
                          const std::string& guid,
                          bool expected_success) {
    cros_usb_detector_->DetachUsbDeviceFromVm(
        vm_name, guid,
        base::BindOnce(
            [](bool expected, bool actual) { EXPECT_EQ(expected, actual); },
            expected_success));
    base::RunLoop().RunUntilIdle();
  }

  // The GetSingle..() functions expect only one device is present and may crash
  // if there are no devices (we can't use ASSERT_EQ as they return values).

  CrosUsbDeviceInfo GetSingleDeviceInfo() const {
    auto devices = cros_usb_detector_->GetShareableDevices();
    EXPECT_EQ(1U, devices.size());
    return devices.front();
  }

  absl::optional<uint8_t> GetSingleGuestPort() const {
    EXPECT_EQ(1U, cros_usb_detector_->usb_devices_.size());
    return cros_usb_detector_->usb_devices_.begin()->second.guest_port;
  }

  uint32_t GetSingleAllowedInterfacesMask() const {
    EXPECT_EQ(1U, cros_usb_detector_->usb_devices_.size());
    return cros_usb_detector_->usb_devices_.begin()
        ->second.allowed_interfaces_mask;
  }

  void AddDisk(const std::string& name,
               int bus_number,
               int device_number,
               bool mounted) {
    mock_disk_mount_manager_->CreateDiskEntryForMountDevice(
        disks::Disk::Builder()
            .SetBusNumber(bus_number)
            .SetDeviceNumber(device_number)
            .SetDevicePath("/dev/" + name)
            .SetMountPath("/mount/" + name)
            .SetIsMounted(mounted)
            .Build());
    if (mounted)
      NotifyMountEvent(name, disks::DiskMountManager::MOUNTING);
  }

  void NotifyMountEvent(const std::string& name,
                        disks::DiskMountManager::MountEvent event,
                        MountError mount_error = MountError::kNone) {
    // In theory we should also clear the mounted flag from the disk, but we
    // don't rely on that.
    disks::DiskMountManager::MountPoint info{"/dev/" + name, "/mount/" + name,
                                             MountType::kDevice};
    mock_disk_mount_manager_->NotifyMountEvent(event, mount_error, info);
  }

 protected:
  std::u16string connection_message(const char* product_name) {
    return base::ASCIIToUTF16(base::StringPrintf(
        "Open Settings to connect %s to Linux", product_name));
  }

  std::u16string expected_title() { return u"USB device detected"; }

  device::FakeUsbDeviceManager device_manager_;
  std::unique_ptr<NotificationDisplayServiceTester> display_service_;
  disks::MockDiskMountManager* mock_disk_mount_manager_;
  disks::DiskMountManager::Disks disks_;

  ash::FakeCiceroneClient* fake_cicerone_client_;
  FakeConciergeClient* fake_concierge_client_;
  FakeVmPluginDispatcherClient* fake_vm_plugin_dispatcher_client_;

  TestCrosUsbDeviceObserver usb_device_observer_;
  std::unique_ptr<CrosUsbDetector> cros_usb_detector_;

  std::unique_ptr<crostini::CrostiniTestHelper> crostini_test_helper_;
};

TEST_F(CrosUsbDetectorTest, UsbDeviceAddedAndRemoved) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();

  std::string notification_id =
      CrosUsbDetector::MakeNotificationId(device->guid());

  absl::optional<message_center::Notification> notification =
      display_service_->GetNotification(notification_id);
  ASSERT_TRUE(notification);

  EXPECT_EQ(expected_title(), notification->title());
  EXPECT_EQ(connection_message(kProductName_1), notification->message());
  EXPECT_TRUE(notification->delegate());

  device_manager_.RemoveDevice(device);
  base::RunLoop().RunUntilIdle();
  // Device is removed, so notification should be removed too.
  EXPECT_FALSE(display_service_->GetNotification(notification_id));
}

TEST_F(CrosUsbDetectorTest, NotificationShown) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  std::string notification_id =
      CrosUsbDetector::MakeNotificationId(device->guid());

  // Notifications should not be shown if no VMs enabled.
  crostini::FakeCrostiniFeatures crostini_features;
  crostini_features.set_enabled(false);
  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();

  absl::optional<message_center::Notification> notification =
      display_service_->GetNotification(notification_id);
  EXPECT_FALSE(notification);
  device_manager_.RemoveDevice(device);
  base::RunLoop().RunUntilIdle();

  // Notification should have 1 button when only crostini is enabled.
  crostini_features.set_enabled(true);
  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();
  notification = display_service_->GetNotification(notification_id);
  ASSERT_TRUE(notification);
  EXPECT_EQ(notification->buttons().size(), 1u);
  device_manager_.RemoveDevice(device);
  base::RunLoop().RunUntilIdle();

  // Should have 2 buttons when Plugin VM is enabled.
  plugin_vm::FakePluginVmFeatures plugin_vm_features;
  plugin_vm_features.set_enabled(true);
  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();
  notification = display_service_->GetNotification(notification_id);
  ASSERT_TRUE(notification);
  EXPECT_EQ(notification->buttons().size(), 2u);
  device_manager_.RemoveDevice(device);
  base::RunLoop().RunUntilIdle();

  // Should have 2 buttions when ARCVM is enabled but user disables ARC.
  // ARC is disabled by default in test.
  arc::ResetArcAllowedCheckForTesting(profile());
  auto* command_line = base::CommandLine::ForCurrentProcess();
  command_line->InitFromArgv(
      {"", "--enable-arcvm", "--arc-availability=officially-supported"});
  EXPECT_TRUE(arc::IsArcVmEnabled());
  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();
  notification = display_service_->GetNotification(notification_id);
  ASSERT_TRUE(notification);
  EXPECT_EQ(notification->buttons().size(), 2u);
  device_manager_.RemoveDevice(device);
  base::RunLoop().RunUntilIdle();

  // Should have 3 buttions when ARCVM is enabled and user enables ARC but the
  // feature is disabled.
  ASSERT_TRUE(arc::SetArcPlayStoreEnabledForProfile(profile(), true));
  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();
  notification = display_service_->GetNotification(notification_id);
  ASSERT_TRUE(notification);
  EXPECT_EQ(notification->buttons().size(), 3u);
  device_manager_.RemoveDevice(device);
  base::RunLoop().RunUntilIdle();

  // Now should have 4 buttons when Bruschetta is enabled.
  bruschetta::FakeBruschettaFeatures bruschetta_features;
  bruschetta_features.set_enabled(true);
  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();
  notification = display_service_->GetNotification(notification_id);
  ASSERT_TRUE(notification);
  EXPECT_EQ(notification->buttons().size(), 4u);
  device_manager_.RemoveDevice(device);
  base::RunLoop().RunUntilIdle();
}

TEST_F(CrosUsbDetectorTest, UsbNotificationClicked) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();

  std::string notification_id =
      CrosUsbDetector::MakeNotificationId(device->guid());

  absl::optional<message_center::Notification> notification =
      display_service_->GetNotification(notification_id);
  ASSERT_TRUE(notification);

  notification->delegate()->Click(0, absl::nullopt);
  base::RunLoop().RunUntilIdle();

  EXPECT_GE(fake_concierge_client_->attach_usb_device_call_count(), 1);
  // Notification should close.
  EXPECT_FALSE(display_service_->GetNotification(notification_id));
}

TEST_F(CrosUsbDetectorTest, UsbDeviceClassBlockedAdded) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  scoped_refptr<device::FakeUsbDeviceInfo> device =
      CreateTestDeviceOfClass(/* USB_CLASS_HUB */ 0x09);

  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();

  std::string notification_id =
      CrosUsbDetector::MakeNotificationId(device->guid());
  ASSERT_FALSE(display_service_->GetNotification(notification_id));
  EXPECT_EQ(0U, cros_usb_detector_->GetShareableDevices().size());
}

TEST_F(CrosUsbDetectorTest, UsbDeviceClassAdbAdded) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  const int kAdbClass = 0xff;
  const int kAdbSubclass = 0x42;
  const int kAdbProtocol = 0x1;
  // Adb interface as well as a forbidden interface
  scoped_refptr<device::FakeUsbDeviceInfo> device = CreateTestDeviceFromCodes(
      /* USB_CLASS_HID */ 0x03,
      {InterfaceCodes(kAdbClass, kAdbSubclass, kAdbProtocol),
       InterfaceCodes(0x03, 0xff, 0xff)});

  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();

  std::string notification_id =
      CrosUsbDetector::MakeNotificationId(device->guid());
  ASSERT_TRUE(display_service_->GetNotification(notification_id));
  // ADB interface wins.
  EXPECT_EQ(1U, cros_usb_detector_->GetShareableDevices().size());
}

TEST_F(CrosUsbDetectorTest, UsbDeviceClassWithoutNotificationAdded) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  scoped_refptr<device::FakeUsbDeviceInfo> device =
      CreateTestDeviceOfClass(/* USB_CLASS_AUDIO */ 0x01);

  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();

  std::string notification_id =
      CrosUsbDetector::MakeNotificationId(device->guid());
  ASSERT_FALSE(display_service_->GetNotification(notification_id));
  EXPECT_EQ(1U, cros_usb_detector_->GetShareableDevices().size());
}

TEST_F(CrosUsbDetectorTest, UsbDeviceWithoutProductNameAddedAndRemoved) {
  std::string product_name;
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, product_name, "002");
  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();

  std::string notification_id =
      CrosUsbDetector::MakeNotificationId(device->guid());

  absl::optional<message_center::Notification> notification =
      display_service_->GetNotification(notification_id);
  ASSERT_TRUE(notification);

  EXPECT_EQ(expected_title(), notification->title());
  EXPECT_EQ(connection_message("USB device from Google"),
            notification->message());
  EXPECT_TRUE(notification->delegate());

  device_manager_.RemoveDevice(device);
  base::RunLoop().RunUntilIdle();
  // Device is removed, so notification should be removed too.
  EXPECT_FALSE(display_service_->GetNotification(notification_id));
}

TEST_F(CrosUsbDetectorTest,
       UsbDeviceWithoutProductNameOrManufacturerNameAddedAndRemoved) {
  std::string product_name;
  std::string manufacturer_name;
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, manufacturer_name, product_name, "002");
  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();

  std::string notification_id =
      CrosUsbDetector::MakeNotificationId(device->guid());

  absl::optional<message_center::Notification> notification =
      display_service_->GetNotification(notification_id);
  ASSERT_TRUE(notification);
  EXPECT_EQ(expected_title(), notification->title());
  EXPECT_EQ(connection_message(kUnknownProductName), notification->message());
  EXPECT_TRUE(notification->delegate());

  device_manager_.RemoveDevice(device);
  base::RunLoop().RunUntilIdle();
  // Device is removed, so notification should be removed too.
  EXPECT_FALSE(display_service_->GetNotification(notification_id));
}

TEST_F(CrosUsbDetectorTest, UsbDeviceWasThereBeforeAndThenRemoved) {
  // USB device was added before cros_usb_detector was created.
  auto device = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();

  std::string notification_id =
      CrosUsbDetector::MakeNotificationId(device->guid());

  EXPECT_FALSE(display_service_->GetNotification(notification_id));

  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  device_manager_.RemoveDevice(device);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id));
}

TEST_F(
    CrosUsbDetectorTest,
    ThreeUsbDevicesWereThereBeforeAndThenRemovedBeforeUsbDetectorWasCreated) {
  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  std::string notification_id_1 =
      CrosUsbDetector::MakeNotificationId(device_1->guid());

  auto device_2 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      3, 4, kManufacturerName, kProductName_2, "005");
  std::string notification_id_2 =
      CrosUsbDetector::MakeNotificationId(device_2->guid());

  auto device_3 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      6, 7, kManufacturerName, kProductName_3, "008");
  std::string notification_id_3 =
      CrosUsbDetector::MakeNotificationId(device_3->guid());

  // Three usb devices were added and removed before cros_usb_detector was
  // created.
  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_1));

  device_manager_.AddDevice(device_2);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_2));

  device_manager_.AddDevice(device_3);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_3));

  device_manager_.RemoveDevice(device_1);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_1));

  device_manager_.RemoveDevice(device_2);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_2));

  device_manager_.RemoveDevice(device_3);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_3));

  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
  EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
  EXPECT_FALSE(display_service_->GetNotification(notification_id_3));
}

TEST_F(CrosUsbDetectorTest,
       ThreeUsbDevicesWereThereBeforeAndThenRemovedAfterUsbDetectorWasCreated) {
  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  std::string notification_id_1 =
      CrosUsbDetector::MakeNotificationId(device_1->guid());

  auto device_2 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      3, 4, kManufacturerName, kProductName_2, "005");
  std::string notification_id_2 =
      CrosUsbDetector::MakeNotificationId(device_2->guid());

  auto device_3 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      6, 7, kManufacturerName, kProductName_3, "008");
  std::string notification_id_3 =
      CrosUsbDetector::MakeNotificationId(device_3->guid());

  // Three usb devices were added before cros_usb_detector was created.
  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_1));

  device_manager_.AddDevice(device_2);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_2));

  device_manager_.AddDevice(device_3);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_3));

  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
  EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
  EXPECT_FALSE(display_service_->GetNotification(notification_id_3));

  device_manager_.RemoveDevice(device_1);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_1));

  device_manager_.RemoveDevice(device_2);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_2));

  device_manager_.RemoveDevice(device_3);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_3));
}

TEST_F(CrosUsbDetectorTest,
       TwoUsbDevicesWereThereBeforeAndThenRemovedAndNewUsbDeviceAdded) {
  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  std::string notification_id_1 =
      CrosUsbDetector::MakeNotificationId(device_1->guid());

  auto device_2 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      3, 4, kManufacturerName, kProductName_2, "005");
  std::string notification_id_2 =
      CrosUsbDetector::MakeNotificationId(device_2->guid());

  // Two usb devices were added before cros_usb_detector was created.
  device_manager_.AddDevice(device_1);
  device_manager_.AddDevice(device_2);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
  EXPECT_FALSE(display_service_->GetNotification(notification_id_2));

  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
  EXPECT_FALSE(display_service_->GetNotification(notification_id_2));

  device_manager_.RemoveDevice(device_1);
  device_manager_.RemoveDevice(device_2);
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
  EXPECT_FALSE(display_service_->GetNotification(notification_id_2));

  device_manager_.AddDevice(device_2);
  base::RunLoop().RunUntilIdle();
  absl::optional<message_center::Notification> notification =
      display_service_->GetNotification(notification_id_2);
  ASSERT_TRUE(notification);

  EXPECT_EQ(expected_title(), notification->title());
  EXPECT_EQ(connection_message(kProductName_2), notification->message());
  EXPECT_TRUE(notification->delegate());

  device_manager_.RemoveDevice(device_2);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
}

TEST_F(CrosUsbDetectorTest, ThreeUsbDevicesAddedAndRemoved) {
  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  std::string notification_id_1 =
      CrosUsbDetector::MakeNotificationId(device_1->guid());

  auto device_2 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      3, 4, kManufacturerName, kProductName_2, "005");
  std::string notification_id_2 =
      CrosUsbDetector::MakeNotificationId(device_2->guid());

  auto device_3 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      6, 7, kManufacturerName, kProductName_3, "008");
  std::string notification_id_3 =
      CrosUsbDetector::MakeNotificationId(device_3->guid());

  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();
  absl::optional<message_center::Notification> notification_1 =
      display_service_->GetNotification(notification_id_1);
  ASSERT_TRUE(notification_1);

  EXPECT_EQ(expected_title(), notification_1->title());
  EXPECT_EQ(connection_message(kProductName_1), notification_1->message());
  EXPECT_TRUE(notification_1->delegate());

  device_manager_.RemoveDevice(device_1);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_1));

  device_manager_.AddDevice(device_2);
  base::RunLoop().RunUntilIdle();
  absl::optional<message_center::Notification> notification_2 =
      display_service_->GetNotification(notification_id_2);
  ASSERT_TRUE(notification_2);

  EXPECT_EQ(expected_title(), notification_2->title());
  EXPECT_EQ(connection_message(kProductName_2), notification_2->message());
  EXPECT_TRUE(notification_2->delegate());

  device_manager_.RemoveDevice(device_2);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_2));

  device_manager_.AddDevice(device_3);
  base::RunLoop().RunUntilIdle();
  absl::optional<message_center::Notification> notification_3 =
      display_service_->GetNotification(notification_id_3);
  ASSERT_TRUE(notification_3);

  EXPECT_EQ(expected_title(), notification_3->title());
  EXPECT_EQ(connection_message(kProductName_3), notification_3->message());
  EXPECT_TRUE(notification_3->delegate());

  device_manager_.RemoveDevice(device_3);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_3));
}

TEST_F(CrosUsbDetectorTest, ThreeUsbDeviceAddedAndRemovedDifferentOrder) {
  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  std::string notification_id_1 =
      CrosUsbDetector::MakeNotificationId(device_1->guid());

  auto device_2 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      3, 4, kManufacturerName, kProductName_2, "005");
  std::string notification_id_2 =
      CrosUsbDetector::MakeNotificationId(device_2->guid());

  auto device_3 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      6, 7, kManufacturerName, kProductName_3, "008");
  std::string notification_id_3 =
      CrosUsbDetector::MakeNotificationId(device_3->guid());

  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();
  absl::optional<message_center::Notification> notification_1 =
      display_service_->GetNotification(notification_id_1);
  ASSERT_TRUE(notification_1);

  EXPECT_EQ(expected_title(), notification_1->title());
  EXPECT_EQ(connection_message(kProductName_1), notification_1->message());
  EXPECT_TRUE(notification_1->delegate());

  device_manager_.AddDevice(device_2);
  base::RunLoop().RunUntilIdle();
  absl::optional<message_center::Notification> notification_2 =
      display_service_->GetNotification(notification_id_2);
  ASSERT_TRUE(notification_2);

  EXPECT_EQ(expected_title(), notification_2->title());
  EXPECT_EQ(connection_message(kProductName_2), notification_2->message());
  EXPECT_TRUE(notification_2->delegate());

  device_manager_.RemoveDevice(device_2);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_2));

  device_manager_.AddDevice(device_3);
  base::RunLoop().RunUntilIdle();
  absl::optional<message_center::Notification> notification_3 =
      display_service_->GetNotification(notification_id_3);
  ASSERT_TRUE(notification_3);

  EXPECT_EQ(expected_title(), notification_3->title());
  EXPECT_EQ(connection_message(kProductName_3), notification_3->message());
  EXPECT_TRUE(notification_3->delegate());

  device_manager_.RemoveDevice(device_1);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_1));

  device_manager_.RemoveDevice(device_3);
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(display_service_->GetNotification(notification_id_3));
}

TEST_F(CrosUsbDetectorTest, AttachDeviceToVmSetsGuestPort) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();

  auto device_info = GetSingleDeviceInfo();
  EXPECT_FALSE(GetSingleGuestPort().has_value());
  AttachDeviceToGuest(guest_os::GuestId(crostini::kCrostiniDefaultVmName, ""),
                      device_info.guid);

  device_info = GetSingleDeviceInfo();
  EXPECT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ(crostini::kCrostiniDefaultVmName,
            device_info.shared_guest_id->vm_name);
  EXPECT_TRUE(GetSingleGuestPort().has_value());
  EXPECT_EQ(0U, *GetSingleGuestPort());
}

TEST_F(CrosUsbDetectorTest, AttachingAlreadyAttachedDeviceIsANoOp) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();

  auto device_info = GetSingleDeviceInfo();
  EXPECT_FALSE(device_info.shared_guest_id.has_value());

  AttachDeviceToGuest(guest_os::GuestId(crostini::kCrostiniDefaultVmName, ""),
                      device_info.guid);
  cros_usb_detector_->AddUsbDeviceObserver(&usb_device_observer_);
  AttachDeviceToGuest(guest_os::GuestId(crostini::kCrostiniDefaultVmName, ""),
                      device_info.guid);
  EXPECT_EQ(0, usb_device_observer_.notify_count());
  device_info = GetSingleDeviceInfo();
  EXPECT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ(crostini::kCrostiniDefaultVmName,
            device_info.shared_guest_id->vm_name);
}

TEST_F(CrosUsbDetectorTest, DeviceCanBeAttachedToArcVmWhenCrostiniIsDisabled) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();

  auto device_info = GetSingleDeviceInfo();
  AttachDeviceToGuest(guest_os::GuestId(arc::kArcVmName, ""), device_info.guid);
  base::RunLoop().RunUntilIdle();
  device_info = GetSingleDeviceInfo();
  EXPECT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ(arc::kArcVmName, device_info.shared_guest_id->vm_name);
}

TEST_F(CrosUsbDetectorTest, SharedDevicesGetAttachedOnStartup) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();

  cros_usb_detector_->ConnectSharedDevicesOnVmStartup(
      crostini::kCrostiniDefaultVmName);
  base::RunLoop().RunUntilIdle();
  // No device is shared with Crostini, yet.
  EXPECT_EQ(0, usb_device_observer_.notify_count());
  auto device_info = GetSingleDeviceInfo();
  EXPECT_FALSE(device_info.shared_guest_id.has_value());

  AttachDeviceToGuest(guest_os::GuestId(crostini::kCrostiniDefaultVmName, ""),
                      device_info.guid);
  base::RunLoop().RunUntilIdle();
  device_info = GetSingleDeviceInfo();
  EXPECT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ(crostini::kCrostiniDefaultVmName,
            device_info.shared_guest_id->vm_name);

  // Concierge::VmStarted signal should trigger connections.
  cros_usb_detector_->AddUsbDeviceObserver(&usb_device_observer_);
  vm_tools::concierge::VmStartedSignal vm_started_signal;
  vm_started_signal.set_name(crostini::kCrostiniDefaultVmName);
  fake_concierge_client_->NotifyVmStarted(vm_started_signal);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(1, usb_device_observer_.notify_count());
  device_info = GetSingleDeviceInfo();
  EXPECT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ(crostini::kCrostiniDefaultVmName,
            device_info.shared_guest_id->vm_name);

  // VmPluginDispatcherClient::OnVmStateChanged RUNNING should also trigger.
  vm_tools::plugin_dispatcher::VmStateChangedSignal vm_state_changed_signal;
  vm_state_changed_signal.set_vm_name(crostini::kCrostiniDefaultVmName);
  vm_state_changed_signal.set_vm_state(
      vm_tools::plugin_dispatcher::VmState::VM_STATE_RUNNING);
  fake_vm_plugin_dispatcher_client_->NotifyVmStateChanged(
      vm_state_changed_signal);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(2, usb_device_observer_.notify_count());
  device_info = GetSingleDeviceInfo();
  EXPECT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ(crostini::kCrostiniDefaultVmName,
            device_info.shared_guest_id->vm_name);
}

TEST_F(CrosUsbDetectorTest, DeviceAllowedInterfacesMaskSetCorrectly) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  const int kAdbClass = 0xff;
  const int kAdbSubclass = 0x42;
  const int kAdbProtocol = 0x1;

  // Adb interface as well as a forbidden interface and allowed interface.
  scoped_refptr<device::FakeUsbDeviceInfo> device = CreateTestDeviceFromCodes(
      /* USB_CLASS_HUB */ 0x09,
      {InterfaceCodes(0x03, 0xff, 0xff),
       InterfaceCodes(kAdbClass, kAdbSubclass, kAdbProtocol),
       InterfaceCodes(/*USB_CLASS_AUDIO*/ 0x01, 0xff, 0xff)});

  device_manager_.AddDevice(device);
  base::RunLoop().RunUntilIdle();

  // The device should notify because it has an allowed, notifiable interface.
  std::string notification_id =
      CrosUsbDetector::MakeNotificationId(device->guid());
  EXPECT_TRUE(display_service_->GetNotification(notification_id));

  EXPECT_EQ(0x00000007U, GetSingleAllowedInterfacesMask());
}

TEST_F(CrosUsbDetectorTest, SwitchDeviceWithAttachSuccess) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();

  auto device_info = GetSingleDeviceInfo();
  EXPECT_FALSE(device_info.shared_guest_id.has_value());

  AttachDeviceToGuest(guest_os::GuestId("VM1", ""), device_info.guid,
                      /*vm_success=*/false);
  device_info = GetSingleDeviceInfo();
  ASSERT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ("VM1", device_info.shared_guest_id->vm_name);

  // Shared but not attached to VM1 -> attached to VM2
  AttachDeviceToGuest(guest_os::GuestId("VM2", ""), device_info.guid);
  device_info = GetSingleDeviceInfo();
  ASSERT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ("VM2", device_info.shared_guest_id->vm_name);
  EXPECT_EQ(fake_concierge_client_->detach_usb_device_call_count(), 0);

  // Attached to VM2 -> attached to VM3
  AttachDeviceToGuest(guest_os::GuestId("VM3", ""), device_info.guid);
  device_info = GetSingleDeviceInfo();
  ASSERT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ("VM3", device_info.shared_guest_id->vm_name);
  EXPECT_GE(fake_concierge_client_->detach_usb_device_call_count(), 1);
}

TEST_F(CrosUsbDetectorTest, SwitchDeviceWithAttachFailure) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();

  auto device_info = GetSingleDeviceInfo();
  EXPECT_FALSE(device_info.shared_guest_id.has_value());

  AttachDeviceToGuest(guest_os::GuestId("VM1", ""), device_info.guid);
  device_info = GetSingleDeviceInfo();
  EXPECT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ("VM1", device_info.shared_guest_id->vm_name);

  // Attached to VM1 -> shared but not attached to VM2
  AttachDeviceToGuest(guest_os::GuestId("VM2", ""), device_info.guid,
                      /*vm_success=*/false);
  device_info = GetSingleDeviceInfo();
  EXPECT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ("VM2", device_info.shared_guest_id->vm_name);
  EXPECT_GE(fake_concierge_client_->detach_usb_device_call_count(), 1);

  // Shared but not attached to VM2 -> shared but not attached to VM3
  AttachDeviceToGuest(guest_os::GuestId("VM3", ""), device_info.guid,
                      /*vm_success=*/false);
  device_info = GetSingleDeviceInfo();
  EXPECT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ("VM3", device_info.shared_guest_id->vm_name);
}

TEST_F(CrosUsbDetectorTest, DetachFromDifferentVM) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();

  auto device_info = GetSingleDeviceInfo();
  EXPECT_FALSE(device_info.shared_guest_id.has_value());

  AttachDeviceToGuest(guest_os::GuestId("VM1", ""), device_info.guid);
  device_info = GetSingleDeviceInfo();
  EXPECT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ("VM1", device_info.shared_guest_id->vm_name);

  // Device is not attached to VM2, so this will no-op.
  DetachDeviceFromVm("VM2", device_info.guid, /*expected_success=*/false);
  EXPECT_EQ(fake_concierge_client_->detach_usb_device_call_count(), 0);
  EXPECT_EQ("VM1", device_info.shared_guest_id->vm_name);
}

TEST_F(CrosUsbDetectorTest, AttachUnmountFilesystemSuccess) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  device_manager_.CreateAndAddDevice(
      0x0200, 0xff, 0xff, 0xff, 0x0100, 1, 2, /*bus_number=*/3,
      /*port_number=*/4, kManufacturerName, kProductName_1, "5");
  base::RunLoop().RunUntilIdle();

  AddDisk("disk1", 3, 4, true);
  AddDisk("disk2", 3, 4, /*mounted=*/false);
  NotifyMountEvent("disk2", disks::DiskMountManager::MOUNTING,
                   MountError::kInternal);
  AddDisk("disk3", 3, 5, true);
  AddDisk("disk4", 3, 4, true);
  AddDisk("disk5", 2, 4, true);
  MountCallback callback1;
  MountCallback callback4;
  EXPECT_CALL(*mock_disk_mount_manager_, UnmountPath("/mount/disk1", _))
      .WillOnce(MoveArg<1>(&callback1));
  EXPECT_CALL(*mock_disk_mount_manager_, UnmountPath("/mount/disk4", _))
      .WillOnce(MoveArg<1>(&callback4));

  auto device_info = GetSingleDeviceInfo();
  AttachDeviceToGuest(guest_os::GuestId("VM1", ""), device_info.guid);
  EXPECT_EQ(fake_concierge_client_->attach_usb_device_call_count(), 0);

  // Unmount events would normally be fired by the DiskMountManager.
  NotifyMountEvent("disk1", disks::DiskMountManager::UNMOUNTING);
  std::move(callback1).Run(MountError::kNone);
  base::RunLoop().RunUntilIdle();

  device_info = GetSingleDeviceInfo();
  EXPECT_FALSE(device_info.shared_guest_id.has_value());
  EXPECT_EQ(fake_concierge_client_->attach_usb_device_call_count(), 0);

  // All unmounts must complete before sharing succeeds.
  NotifyMountEvent("disk4", disks::DiskMountManager::UNMOUNTING);
  std::move(callback4).Run(MountError::kNone);
  base::RunLoop().RunUntilIdle();

  device_info = GetSingleDeviceInfo();
  EXPECT_GE(fake_concierge_client_->attach_usb_device_call_count(), 1);
  EXPECT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ("VM1", device_info.shared_guest_id->vm_name);
}

TEST_F(CrosUsbDetectorTest, AttachUnmountFilesystemFailure) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  device_manager_.CreateAndAddDevice(
      0x0200, 0xff, 0xff, 0xff, 0x0100, 1, 2, /*bus_number=*/1,
      /*port_number=*/5, kManufacturerName, kProductName_1, "5");
  base::RunLoop().RunUntilIdle();

  AddDisk("disk1", 1, 5, true);
  AddDisk("disk2", 1, 5, true);
  AddDisk("disk3", 1, 5, true);
  MountCallback callback1;
  MountCallback callback2;
  MountCallback callback3;
  EXPECT_CALL(*mock_disk_mount_manager_, UnmountPath("/mount/disk1", _))
      .WillOnce(MoveArg<1>(&callback1));
  EXPECT_CALL(*mock_disk_mount_manager_, UnmountPath("/mount/disk2", _))
      .WillOnce(MoveArg<1>(&callback2));
  EXPECT_CALL(*mock_disk_mount_manager_, UnmountPath("/mount/disk3", _))
      .WillOnce(MoveArg<1>(&callback3));

  // Unmount events would normally be fired by the DiskMountManager.
  AttachDeviceToGuest(guest_os::GuestId("VM1", ""), GetSingleDeviceInfo().guid,
                      /*vm_success=*/false);
  NotifyMountEvent("disk1", disks::DiskMountManager::UNMOUNTING);
  std::move(callback1).Run(MountError::kNone);
  std::move(callback2).Run(MountError::kUnknown);
  NotifyMountEvent("disk3", disks::DiskMountManager::UNMOUNTING);
  std::move(callback3).Run(MountError::kNone);
  base::RunLoop().RunUntilIdle();

  // AttachDeviceToGuest() verifies CrosUsbDetector correctly calls the
  // completion callback, so there's not much to check here.
  EXPECT_EQ(fake_concierge_client_->attach_usb_device_call_count(), 0);
}

TEST_F(CrosUsbDetectorTest, ReassignPromptForSharedDevice) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  device_manager_.CreateAndAddDevice(0x1234, 0x5678);
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(GetSingleDeviceInfo().prompt_before_sharing);
  auto guid = GetSingleDeviceInfo().guid;

  AttachDeviceToGuest(guest_os::GuestId("VM1", ""), guid);
  EXPECT_TRUE(GetSingleDeviceInfo().prompt_before_sharing);

  DetachDeviceFromVm("VM1", guid, /*expected_success=*/true);
  EXPECT_FALSE(GetSingleDeviceInfo().prompt_before_sharing);
}

TEST_F(CrosUsbDetectorTest, ReassignPromptForStorageDevice) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  // Disks mounted before the usb device is detected by the CrosUsbDetector
  // require a prompt.
  AddDisk("disk_early", 1, 5, true);

  device_manager_.CreateAndAddDevice(
      0x0200, 0xff, 0xff, 0xff, 0x0100, 1, 2, /*bus_number=*/1,
      /*port_number=*/5, kManufacturerName, kProductName_1, "5");
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(GetSingleDeviceInfo().prompt_before_sharing);

  NotifyMountEvent("disk_early", disks::DiskMountManager::UNMOUNTING);
  EXPECT_FALSE(GetSingleDeviceInfo().prompt_before_sharing);

  // A disk which fails to mount shouldn't cause the prompt to be shown.
  AddDisk("disk_error", 1, 5, /*mounted=*/false);
  NotifyMountEvent("disk_error", disks::DiskMountManager::MOUNTING,
                   MountError::kInternal);
  EXPECT_FALSE(GetSingleDeviceInfo().prompt_before_sharing);

  AddDisk("disk_success", 1, 5, true);
  EXPECT_TRUE(GetSingleDeviceInfo().prompt_before_sharing);
}

TEST_F(CrosUsbDetectorTest, AttachDeviceToVmWithContainer) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();

  auto device_info = GetSingleDeviceInfo();
  EXPECT_FALSE(GetSingleGuestPort().has_value());
  AttachDeviceToGuest(
      guest_os::GuestId(crostini::kCrostiniDefaultVmName,
                        crostini::kCrostiniDefaultContainerName),
      device_info.guid);

  device_info = GetSingleDeviceInfo();
  EXPECT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ(crostini::kCrostiniDefaultVmName,
            device_info.shared_guest_id->vm_name);
  EXPECT_EQ(crostini::kCrostiniDefaultContainerName,
            device_info.shared_guest_id->container_name);
  EXPECT_EQ(0U, GetSingleGuestPort());
}

TEST_F(CrosUsbDetectorTest, ReattachDeviceToAnotherContainer) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();

  auto device_info = GetSingleDeviceInfo();
  EXPECT_FALSE(device_info.shared_guest_id.has_value());

  AttachDeviceToGuest(
      guest_os::GuestId(crostini::kCrostiniDefaultVmName,
                        crostini::kCrostiniDefaultContainerName),
      device_info.guid);
  AttachDeviceToGuest(guest_os::GuestId(crostini::kCrostiniDefaultVmName,
                                        kCrostiniTestContainerName),
                      device_info.guid);
  device_info = GetSingleDeviceInfo();
  EXPECT_TRUE(device_info.shared_guest_id.has_value());
  EXPECT_EQ(crostini::kCrostiniDefaultVmName,
            device_info.shared_guest_id->vm_name);
  EXPECT_EQ(kCrostiniTestContainerName,
            device_info.shared_guest_id->container_name);
}

TEST_F(CrosUsbDetectorTest, AttachDeviceOnContainerStartup) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();

  auto device_info = GetSingleDeviceInfo();
  // Attaching to container fails, as if the container is not started yet.
  // But the VM attach should succeed and result in a valid guest_port.
  AttachDeviceToGuest(
      guest_os::GuestId(crostini::kCrostiniDefaultVmName,
                        crostini::kCrostiniDefaultContainerName),
      device_info.guid, /*vm_success=*/true,
      /*container_success=*/false);
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(GetSingleGuestPort().has_value());

  vm_tools::cicerone::AttachUsbToContainerResponse response;
  response.set_status(
      vm_tools::cicerone::AttachUsbToContainerResponse_Status_OK);
  fake_cicerone_client_->set_attach_usb_to_container_response(
      std::move(response));

  // cicerone::ContainerStartedSignal triggers container attachment.
  cros_usb_detector_->AddUsbDeviceObserver(&usb_device_observer_);
  vm_tools::cicerone::ContainerStartedSignal container_started_signal;
  container_started_signal.set_vm_name(crostini::kCrostiniDefaultVmName);
  container_started_signal.set_container_name(
      crostini::kCrostiniDefaultContainerName);
  fake_cicerone_client_->NotifyContainerStarted(
      std::move(container_started_signal));
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(1, usb_device_observer_.notify_count());
  device_info = GetSingleDeviceInfo();
  EXPECT_EQ(crostini::kCrostiniDefaultVmName,
            device_info.shared_guest_id->vm_name);
  EXPECT_EQ(crostini::kCrostiniDefaultContainerName,
            device_info.shared_guest_id->container_name);
}

TEST_F(CrosUsbDetectorTest, DetachDeviceOnContainerDeleted) {
  ConnectToDeviceManager();
  base::RunLoop().RunUntilIdle();

  auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
      0, 1, kManufacturerName, kProductName_1, "002");
  device_manager_.AddDevice(device_1);
  base::RunLoop().RunUntilIdle();

  auto device_info = GetSingleDeviceInfo();
  // Attaching to container fails, as if the container is not started yet.
  // But the VM attach should succeed and result in a valid guest_port.
  AttachDeviceToGuest(
      guest_os::GuestId(crostini::kCrostiniDefaultVmName,
                        crostini::kCrostiniDefaultContainerName),
      device_info.guid);
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(GetSingleGuestPort().has_value());

  // cicerone::LxdContainerDeletedSignal triggers detachment.
  cros_usb_detector_->AddUsbDeviceObserver(&usb_device_observer_);
  vm_tools::cicerone::LxdContainerDeletedSignal container_deleted_signal;
  container_deleted_signal.set_status(
      vm_tools::cicerone::LxdContainerDeletedSignal_Status_DELETED);
  container_deleted_signal.set_vm_name(crostini::kCrostiniDefaultVmName);
  container_deleted_signal.set_container_name(
      crostini::kCrostiniDefaultContainerName);
  fake_cicerone_client_->NotifyLxdContainerDeleted(
      std::move(container_deleted_signal));
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(1, usb_device_observer_.notify_count());
  EXPECT_FALSE(GetSingleGuestPort().has_value());
  device_info = GetSingleDeviceInfo();
  EXPECT_FALSE(device_info.shared_guest_id.has_value());
}

}  // namespace ash


text:
/* This file contains the functions for converting C expressions
   to different data types.  The only entry point is `convert'.
   Every language front end must have a `convert' function
   but what kind of conversions it does will depend on the language.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "flags.h"
#include "convert.h"
#include "c-family/c-common.h"
#include "c-tree.h"
#include "langhooks.h"
#include "target.h"

/* Change of width--truncation and extension of integers or reals--
   is represented with NOP_EXPR.  Proper functioning of many things
   assumes that no other conversions can be NOP_EXPRs.

   Conversion between integer and pointer is represented with CONVERT_EXPR.
   Converting integer to real uses FLOAT_EXPR
   and real to integer uses FIX_TRUNC_EXPR.

   Here is a list of all the functions that assume that widening and
   narrowing is always done with a NOP_EXPR:
     In convert.c, convert_to_integer.
     In c-typeck.c, build_binary_op (boolean ops), and
	c_common_truthvalue_conversion.
     In expr.c: expand_expr, for operands of a MULT_EXPR.
     In fold-const.c: fold.
     In tree.c: get_narrower and get_unwidened.  */

/* Subroutines of `convert'.  */

/* Create an expression whose value is that of EXPR,
   converted to type TYPE.  The TREE_TYPE of the value
   is always TYPE.  This function implements all reasonable
   conversions; callers should filter out those that are
   not permitted by the language being compiled.  */

tree
convert (tree type, tree expr)
{
  tree e = expr;
  enum tree_code code = TREE_CODE (type);
  const char *invalid_conv_diag;
  tree ret;
  location_t loc = EXPR_LOCATION (expr);

  if (type == error_mark_node
      || expr == error_mark_node
      || TREE_TYPE (expr) == error_mark_node)
    return error_mark_node;

  if ((invalid_conv_diag
       = targetm.invalid_conversion (TREE_TYPE (expr), type)))
    {
      error (invalid_conv_diag);
      return error_mark_node;
    }

  if (type == TREE_TYPE (expr))
    return expr;
  ret = targetm.convert_to_type (type, expr);
  if (ret)
      return ret;

  STRIP_TYPE_NOPS (e);

  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))
      && (TREE_CODE (TREE_TYPE (expr)) != COMPLEX_TYPE
	  || TREE_CODE (e) == COMPLEX_EXPR))
    return fold_convert_loc (loc, type, expr);
  if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
    return error_mark_node;
  if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE)
    {
      error ("void value not ignored as it ought to be");
      return error_mark_node;
    }

  switch (code)
    {
    case VOID_TYPE:
      return fold_convert_loc (loc, type, e);

    case INTEGER_TYPE:
    case ENUMERAL_TYPE:
      ret = convert_to_integer (type, e);
      goto maybe_fold;

    case BOOLEAN_TYPE:
      return fold_convert_loc
	(loc, type, c_objc_common_truthvalue_conversion (input_location, expr));

    case POINTER_TYPE:
    case REFERENCE_TYPE:
      ret = convert_to_pointer (type, e);
      goto maybe_fold;

    case REAL_TYPE:
      ret = convert_to_real (type, e);
      goto maybe_fold;

    case FIXED_POINT_TYPE:
      ret = convert_to_fixed (type, e);
      goto maybe_fold;

    case COMPLEX_TYPE:
      /* If converting from COMPLEX_TYPE to a different COMPLEX_TYPE
	 and e is not COMPLEX_EXPR, convert_to_complex uses save_expr,
	 but for the C FE c_save_expr needs to be called instead.  */
      if (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE)
	{
	  if (TREE_CODE (e) != COMPLEX_EXPR)
	    {
	      tree subtype = TREE_TYPE (type);
	      tree elt_type = TREE_TYPE (TREE_TYPE (e));

	      if (in_late_binary_op)
		e = save_expr (e);
	      else
		e = c_save_expr (e);
	      ret
		= fold_build2_loc (loc, COMPLEX_EXPR, type,
				   convert (subtype,
					    fold_build1 (REALPART_EXPR,
							 elt_type, e)),
				   convert (subtype,
					    fold_build1 (IMAGPART_EXPR,
							 elt_type, e)));
	      goto maybe_fold;
	    }
	}
      ret = convert_to_complex (type, e);
      goto maybe_fold;

    case VECTOR_TYPE:
      ret = convert_to_vector (type, e);
      goto maybe_fold;

    case RECORD_TYPE:
    case UNION_TYPE:
      if (lang_hooks.types_compatible_p (type, TREE_TYPE (expr)))
	return e;
      break;

    default:
      break;

    maybe_fold:
      if (TREE_CODE (ret) != C_MAYBE_CONST_EXPR)
	ret = fold (ret);
      return ret;
    }

  error ("conversion to non-scalar type requested");
  return error_mark_node;
}

redpajama_set_name: RedPajamaGithub


text:
<?php

?>

Transducers

Conditioners

Standards

DAS Chassis Setups

            <?= $transdcuer_table ?>

            <?= $das_setup_table ?>


text:
module Cb
  module Responses
    module NilModel
      private

      def extract_models
        nil
      end
    end
  end
end


text:
import pytest

from .factories import ContentFactory

pytestmark = pytest.mark.django_db

def test_get_author_display_should_return_author_text(published):
    text = 'An author'
    published.author_text = text
    assert published.get_author_display() == text

def test_get_author_display_should_return_author_if_no_author_text(user):
    content = ContentFactory(author=user)
    content.author_text = ''
    assert content.get_author_display() == unicode(user)


text:
typedef void (^uigesturerecognizer_block_t)(UIGestureRecognizer * _Nonnull recognizer);

@interface UIGestureRecognizer (ODXBlocks)
- (nonnull instancetype)initWithBlock:(nonnull uigesturerecognizer_block_t)block;
- (void)addBlock:(nonnull uigesturerecognizer_block_t)block;
@end

#endif
#endif


text:
namespace Poco {

std::streamsize StreamCopier::copyStream(std::istream& istr, std::ostream& ostr, std::size_t bufferSize)
{
	poco_assert (bufferSize > 0);

	Buffer<char> buffer(bufferSize);
	std::streamsize len = 0;
	istr.read(buffer.begin(), bufferSize);
	std::streamsize n = istr.gcount();
	while (n > 0)
	{
		len += n;
		ostr.write(buffer.begin(), n);
		if (istr && ostr)
		{
			istr.read(buffer.begin(), bufferSize);
			n = istr.gcount();
		}
		else n = 0;
	}
	return len;
}

#if defined(POCO_HAVE_INT64)
Poco::UInt64 StreamCopier::copyStream64(std::istream& istr, std::ostream& ostr, std::size_t bufferSize)
{
	poco_assert (bufferSize > 0);

	Buffer<char> buffer(bufferSize);
	Poco::UInt64 len = 0;
	istr.read(buffer.begin(), bufferSize);
	std::streamsize n = istr.gcount();
	while (n > 0)
	{
		len += n;
		ostr.write(buffer.begin(), n);
		if (istr && ostr)
		{
			istr.read(buffer.begin(), bufferSize);
			n = istr.gcount();
		}
		else n = 0;
	}
	return len;
}
#endif

std::streamsize StreamCopier::copyToString(std::istream& istr, std::string& str, std::size_t bufferSize)
{
	poco_assert (bufferSize > 0);

	Buffer<char> buffer(bufferSize);
	std::streamsize len = 0;
	istr.read(buffer.begin(), bufferSize);
	std::streamsize n = istr.gcount();
	while (n > 0)
	{
		len += n;
		str.append(buffer.begin(), static_cast<std::string::size_type>(n));
		if (istr)
		{
			istr.read(buffer.begin(), bufferSize);
			n = istr.gcount();
		}
		else n = 0;
	}
	return len;
}

#if defined(POCO_HAVE_INT64)
Poco::UInt64 StreamCopier::copyToString64(std::istream& istr, std::string& str, std::size_t bufferSize)
{
	poco_assert (bufferSize > 0);

	Buffer<char> buffer(bufferSize);
	Poco::UInt64 len = 0;
	istr.read(buffer.begin(), bufferSize);
	std::streamsize n = istr.gcount();
	while (n > 0)
	{
		len += n;
		str.append(buffer.begin(), static_cast<std::string::size_type>(n));
		if (istr)
		{
			istr.read(buffer.begin(), bufferSize);
			n = istr.gcount();
		}
		else n = 0;
	}
	return len;
}
#endif

std::streamsize StreamCopier::copyStreamUnbuffered(std::istream& istr, std::ostream& ostr)
{
    char c;
    std::streamsize len = 0;
    istr.get(c);
    while (istr && ostr)
    {
        ++len;
        ostr.put(c);
        istr.get(c);
    }
    return len;
}

#if defined(POCO_HAVE_INT64)
Poco::UInt64 StreamCopier::copyStreamUnbuffered64(std::istream& istr, std::ostream& ostr)
{
    char c;
    Poco::UInt64 len = 0;
    istr.get(c);
    while (istr && ostr)
    {
        ++len;
        ostr.put(c);
        istr.get(c);
    }
    return len;
}
#endif

} // namespace Poco


text:
package com.google.devtools.depan.eclipse.ui.nodes.trees;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.model.IWorkbenchAdapter;

public class ViewerRootAdapter implements IWorkbenchAdapter {

  @Override
  public Object[] getChildren(Object o) {
    if (o instanceof ViewerRoot) {
      return (((ViewerRoot) o).getRoots());
    }
    return new Object[] {};
  }

  @Override
  public ImageDescriptor getImageDescriptor(Object object) {
    return null;
  }

  @Override
  public String getLabel(Object o) {
    if (o instanceof ViewerRoot) {
      return "";
    }
    return o.toString();
  }

  @Override
  public Object getParent(Object o) {
    return null;
  }
}


text:
package org.apache.lenya.cms.site.usecases;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.lenya.ac.Identity;
import org.apache.lenya.cms.metadata.dublincore.DublinCore;
import org.apache.lenya.cms.publication.Document;
import org.apache.lenya.cms.publication.DocumentException;
import org.apache.lenya.cms.publication.DocumentManager;
import org.apache.lenya.cms.publication.Node;
import org.apache.lenya.cms.publication.ResourceType;
import org.apache.lenya.cms.publication.ResourceTypeResolver;
import org.apache.lenya.cms.site.SiteStructure;
import org.apache.lenya.cms.usecase.DocumentUsecase;
import org.apache.lenya.cms.usecase.UsecaseException;
import org.apache.lenya.xml.DocumentHelper;
import org.apache.xpath.XPathAPI;
import org.w3c.dom.Element;

/**
 * Usecase to create a Blog entry.
 *
 * @version $Id$
 */
public class CreateBlogEntry extends DocumentUsecase {

    protected static final String PARENT_ID = "parentId";
    protected static final String DOCUMENT_TYPE = "doctype";
    protected static final String DOCUMENT_ID = "documentId";

    private DocumentManager documentManager;
    private ResourceTypeResolver resourceTypeResolver;

    /**
     * @see org.apache.lenya.cms.usecase.AbstractUsecase#getNodesToLock()
     */
    protected Node[] getNodesToLock() throws UsecaseException {
        SiteStructure structure = getSourceDocument().area().getSite();
        Node[] nodes = { structure };
        return nodes;
    }

    /**
     * @see org.apache.lenya.cms.usecase.AbstractUsecase#initParameters()
     */
    protected void initParameters() {
        super.initParameters();

        Document parent = getSourceDocument();
        try {
            setParameter(PARENT_ID, parent.getPath());
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @see org.apache.lenya.cms.usecase.AbstractUsecase#doCheckExecutionConditions()
     */
    protected void doCheckExecutionConditions() throws Exception {

        String documentId = getParameterAsString(DOCUMENT_ID);

        if (documentId.equals("")) {
            addErrorMessage("The document ID is required.");
        }

        if (documentId.matches("[^a-zA-Z0-9\\-]+")) {
            addErrorMessage("The document ID is not valid.");
        }

        super.doCheckExecutionConditions();
    }

    /**
     * @see org.apache.lenya.cms.usecase.AbstractUsecase#doExecute()
     */
    protected void doExecute() throws Exception {
        super.doExecute();

        // prepare values necessary for blog entry creation
        Document parent = getSourceDocument();
        String language = parent.getPublication().getDefaultLanguage();

        // create new document
        // implementation note: since blog does not have a hierarchy,
        // document id (full path) and document id-name (this leaf's id)
        // are the same
        ResourceType resourceType = getResourceTypeResolver()
                .getResourceType(getDocumentTypeName());

        String documentId = getDocumentID();

        String sampleName = resourceType.getSampleNames()[0];
        String sampleUri = resourceType.getSample(sampleName).getUri();

        Document document = documentManager.add(resourceType, sampleUri, getSourceDocument()
                .getPublication(), getSourceDocument().getArea(), documentId, language, "xml",
                getParameterAsString(DublinCore.ELEMENT_TITLE), true);

        transformXML(document);
    }

    /**
     * The blog publication has a specific site structuring: it groups nodes by date.
     *
     *

     * Example structuring of blog entries:
     *

     *

     *
2004

     *
2005

     *

     *
01

     *
02

     *

     *
23

     *
24

     *

     *
article-one

     *
article-two

     *

     *

     *
     * @return The document ID.
     */
    protected String getDocumentID() {
        DateFormat fmtyyyy = new SimpleDateFormat("yyyy");
        DateFormat fmtMM = new SimpleDateFormat("MM");
        DateFormat fmtdd = new SimpleDateFormat("dd");
        Date date = new Date();

        String year = fmtyyyy.format(date);
        String month = fmtMM.format(date);
        String day = fmtdd.format(date);

        String documentId = "/entries/" + year + "/" + month + "/" + day + "/"
                + getNewDocumentName() + "/index";
        return documentId;
    }

    /**
     * @return The document name.
     * @see org.apache.lenya.cms.site.usecases.Create#getNewDocumentName()
     */
    protected String getNewDocumentName() {
        return getParameterAsString(DOCUMENT_ID);
    }

    /**
     * @return The name of the document type.
     * @see org.apache.lenya.cms.site.usecases.Create#getDocumentTypeName()
     */
    protected String getDocumentTypeName() {
        return getParameterAsString(DOCUMENT_TYPE);
    }

    protected void transformXML(Document document) throws Exception {

        HttpServletRequest request = getRequest();
        HttpSession session = request.getSession(false);
        Identity identity = (Identity) session.getAttribute(Identity.class.getName());
        String title = getParameterAsString(DublinCore.ELEMENT_TITLE);

        org.w3c.dom.Document xmlDoc = DocumentHelper.readDocument(document.getInputStream());

        Element parent = xmlDoc.getDocumentElement();

        if (getLogger().isDebugEnabled())
            getLogger().debug("NewBlogEntryCreator.transformXML(): " + document);

        String[] steps = document.getPath().split("/");
        String nodeId = steps[5];

        // Replace id
        Element element = (Element) XPathAPI.selectSingleNode(parent,
                "/*[local-name() = 'entry']/*[local-name() = 'id']");

        String year = steps[2];
        String month = steps[3];
        String day = steps[4];

        DocumentHelper.setSimpleElementText(element, year + "/" + month + "/" + day + "/" + nodeId);

        // Replace title
        element = (Element) XPathAPI.selectSingleNode(parent,
                "/*[local-name() = 'entry']/*[local-name() = 'title']");
        DocumentHelper.setSimpleElementText(element, title);

        element = (Element) XPathAPI.selectSingleNode(parent,
                "/*[local-name() = 'entry']/*[local-name() = 'link']");
        element.setAttribute("rel", "alternate");
        element.setAttribute("href", "");
        element.setAttribute("type", "text/xml");

        // Replace Summary
        element = (Element) XPathAPI.selectSingleNode(parent,
                "/*[local-name() = 'entry']/*[local-name() = 'summary']");
        DocumentHelper.setSimpleElementText(element, "Summary");

        element = (Element) XPathAPI.selectSingleNode(parent,
                "/*[local-name() = 'entry']/*[local-name() = 'author']/*[local-name() = 'name']");

        if (element == null) {
            throw new RuntimeException("Element entry/author/name not found.");
        }

        DocumentHelper.setSimpleElementText(element, identity.getUser().getId());

        // Replace date created, issued and modified
        DateFormat datefmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        DateFormat ofsfmt = new SimpleDateFormat("Z");
        Date date = new Date();

        String dateofs = ofsfmt.format(date);
        String datestr = datefmt.format(date) + dateofs.substring(0, 3) + ":"
                + dateofs.substring(3, 5);

        element = (Element) XPathAPI.selectSingleNode(parent,
                "/*[local-name() = 'entry']/*[local-name() = 'created']");
        DocumentHelper.setSimpleElementText(element, datestr);
        element = (Element) XPathAPI.selectSingleNode(parent,
                "/*[local-name() = 'entry']/*[local-name() = 'issued']");
        DocumentHelper.setSimpleElementText(element, datestr);
        element = (Element) XPathAPI.selectSingleNode(parent,
                "/*[local-name() = 'entry']/*[local-name() = 'modified']");
        DocumentHelper.setSimpleElementText(element, datestr);

        DocumentHelper.writeDocument(xmlDoc, document.getOutputStream());
    }

    protected DocumentManager getDocumentManager() {
        return documentManager;
    }

    /**
     * TODO: Bean wiring
     */
    public void setDocumentManager(DocumentManager documentManager) {
        this.documentManager = documentManager;
    }

    protected ResourceTypeResolver getResourceTypeResolver() {
        return resourceTypeResolver;
    }

    /**
     * TODO: Bean wiring
     */
    public void setResourceTypeResolver(ResourceTypeResolver resourceTypeResolver) {
        this.resourceTypeResolver = resourceTypeResolver;
    }

}


text:
const removeDivisionByOne = require('../../../lib/simplifyExpression/basicsSearch/removeDivisionByOne');

const testSimplify = require('./testSimplify');

describe('removeDivisionByOne', function() {
  testSimplify('x/1', 'x', removeDivisionByOne);
});


text:
* Scala.js version : 0.6.31

```scala
resolvers in ThisBuild ++= Seq(
  Resolver.bintrayRepo("pragmaxim", "maven")
)
libraryDependencies ++= Seq("com.pragmaxim" %%% "scalajs-keyboard-polyfill" % "0.0.5")
```

Improves keyboard event handling experience in hostile browser environment

Primarily it allows you to abandon onpress events that have cross-browser incompatible behavior and
that are to be deprecated in favor of beforeinput events in W3C DOM4. Calling polyfill method on keydown/keyup PfEvent
gives you normalized keyCode across platforms and browsers and estimated charCode in case of a key representing
printable character. pfKeyCode and optional pfCharCode properties are added to Event object for possible latter use

NOTE:

it might be eventually merged into [scala-js-dom](https://github.com/scala-js/scala-js-dom), see my [PR](https://github.com/scala-js/scala-js-dom/pull/61)


text:
package dynago_test

import (
	"fmt"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"gopkg.in/underarmour/dynago.v1"
)

func ExampleList() {
	l := dynago.List{
		1234,
		"Foo",
		dynago.Document{"Foo": "Bar"},
	}
	fmt.Printf("%s", l[1]) //Output: Foo
}

func TestNumberIntValReturnsTheValueAsAnInt(t *testing.T) {
	num := dynago.Number("18")
	intVal, err := num.IntVal()
	assert.Equal(t, 18, intVal)
	assert.Nil(t, err)
}

func TestNumberIntValReturnsAnErrorIfItCannotParseTheValue(t *testing.T) {
	num := dynago.Number("nope")
	intVal, err := num.IntVal()
	assert.Equal(t, 0, intVal)
	assert.Error(t, err)
}

func TestNumberInt64ValReturnsTheValueAsAnInt(t *testing.T) {
	num := dynago.Number("18")
	intVal, err := num.Int64Val()
	assert.Equal(t, int64(18), intVal)
	assert.Nil(t, err)
}

func TestNumberUint64ValReturnsTheValueAsAnInt(t *testing.T) {
	num := dynago.Number("123456789012")
	intVal, err := num.Uint64Val()
	assert.Equal(t, uint64(123456789012), intVal)
	assert.Nil(t, err)
}

func TestNumberInt64ValReturnsAnErrorIfItCannotParseTheValue(t *testing.T) {
	num := dynago.Number("nope")
	intVal, err := num.Int64Val()
	assert.Equal(t, int64(0), intVal)
	assert.Error(t, err)
}

func TestNumberFloatValReturnsTheValueAsAnfloat(t *testing.T) {
	num := dynago.Number("18.12")
	floatVal, err := num.FloatVal()
	assert.Equal(t, float64(18.12), floatVal)
	assert.Nil(t, err)
}

func TestNumberFloatValReturnsAnErrorIfItCannotParseTheValue(t *testing.T) {
	num := dynago.Number("nope")
	floatVal, err := num.FloatVal()
	assert.Equal(t, float64(0), floatVal)
	assert.Error(t, err)
}

func TestListAsDocumentListReturnsAListOfDocuments(t *testing.T) {
	list := dynago.List{dynago.Document{"id": 1}}
	docList, _ := list.AsDocumentList()
	assert.Equal(t, dynago.Document{"id": 1}, docList[0])
}

func TestListAsDocumentListReturnsAnErrorIfThereAreNonDocuments(t *testing.T) {
	list := dynago.List{dynago.Document{"real": "item"}, "imnotadocument"}
	_, err := list.AsDocumentList()
	assert.Equal(t, err.Error(), "item at index 1 was not a Document")
}

func TestListAsDocumentListReturnsTheDocumentsUpToTheFirstNonDocument(t *testing.T) {
	list := dynago.List{dynago.Document{"real": "item"}, "imnotadocument", dynago.Document{"i won't": "show up"}}
	docList, _ := list.AsDocumentList()
	assert.Equal(t, []dynago.Document{{"real": "item"}}, docList)
}

func TestDocumentGetStringReturnsTheUnderlyingValueAsAString(t *testing.T) {
	doc := dynago.Document{"name": "Timmy Testerson"}
	assert.Equal(t, "Timmy Testerson", doc.GetString("name"))
}

func TestDocumentGetStringReturnsAnEmptyStringWhenTheKeyIsNotPresent(t *testing.T) {
	doc := dynago.Document{}
	assert.Equal(t, "", doc.GetString("name"))
}

func TestDocumentGetNumberReturnsTheDynagoNumberWrappingTheValue(t *testing.T) {
	doc := dynago.Document{"id": dynago.Number("12")}
	assert.Equal(t, dynago.Number("12"), doc.GetNumber("id"))
}

func TestDocumentGetNumberReturnsAnEmptyNumberWhenTheKeyIsNotPresent(t *testing.T) {
	doc := dynago.Document{}
	assert.Equal(t, dynago.Number(""), doc.GetNumber("id"))
}

func TestDocumentGetNumberPanicsIfTheUnderlyingTypeIsNotANumber(t *testing.T) {
	doc := dynago.Document{"id": "not-a-dynago-number"}
	assert.Panics(t, func() {
		doc.GetNumber("id")
	})
}

func TestDocumentGetStringSetReturnsTheStringSetValue(t *testing.T) {
	doc := dynago.Document{"vals": dynago.StringSet{"val1", "val2"}}
	assert.Equal(t, dynago.StringSet{"val1", "val2"}, doc.GetStringSet("vals"))
}

func TestDocumentGetStringSetReturnsAnEmptyStringSetWhenTheKeyDoesNotExist(t *testing.T) {
	doc := dynago.Document{}
	assert.Equal(t, dynago.StringSet{}, doc.GetStringSet("vals"))
}

func TestDocumentGetStringSetPanic(t *testing.T) {
	doc := dynago.Document{"vals": "not-a-string-slice"}
	assert.Panics(t, func() {
		doc.GetStringSet("vals")
	})
}

func TestDocumentGetTimeReturnsTheTimeValueFromISO8601(t *testing.T) {
	doc := dynago.Document{"time": "1990-04-16T00:00:00Z"}
	val, _ := time.Parse("2006-01-02T15:04:05Z", "1990-04-16T00:00:00Z")
	assert.Equal(t, &val, doc.GetTime("time"))
}

func TestDocumentGetTimeReturnsNilWhenTheKeyDoesNotExist(t *testing.T) {
	doc := dynago.Document{}
	assert.Nil(t, doc.GetTime("time"))
}

func TestDocumentGetTimePanicsWhenFormatIsNotIso8601(t *testing.T) {
	doc := dynago.Document{"time": "Foo"}
	assert.Panics(t, func() { doc.GetTime("time") })
}

func TestDocumentMarshalJSONDoesNotIncludeEmptyValues(t *testing.T) {
	doc := dynago.Document{"key1": "shows up", "key2": 9, "fields": dynago.StringSet([]string{"is", "present"}), "id": "", "name": nil, "tags": []string{}}
	jsonDoc, _ := doc.MarshalJSON()

	assert.Contains(t, string(jsonDoc), `"fields":{"SS":["is","present"]}`)
	assert.Contains(t, string(jsonDoc), `"key1":{"S":"shows up"}`)
	assert.Contains(t, string(jsonDoc), `"key2":{"N":"9"}`)
}

func TestDocumentGetBool(t *testing.T) {
	var doc dynago.Document
	for _, n := range []string{"1", "-1", "5", "100"} {
		doc = dynago.Document{"val": dynago.Number(n)}
		assert.Equal(t, true, doc.GetBool("val"))
	}
	doc = dynago.Document{"val": dynago.Number("0")}
	assert.Equal(t, false, doc.GetBool("val"))

	doc = dynago.Document{}
	assert.Equal(t, false, doc.GetBool("val"))

	doc = dynago.Document{"val": nil}
	assert.Equal(t, false, doc.GetBool("val"))

	doc = dynago.Document{"val": dynago.Number("b")}
	assert.Panics(t, func() {
		doc.GetBool("val")
	})

	doc = dynago.Document{"val": "hello"}
	assert.Panics(t, func() {
		doc.GetBool("val")
	})

	doc = dynago.Document{"val": true}
	assert.Equal(t, true, doc.GetBool("val"))

	doc = dynago.Document{"val": false}
	assert.Equal(t, false, doc.GetBool("val"))

}

func TestDocumentGetList(t *testing.T) {
	doc := dynago.Document{"vals": dynago.List{"val1", "val2"}, "wrongtype": 4}
	assert.Equal(t, dynago.List{"val1", "val2"}, doc.GetList("vals"))
	assert.Equal(t, dynago.List(nil), doc.GetList("notarealkey"))
	assert.Panics(t, func() { doc.GetList("wrongtype") })
}


text:
package com.fetoxdevelopments.optix.api.enumeration;

import java.util.Collections;
import java.util.Iterator;

import org.bridj.FlagSet;
import org.bridj.IntValuedEnum;

/**
 * enum values

 * native declaration : include\internal\optix_declarations.h
 */
public enum RTremotedevicestatus
  implements IntValuedEnum<RTremotedevicestatus>
{
  RT_REMOTEDEVICE_STATUS_READY(0),
  RT_REMOTEDEVICE_STATUS_CONNECTED(1),
  RT_REMOTEDEVICE_STATUS_RESERVED(2),
  /** < RemoteDevice Status Disconnected */
  RT_REMOTEDEVICE_STATUS_DISCONNECTED(~0);

  RTremotedevicestatus(long value)
  {
    this.value = value;
  }

  public final long value;

  public long value()
  {
    return this.value;
  }

  public Iterator<RTremotedevicestatus> iterator()
  {
    return Collections.singleton(this).iterator();
  }

  public static IntValuedEnum<RTremotedevicestatus> fromValue(int value)
  {
    return FlagSet.fromValue(value, values());
  }
}


text:
<?php
namespace dlds\shareit;

use Yii;
use yii\web\AssetBundle;

class ShareItAssets extends AssetBundle
{
	public $sourcePath = '@shareit/assets';
	public $basePath = '@webroot/assets';
	public $js = [
		'social.js'
	];
	public $css = [];
	public $depends = [
		'yii\web\JqueryAsset',
	];

	public function init() {
		Yii::setAlias('@shareit', __DIR__);
		return parent::init();
	}
}


text:
Start here to begin with VivaGraph.JS.

## Creating a graph
Create a graph with no edges and no nodes:

```html
<!DOCTYPE html>
<html>
    <head>
        <title>VivaGraphs test page</title>
        <script src="../dist/vivagraph.js"></script>
        <script type='text/javascript'>

            function onLoad() {
                var g = Viva.Graph.graph();
            }

        </script>
    </head>
    <body onload="onLoad()">

    </body>
</html>
```

By definition, a Graph is a collection of nodes (vertices) and links (also called edges - identified pairs of nodes). In VivaGraph.JS nodes can be any object e.g. a string, a number, a function, another graph or object, and so on.

## Growing a graph
The graph `g`can be grown in two ways. You can add one node at a time:

```javascript
g.addNode('hello');
g.addNode('world');
```

Now graph `g` contains two nodes: `hello` and `world`. You can also use `addLink()` method to grow a graph. Calling this method with nodes which are not present in the graph creates them:

```javascript
g.addLink('space', 'bar'); // now graph 'g' has two new nodes: 'space' and 'bar'
```

If nodes already present in the graph 'addLink()' makes them connected:

```javascript
g.addLink('hello', 'world'); // Only a link between 'hello' and 'bar' is created. No new nodes.
```

### What to use as nodes and edges?
Though VivaGraph.JS does not limit you in choosing node type, the most common and convenient choices are numbers and strings, used to identify a node, and actual node data is passed via optional second parameter of `addNode()` method:

```javascript
g.addNode('world', 'custom data'); // Now node 'world' is associated with a string object 'custom data'
```

It's better to think of the first parameter as node identifier, and second parameter its actual content.

> Note: if node already present in the graph `addNode()` augments data object associated with the node.

You can also associate arbitrary object with a link using third optional parameter of `addLink()` method:

```javascript
g.addLink(1, 2, x); // A link between nodes '1' and '2' is now associated with object 'x'
```

### Enumerating nodes and links
After you created a graph one of the most common task is to enumerate its nodes/links to perform an operation.

```javascript
g.forEachNode(function(node){
    console.log(node.id, node.data);
});
```

The function takes callback which accepts current node. Node object holds set of internal properties used by layouting algorithms which might be changed in future. But `node.id` and `node.data` represent parameters passed to the `g.addNode(id, data)` method and they are guaranteed to persist across library releases.

To enumerate all links in the graph use `forEachLink()` method:

```javascript
g.forEachLink(function(link) {
    console.dir(link);
});
```

To enumerate all links for a specific node use `forEachLinkedNode()` method:

```JavaScript
g.forEachLinkedNode('hello', function(linkedNode, link){
    console.log("Connected node: ", linkedNode.id, linkedNode.data);
    console.dir(link); // link object itself
});
```

This method always enumerates both inbound and outbound links. To get a particular node object use `getNode()` method. E.g.:

```javascript
var world = g.getNode('world'); // returns 'world' node
console.log(world.id, world.data);
```

Finally to remove a node or a link from a graph use `removeNode()` or `removeLink()` correspondingly:

```javascript
g.removeNode('space');
// Removing link is a bit harder, since method requires actual link object:
g.forEachLinkedNode('hello', function(linkedNode, link){
  g.removeLink(link);
});
```

Stop now and play with [interactive fiddle](http://jsfiddle.net/JA76K/182/) for this article.


text:
using namespace std;

int main() {
    string x;
    while(cin>>x)
        cout<<x<<endl;
    // Complete the code.
    return 0;
}


text:
local K, C, L = unpack(select(2, ...))
if C["DataText"].Time ~= true then
	return
end

-- Lua API
local _G = _G
local date = date
local next = next
local pairs = pairs
local string_format = string.format
local string_join = string.join
local string_utf8sub = string.utf8sub
local table_sort, table_insert = table.sort, table.insert
local unpack = unpack

-- WoW API
local EJ_GetCurrentTier = _G.EJ_GetCurrentTier
local EJ_GetInstanceByIndex = _G.EJ_GetInstanceByIndex
local EJ_GetNumTiers = _G.EJ_GetNumTiers
local EJ_SelectTier = _G.EJ_SelectTier
local GameTooltip = _G.GameTooltip
local GetAchievementInfo = _G.GetAchievementInfo
local GetDifficultyInfo = _G.GetDifficultyInfo
local GetGameTime = _G.GetGameTime
local GetNumSavedInstances = _G.GetNumSavedInstances
local GetNumSavedWorldBosses = _G.GetNumSavedWorldBosses
local GetNumWorldPVPAreas = _G.GetNumWorldPVPAreas
local GetSavedInstanceInfo = _G.GetSavedInstanceInfo
local GetSavedWorldBossInfo = _G.GetSavedWorldBossInfo
local GetWorldPVPAreaInfo = _G.GetWorldPVPAreaInfo
local QUEUE_TIME_UNAVAILABLE = _G.QUEUE_TIME_UNAVAILABLE
local RequestRaidInfo = _G.RequestRaidInfo
local SecondsToTime = _G.SecondsToTime
local TIMEMANAGER_TOOLTIP_LOCALTIME = _G.TIMEMANAGER_TOOLTIP_LOCALTIME
local TIMEMANAGER_TOOLTIP_REALMTIME = _G.TIMEMANAGER_TOOLTIP_REALMTIME
local VOICE_CHAT_BATTLEGROUND = _G.VOICE_CHAT_BATTLEGROUND
local WINTERGRASP_IN_PROGRESS = _G.WINTERGRASP_IN_PROGRESS

-- GLOBALS: GameTimeFrame

local DataTextTime = CreateFrame("Frame")

local NameColor = K.RGBToHex(K.Color.r, K.Color.g, K.Color.b)
local ValueColor = K.RGBToHex(1, 1, 1)

DataTextTime.Text = Minimap:CreateFontString(nil, "OVERLAY")
DataTextTime.Text:SetFont(C["Media"].Font, 12, "")
DataTextTime.Text:SetShadowOffset(1.25, -1.25)
DataTextTime.Text:SetPoint("BOTTOM", Minimap, "BOTTOM", 0, 2)
DataTextTime:SetAllPoints(DataTextTime.Text)

local WORLD_BOSSES_TEXT = RAID_INFO_WORLD_BOSS.."(s)"
local APM = {TIMEMANAGER_PM, TIMEMANAGER_AM}
local europeDisplayFormat = "%s%02d|r:%s%02d|r"
local ukDisplayFormat = "%s%d|r:%s%02d|r %s%s|r"
local europeDisplayFormat_nocolor = string_join("", "%02d", ":|r%02d")
local ukDisplayFormat_nocolor = string_join("", "", "%d", ":|r%02d", " %s|r")
local lockoutInfoFormat = "%s%s %s |cffaaaaaa(%s, %s/%s)"
local lockoutInfoFormatNoEnc = "%s%s %s |cffaaaaaa(%s)"
local formatBattleGroundInfo = "%s: "
local lockoutColorExtended, lockoutColorNormal = {r = 0.3, g = 1, b = 0.3}, {r = .8,g = .8,b = .8}
local curHr, curMin, curAmPm
local enteredFrame = false
local Update, lastPanel -- UpValue
local localizedName, isActive, startTime, canEnter, _

if lastPanel ~= nil then
	Update(lastPanel, 20000)
end

local function ConvertTime(h, m)
	local AmPm
	if C["DataText"].Time24Hr == true then
		return h, m, -1
	else
		if h >= 12 then
			if h > 12 then h = h - 12 end
			AmPm = 1
		else
			if h == 0 then h = 12 end
			AmPm = 2
		end
	end
	return h, m, AmPm
end

local function CalculateTimeValues(tooltip)
	if (tooltip and C["DataText"].LocalTime) or (not tooltip and not C["DataText"].LocalTime) then
		return ConvertTime(GetGameTime())
	else
		local dateTable = date("*t")
		return ConvertTime(dateTable["hour"], dateTable["min"])
	end
end

local function Click(self, btn)
	GameTimeFrame:Click()
end

local function OnLeave()
	if not GameTooltip:IsForbidden() then
		GameTooltip:Hide()
		enteredFrame = false
	end
end

-- use these to convert "The Eye" into "Tempest Keep"
local DUNGEON_FLOOR_TEMPESTKEEP1 = DUNGEON_FLOOR_TEMPESTKEEP1
local TempestKeep = select(2, GetAchievementInfo(1088)):match("%((.-)%)$")

local instanceIconByName = {}
local function GetInstanceImages(index, raid)
	local instanceID, name, _, _, buttonImage = EJ_GetInstanceByIndex(index, raid)
	while instanceID do
		if name == DUNGEON_FLOOR_TEMPESTKEEP1 then
			instanceIconByName[TempestKeep] = buttonImage
		else
			instanceIconByName[name] = buttonImage
		end
		index = index + 1
		instanceID, name, _, _, buttonImage = EJ_GetInstanceByIndex(index, raid)
	end
end

local locale = GetLocale()
local krcntw = locale == "koKR" or locale == "zhCN" or locale == "zhTW"
local difficultyTag = { -- Raid Finder, Normal, Heroic, Mythic
	(krcntw and PLAYER_DIFFICULTY1) or string_utf8sub(PLAYER_DIFFICULTY1, 1, 1), -- N
	(krcntw and PLAYER_DIFFICULTY2) or string_utf8sub(PLAYER_DIFFICULTY2, 1, 1), -- H
	(krcntw and PLAYER_DIFFICULTY3) or string_utf8sub(PLAYER_DIFFICULTY3, 1, 1), -- R
	(krcntw and PLAYER_DIFFICULTY6) or string_utf8sub(PLAYER_DIFFICULTY6, 1, 1) -- M
}

local collectedInstanceImages = false
local function OnEnter(self)
	GameTooltip:SetOwner(self, "ANCHOR_NONE")
	GameTooltip:SetPoint(K.GetAnchors(self))
	GameTooltip:ClearLines()

	if (not enteredFrame) then
		enteredFrame = true
		RequestRaidInfo()
	end

	if not collectedInstanceImages then
		local numTiers = (EJ_GetNumTiers() or 0)
		if numTiers > 0 then
			local currentTier = EJ_GetCurrentTier()
			-- Loop through the expansions to collect the textures
			for i = 1, numTiers do
				EJ_SelectTier(i)
				GetInstanceImages(1, false) -- Populate for dungeon icons
				GetInstanceImages(1, true) -- Populate for raid icons
			end
			-- Set it back to the previous tier
			if currentTier then
				EJ_SelectTier(currentTier)
			end
			collectedInstanceImages = true
		end
	end

	local addedHeader = false
	local localizedName, isActive, startTime, canEnter, _
	for i = 1, GetNumWorldPVPAreas() do
		_, localizedName, isActive, _, startTime, canEnter = GetWorldPVPAreaInfo(i)
		if canEnter then
			if not addedHeader then
				GameTooltip:AddLine(VOICE_CHAT_BATTLEGROUND)
				addedHeader = true
			end
			if isActive then
				startTime = WINTERGRASP_IN_PROGRESS
			elseif startTime == nil then
				startTime = QUEUE_TIME_UNAVAILABLE
			else
				startTime = SecondsToTime(startTime, false, nil, 3)
			end
			GameTooltip:AddDoubleLine(string_format(formatBattleGroundInfo, localizedName), startTime, 1, 1, 1, lockoutColorNormal.r, lockoutColorNormal.g, lockoutColorNormal.b)
		end
	end

	local lockedInstances = {raids = {}, dungeons = {}}
	local name, difficulty, locked, extended, isRaid
	local isLFR, isHeroicOrMythicDungeon, isHeroic, displayHeroic, displayMythic, sortName, difficultyLetter, buttonImg
	for i = 1, GetNumSavedInstances() do
		name, _, _, difficulty, locked, extended, _, isRaid = GetSavedInstanceInfo(i)
		if (locked or extended) and name then
			isLFR, isHeroicOrMythicDungeon = (difficulty == 7 or difficulty == 17), (difficulty == 2 or difficulty == 23)
			_, _, isHeroic, _, displayHeroic, displayMythic = GetDifficultyInfo(difficulty)
			sortName = name .. (displayMythic and 4 or (isHeroic or displayHeroic) and 3 or isLFR and 1 or 2)
			difficultyLetter = (displayMythic and difficultyTag[4] or (isHeroic or displayHeroic) and difficultyTag[3] or isLFR and difficultyTag[1] or difficultyTag[2])
			buttonImg = instanceIconByName[name] and string_format("|T%s:16:16:0:0:96:96:0:64:0:64|t ", instanceIconByName[name]) or ""
			if isRaid then
				table_insert(lockedInstances["raids"], {sortName, difficultyLetter, buttonImg, {GetSavedInstanceInfo(i)}})
			elseif isHeroicOrMythicDungeon then
				table_insert(lockedInstances["dungeons"], {sortName, difficultyLetter, buttonImg, {GetSavedInstanceInfo(i)}})
			end
		end
	end

	local reset, maxPlayers, numEncounters, encounterProgress, lockoutColor
	if next(lockedInstances["raids"]) then
		if GameTooltip:NumLines() > 0 then
			GameTooltip:AddLine(" ")
		end
		GameTooltip:AddLine("Saved Raid(s)")

		table_sort(lockedInstances["raids"], function(a, b)
			return a[1] < b[1]
		end)

		for i = 1, #lockedInstances["raids"] do
			difficultyLetter = lockedInstances["raids"][i][2]
			buttonImg = lockedInstances["raids"][i][3]
			name, _, reset, _, _, extended, _, _, maxPlayers, _, numEncounters, encounterProgress = unpack(lockedInstances["raids"][i][4])

			lockoutColor = extended and lockoutColorExtended or lockoutColorNormal
			if (numEncounters and numEncounters > 0) and (encounterProgress and encounterProgress > 0) then
				GameTooltip:AddDoubleLine(string_format(lockoutInfoFormat, buttonImg, maxPlayers, difficultyLetter, name, encounterProgress, numEncounters), SecondsToTime(reset, false, nil, 3), 1, 1, 1, lockoutColor.r, lockoutColor.g, lockoutColor.b)
			else
				GameTooltip:AddDoubleLine(string_format(lockoutInfoFormatNoEnc, buttonImg, maxPlayers, difficultyLetter, name), SecondsToTime(reset, false, nil, 3), 1, 1, 1, lockoutColor.r, lockoutColor.g, lockoutColor.b)
			end
		end
	end

	if next(lockedInstances["dungeons"]) then
		if GameTooltip:NumLines() > 0 then
			GameTooltip:AddLine(" ")
		end
		GameTooltip:AddLine("Saved Dungeon(s)")

		table_sort(lockedInstances["dungeons"], function(a, b)
			return a[1] < b[1]
		end)

		for i = 1, #lockedInstances["dungeons"] do
			difficultyLetter = lockedInstances["dungeons"][i][2]
			buttonImg = lockedInstances["dungeons"][i][3]
			name, _, reset, _, _, extended, _, _, maxPlayers, _, numEncounters, encounterProgress = unpack(lockedInstances["dungeons"][i][4])

			lockoutColor = extended and lockoutColorExtended or lockoutColorNormal
			if (numEncounters and numEncounters > 0) and (encounterProgress and encounterProgress > 0) then
				GameTooltip:AddDoubleLine(string_format(lockoutInfoFormat, buttonImg, maxPlayers, difficultyLetter, name, encounterProgress, numEncounters), SecondsToTime(reset, false, nil, 3), 1, 1, 1, lockoutColor.r, lockoutColor.g, lockoutColor.b)
			else
				GameTooltip:AddDoubleLine(string_format(lockoutInfoFormatNoEnc, buttonImg, maxPlayers, difficultyLetter, name), SecondsToTime(reset, false, nil, 3), 1, 1, 1, lockoutColor.r, lockoutColor.g, lockoutColor.b)
			end
		end
	end

	local addedLine = false
	local worldbossLockoutList = {}
	for i = 1, GetNumSavedWorldBosses() do
		name, _, reset = GetSavedWorldBossInfo(i)
		table_insert(worldbossLockoutList, {name, reset})
	end
	table_sort(worldbossLockoutList, function(a, b)
		return a[1] < b[1]
	end)
	for i = 1,#worldbossLockoutList do
		name, reset = unpack(worldbossLockoutList[i])
		if (reset) then
			if (not addedLine) then
				GameTooltip:AddLine(" ")
				GameTooltip:AddLine(WORLD_BOSSES_TEXT)
				addedLine = true
			end
			GameTooltip:AddDoubleLine(name, SecondsToTime(reset, true, nil, 3), 1, 1, 1, 0.8, 0.8, 0.8)
		end
	end

	local Hr, Min, AmPm = CalculateTimeValues(true)

	if GameTooltip:NumLines() > 0 then
		GameTooltip:AddLine(" ")
	end
	if AmPm == -1 then
		GameTooltip:AddDoubleLine(C["DataText"].LocalTime and TIMEMANAGER_TOOLTIP_REALMTIME or TIMEMANAGER_TOOLTIP_LOCALTIME,
		string_format(europeDisplayFormat_nocolor, Hr, Min), 1, 1, 1, lockoutColorNormal.r, lockoutColorNormal.g, lockoutColorNormal.b)
	else
		GameTooltip:AddDoubleLine(C["DataText"].LocalTime and TIMEMANAGER_TOOLTIP_REALMTIME or TIMEMANAGER_TOOLTIP_LOCALTIME,
		string_format(ukDisplayFormat_nocolor, Hr, Min, APM[AmPm]), 1, 1, 1, lockoutColorNormal.r, lockoutColorNormal.g, lockoutColorNormal.b)
	end

	GameTooltip:Show()
end

local function OnEvent(self, event)
	if event == "UPDATE_INSTANCE_INFO" and enteredFrame then
		OnEnter(self)
	end
end

local int = 3
function Update(self, t)
	int = int - t

	if int > 0 then
		return
	end

	if GameTimeFrame.flashInvite then
		K.UIFrameFlash(self, 0.53, true)
	else
		K.UIFrameStopFlash(self)
	end

	if enteredFrame then
		OnEnter(self)
	end

	local Hr, Min, AmPm = CalculateTimeValues(false)

	-- no update quick exit
	if (Hr == curHr and Min == curMin and AmPm == curAmPm) and not (int < -15000) then
		int = 5
		return
	end

	curHr = Hr
	curMin = Min
	curAmPm = AmPm

	if AmPm == -1 then
		DataTextTime.Text:SetFormattedText(europeDisplayFormat, ValueColor, Hr, ValueColor, Min)
	else
		DataTextTime.Text:SetFormattedText(ukDisplayFormat, ValueColor, Hr, ValueColor, Min, NameColor, APM[AmPm])
	end

	lastPanel = self
	int = 5
end

local function DelayDataTextTime()
	DataTextTime:RegisterEvent("UPDATE_INSTANCE_INFO")
	DataTextTime:SetScript("OnEvent", OnEvent)
	DataTextTime:SetScript("OnMouseDown", Click)
	DataTextTime:SetScript("OnUpdate", Update)
	DataTextTime:SetScript("OnEnter", OnEnter)
	DataTextTime:SetScript("OnLeave", OnLeave)
	Update(DataTextTime, 1)
end

C_Timer.After(0.4, function()
	DelayDataTextTime()
end)


text:
var compose = require('ksf/utils/compose');
var FocusableElement = require('./FocusableElement');

module.exports = compose(FocusableElement.prototype, function(args) {
	FocusableElement.call(this, 'input');
	this._asYouType = args && args.asYouType;

	// callbacks mapping
	this._inputCbMap = [];
}, {
	value: function(value) {
		if (arguments.length) {
			this._setValue(value);
			return this;
		} else {
			return this._getValue();
		}
	},
	onInput: function(cb) {
		var self = this;
		var inputCb = function() {
			cb(self._getValue());
		};
		this.on(this._asYouType ? 'input' : 'change', inputCb);
		this._inputCbMap.push([cb, inputCb]);
		return this;
	},
	offInput: function(cb) {
		var inputCb;
		var inputCbMap = this._inputCbMap
		// TODO: replace with ES6 Map?
		inputCbMap.some(function(couple, index) {
			if (couple[0] === cb) {
				inputCb = couple[1];
				inputCbMap.splice(index, 1);
				return true;
			}
		});

		this.off(this._asYouType ? 'input' : 'change', inputCb);
		return this;
	},
});


text:
import os
import sys

from six import print_

class PCI(object):
    """ Dealing with devices binding to NUMA nodes """
    __NODE_DIRECTORY = '/sys/devices/system/node/'
    __FAKE_DEV = {
        'eth0': 0,
        'eth1': 0,
        'eth2': 1,
        'eth3': 1,
    }
    devices = None

    def node_dev_dict(self, devices, fake=False):
        """
        :param devices: list of devices
        :param fake: options.random
        :return: NIC's NUMA bindings dict like {'eth1': 0, 'eth2': 1, 'eth3': 0} """
        if not devices:
            return dict()
        return dict((dev, self.dev_node(dev, fake)) for dev in devices)

    def dev_node(self, dev, fake=False):
        """ Determines which NUMA node given network device belongs to """
        if fake:
            return self.__FAKE_DEV.get(dev, -1)
        filename = '/sys/class/net/{0}/device/numa_node'.format(dev)
        if not os.path.isfile(filename):
            return -1
        with open(filename) as dev_file:
            return int(dev_file.read().strip())

if __name__ == '__main__':
    print_(PCI().node_dev_dict(sys.argv[1:]))


text:
var mongoose = require('mongoose')
var Schema = mongoose.Schema
var ObjectId = Schema.Types.ObjectId

var CommentSchema = new mongoose.Schema({
  movie: {type: ObjectId, ref: 'Movie'},
  from: {type: ObjectId, ref: 'User'},
  reply: [{
    from: {type: ObjectId, ref: 'User'},
    to: {type: ObjectId, ref: 'User'},
    content: String
  }],
  content: String,
  meta: {
    createAt: {
      type: Date,
      default: Date.now()
    },
    updateAt: {
      type: Date,
      default: Date.now()
    }
  }
})

// var ObjectId = mongoose.Schema.Types.ObjectId
CommentSchema.pre('save', function(next) {
  if (this.isNew) {
    this.meta.createAt = this.meta.updateAt = Date.now()
  }
  else {
    this.meta.updateAt = Date.now()
  }

  next()
})

CommentSchema.statics = {
  fetch: function(cb) {
    return this
      .find({})
      .sort('meta.updateAt')
      .exec(cb)
  },
  findById: function(id, cb) {
    return this
      .findOne({_id: id})
      .exec(cb)
  }
}

module.exports = CommentSchema


text:
cd engine && ./release_emscripten.sh
cd ..
echo "Symlinking \`./engine/target/asmjs-unknown-emscripten/release/noise-backend.js\` to \`./public/compiled.js\`"
ln -sf $(pwd)/engine/target/asmjs-unknown-emscripten/release/noise-backend.js $(pwd)/public/compiled.js
#ln -sf $(pwd)/engine/target/asmjs-unknown-emscripten/release/noise_backend.wasm $(pwd)/public/

# Builds the frontend, including the compiled code
yarn run build