text:
#include <err.h>
#include <pow2.h>
#include <stdlib.h>
#include <string.h>

#include <arch/arm/cm.h>
#include <kernel/event.h>
#include <kernel/mutex.h>
#include <lib/bio.h>
#include <platform.h>
#include <platform/n25qxxa.h>
#include <platform/n25q128a.h>
#include <platform/n25q512a.h>
#include <platform/qspi.h>
#include <trace.h>

#define FOUR_BYTE_ADDR_THRESHOLD (1 << 24)
#define LOCAL_TRACE 0
#define MAX_DMA_WAIT_MS 1024

typedef void (*CpltCallback)(void);

typedef enum {
    QSPI_STATE_LINEAR,
    QSPI_STATE_COMMAND,
    QSPI_STATE_MAX
} device_state_t;
device_state_t device_state;

static QSPI_HandleTypeDef qspi_handle;
static DMA_Stream_TypeDef *dma2_stream7;
static CpltCallback cplt_callback;

static const char device_name[] = "qspi-flash";
static bdev_t qspi_flash_device;
static bio_erase_geometry_info_t geometry;

static mutex_t spiflash_mutex;

// Functions exported to Block I/O handler.
static ssize_t spiflash_bdev_read(struct bdev *device, void *buf, off_t offset, size_t len);
static ssize_t spiflash_bdev_read_block(struct bdev *device, void *buf, bnum_t block, uint count);
static ssize_t spiflash_bdev_write_block(struct bdev *device, const void *buf, bnum_t block, uint count);
static ssize_t spiflash_bdev_erase(struct bdev *device, off_t offset, size_t len);
static int spiflash_ioctl(struct bdev *device, int request, void *argp);

static ssize_t qspi_write_page_unsafe(uint32_t addr, const uint8_t *data);

static ssize_t qspi_erase(bdev_t *device, uint32_t block_addr, uint32_t instruction);
static ssize_t qspi_bulk_erase(bdev_t *device);
static ssize_t qspi_erase_sector(bdev_t *device, uint32_t block_addr);
static ssize_t qspi_erase_subsector(bdev_t *device, uint32_t block_addr);
static status_t qspi_auto_polling_mem_ready_unsafe(QSPI_HandleTypeDef *hqspi, uint8_t match, uint8_t mask);

static HAL_StatusTypeDef qspi_cmd(QSPI_HandleTypeDef *, QSPI_CommandTypeDef *);
static HAL_StatusTypeDef qspi_tx_dma(QSPI_HandleTypeDef *, QSPI_CommandTypeDef *, uint8_t *);
static HAL_StatusTypeDef qspi_rx_dma(QSPI_HandleTypeDef *, QSPI_CommandTypeDef *, uint8_t *);

status_t qspi_enable_linear(void);
status_t qspi_disable_linear(void);

status_t qspi_dma_init(QSPI_HandleTypeDef *hqspi);

static uint32_t get_specialized_instruction(uint32_t instruction, uint32_t address);
static uint32_t get_address_size(uint32_t address);

static event_t cmd_event;
static event_t rx_event;
static event_t tx_event;
static event_t st_event;

status_t hal_error_to_status(HAL_StatusTypeDef hal_status);

// Unsetting the DMA Enable bit in the DMA Control register isn't enough to
// disable the DMA Engine since DMA transfers may still be in progress.
// We have to wait for the DMA Engine to acknowledge being disabled by watching
// the DMA Enable bit.
static status_t dma_disable(DMA_Stream_TypeDef *dma)
{
    // Unset the DMA Enable bit.
    dma->CR &= ~DMA_SxCR_EN;

    lk_time_t start_time = current_time();

    while (dma->CR & DMA_SxCR_EN) {

        dma->CR &= ~DMA_SxCR_EN;

        if (current_time() - start_time > MAX_DMA_WAIT_MS) {
            return ERR_TIMED_OUT;
        }
    }

    return NO_ERROR;
}

// Must hold spiflash_mutex before calling.
static status_t qspi_write_enable_unsafe(QSPI_HandleTypeDef *hqspi)
{
    HAL_StatusTypeDef status;

    static const QSPI_CommandTypeDef s_command = {
        .InstructionMode = QSPI_INSTRUCTION_1_LINE,
        .Instruction = WRITE_ENABLE_CMD,
        .AddressMode = QSPI_ADDRESS_NONE,
        .AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
        .DataMode = QSPI_DATA_NONE,
        .DummyCycles = 0,
        .DdrMode = QSPI_DDR_MODE_DISABLE,
        .DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY,
        .SIOOMode = QSPI_SIOO_INST_EVERY_CMD
    };

    status = HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
    if (status != HAL_OK) {
        return hal_error_to_status(status);
    }

    status = qspi_auto_polling_mem_ready_unsafe(hqspi, N25QXXA_SR_WREN, N25QXXA_SR_WREN);
    if (status != HAL_OK) {
        return hal_error_to_status(status);
    }

    return NO_ERROR;
}

// Must hold spiflash_mutex before calling.
static status_t qspi_dummy_cycles_cfg_unsafe(QSPI_HandleTypeDef *hqspi)
{
    uint8_t reg;
    HAL_StatusTypeDef status;

    /* Initialize the read volatile configuration register command */
    static const QSPI_CommandTypeDef init_rvcr_cmd = {
        .InstructionMode = QSPI_INSTRUCTION_1_LINE,
        .Instruction = READ_VOL_CFG_REG_CMD,
        .AddressMode = QSPI_ADDRESS_NONE,
        .AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
        .DataMode = QSPI_DATA_1_LINE,
        .DummyCycles = 0,
        .NbData = 1,
        .DdrMode = QSPI_DDR_MODE_DISABLE,
        .DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY,
        .SIOOMode = QSPI_SIOO_INST_EVERY_CMD
    };

    /* Configure the command */
    status = HAL_QSPI_Command(hqspi, &init_rvcr_cmd, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
    if (status != HAL_OK) {
        return hal_error_to_status(status);
    }

    /* Reception of the data */
    status = HAL_QSPI_Receive(hqspi, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
    if (status != HAL_OK) {
        return hal_error_to_status(status);
    }

    /* Enable write operations */
    status = qspi_write_enable_unsafe(hqspi);
    if (status != NO_ERROR) {
        return status;
    }

    /* Update volatile configuration register (with new dummy cycles) */
    static const QSPI_CommandTypeDef update_rvcr_cmd = {
        .InstructionMode = QSPI_INSTRUCTION_1_LINE,
        .Instruction = WRITE_VOL_CFG_REG_CMD,
        .AddressMode = QSPI_ADDRESS_NONE,
        .AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
        .DataMode = QSPI_DATA_1_LINE,
        .DummyCycles = 0,
        .NbData = 1,
        .DdrMode = QSPI_DDR_MODE_DISABLE,
        .DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY,
        .SIOOMode = QSPI_SIOO_INST_EVERY_CMD
    };
    MODIFY_REG(
        reg, N25QXXA_VCR_NB_DUMMY,
        (N25QXXA_DUMMY_CYCLES_READ_QUAD << POSITION_VAL(N25QXXA_VCR_NB_DUMMY)));

    /* Configure the write volatile configuration register command */
    status = HAL_QSPI_Command(hqspi, &update_rvcr_cmd, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
    if (status != HAL_OK) {
        return hal_error_to_status(status);
    }

    /* Transmission of the data */
    status = HAL_QSPI_Transmit(hqspi, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
    if (status != HAL_OK) {
        return hal_error_to_status(status);
    }

    return NO_ERROR;
}

// Must hold spiflash_mutex before calling.
static status_t qspi_auto_polling_mem_ready_unsafe(QSPI_HandleTypeDef *hqspi, uint8_t match, uint8_t mask)
{
    QSPI_AutoPollingTypeDef s_config;
    HAL_StatusTypeDef status;

    static const QSPI_CommandTypeDef s_command = {
        .InstructionMode = QSPI_INSTRUCTION_1_LINE,
        .Instruction = READ_STATUS_REG_CMD,
        .AddressMode = QSPI_ADDRESS_NONE,
        .AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
        .DataMode = QSPI_DATA_1_LINE,
        .DummyCycles = 0,
        .DdrMode = QSPI_DDR_MODE_DISABLE,
        .DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY,
        .SIOOMode = QSPI_SIOO_INST_EVERY_CMD,
        .NbData = 1
    };

    s_config.Match = match;
    s_config.Mask = mask;
    s_config.MatchMode = QSPI_MATCH_MODE_AND;
    s_config.StatusBytesSize = 1;
    s_config.Interval = 0x10;
    s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE;

    status = HAL_QSPI_AutoPolling_IT(hqspi, &s_command, &s_config);
    if (status != HAL_OK) {
        return hal_error_to_status(status);
    }
    event_wait(&st_event);

    return NO_ERROR;
}

// Must hold spiflash_mutex before calling.
static status_t qspi_reset_memory_unsafe(QSPI_HandleTypeDef *hqspi)
{
    QSPI_CommandTypeDef s_command;
    HAL_StatusTypeDef status;

    /* Initialize the reset enable command */
    s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
    s_command.Instruction = RESET_ENABLE_CMD;
    s_command.AddressMode = QSPI_ADDRESS_NONE;
    s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
    s_command.DataMode = QSPI_DATA_NONE;
    s_command.DummyCycles = 0;
    s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
    s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
    s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;

    /* Send the command */
    status = HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
    if (status != HAL_OK) {
        return hal_error_to_status(status);
    }

    /* Send the reset memory command */
    s_command.Instruction = RESET_MEMORY_CMD;
    status = HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
    if (status != HAL_OK) {
        return hal_error_to_status(status);
    }

    /* Configure automatic polling mode to wait the memory is ready */
    status = qspi_auto_polling_mem_ready_unsafe(hqspi, 0, N25QXXA_SR_WIP);
    if (status != NO_ERROR) {
        return hal_error_to_status(status);
    }

    return NO_ERROR;
}

static ssize_t spiflash_bdev_read_block(struct bdev *device, void *buf,
                                        bnum_t block, uint count)
{
    LTRACEF("device %p, buf %p, block %u, count %u\n",
            device, buf, block, count);

    if (!IS_ALIGNED((uintptr_t)buf, CACHE_LINE)) {
        DEBUG_ASSERT(IS_ALIGNED((uintptr_t)buf, CACHE_LINE));
        return ERR_INVALID_ARGS;
    }

    count = bio_trim_block_range(device, block, count);
    if (count == 0)
        return 0;

    QSPI_CommandTypeDef s_command;
    HAL_StatusTypeDef status;

    uint64_t largest_offset = (block + count) * device->block_size - 1;

    // /* Initialize the read command */
    s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
    s_command.Instruction = get_specialized_instruction(QUAD_OUT_FAST_READ_CMD, largest_offset);
    s_command.AddressMode = QSPI_ADDRESS_1_LINE;
    s_command.AddressSize = get_address_size(largest_offset);
    s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
    s_command.DataMode = QSPI_DATA_4_LINES;
    s_command.DummyCycles = N25QXXA_DUMMY_CYCLES_READ_QUAD;
    s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
    s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
    s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;

    s_command.NbData = device->block_size;

    ssize_t retcode = 0;

    mutex_acquire(&spiflash_mutex);

    s_command.Address = block * device->block_size;
    for (uint i = 0; i < count; i++) {

        status = HAL_QSPI_Command(&qspi_handle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
        if (status != HAL_OK) {
            retcode = hal_error_to_status(status);
            goto err;
        }

        // /* Reception of the data */
        status = qspi_rx_dma(&qspi_handle, &s_command, buf);
        if (status != HAL_OK) {
            retcode = hal_error_to_status(status);
            goto err;
        }

        buf += device->block_size;
        retcode += device->block_size;
        s_command.Address += device->block_size;
    }

err:
    mutex_release(&spiflash_mutex);
    return retcode;
}

static ssize_t spiflash_bdev_write_block(struct bdev *device, const void *_buf,
        bnum_t block, uint count)
{
    count = bio_trim_block_range(device, block, count);
    if (count == 0) {
        return 0;
    }

    const uint8_t *buf = _buf;

    mutex_acquire(&spiflash_mutex);

    ssize_t total_bytes_written = 0;
    for (; count > 0; count--, block++) {
        ssize_t bytes_written = qspi_write_page_unsafe(block * N25QXXA_PAGE_SIZE, buf);
        if (bytes_written < 0) {
            printf("qspi_write_page_unsafe failed\n");
            total_bytes_written = bytes_written;
            goto err;
        }

        buf += N25QXXA_PAGE_SIZE;
        total_bytes_written += bytes_written;
    }

err:
    mutex_release(&spiflash_mutex);
    return total_bytes_written;
}

static ssize_t spiflash_bdev_erase(struct bdev *device, off_t offset,
                                   size_t len)
{
    len = bio_trim_range(device, offset, len);
    if (len == 0) {
        return 0;
    }

    ssize_t total_erased = 0;

    mutex_acquire(&spiflash_mutex);

    // Choose an erase strategy based on the number of bytes being erased.
    if (len == device->total_size && offset == 0) {
        // Bulk erase the whole flash.
        total_erased = qspi_bulk_erase(device);
        goto finish;
    }

    // Erase as many sectors as necessary, then switch to subsector erase for
    // more fine grained erasure.
    while (((ssize_t)len - total_erased) >= N25QXXA_SECTOR_SIZE) {
        ssize_t erased = qspi_erase_sector(device, offset);
        if (erased < 0) {
            total_erased = erased;
            goto finish;
        }
        total_erased += erased;
        offset += erased;
    }

    while (total_erased < (ssize_t)len) {
        ssize_t erased = qspi_erase_subsector(device, offset);
        if (erased < 0) {
            total_erased = erased;
            goto finish;
        }
        total_erased += erased;
        offset += erased;
    }

finish:
    mutex_release(&spiflash_mutex);
    return total_erased;
}

static int spiflash_ioctl(struct bdev *device, int request, void *argp)
{
    int ret = NO_ERROR;

    switch (request) {
        case BIO_IOCTL_GET_MEM_MAP:
            /* put the device into linear mode */
            ret = qspi_enable_linear();
            // Fallthrough.
        case BIO_IOCTL_GET_MAP_ADDR:
            if (argp)
                *(void **)argp = (void *)QSPI_BASE;
            break;
        case BIO_IOCTL_PUT_MEM_MAP:
            ret = qspi_disable_linear();
            break;
        default:
            ret = ERR_NOT_SUPPORTED;
    }

    return ret;
}

static ssize_t qspi_write_page_unsafe(uint32_t addr, const uint8_t *data)
{
    if (!IS_ALIGNED(addr, N25QXXA_PAGE_SIZE)) {
        return ERR_INVALID_ARGS;
    }

    HAL_StatusTypeDef status;

    QSPI_CommandTypeDef s_command = {
        .InstructionMode   = QSPI_INSTRUCTION_1_LINE,
        .Instruction       = get_specialized_instruction(QUAD_IN_FAST_PROG_CMD, addr),
        .AddressMode       = QSPI_ADDRESS_1_LINE,
        .AddressSize       = get_address_size(addr),
        .AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
        .DataMode          = QSPI_DATA_4_LINES,
        .DummyCycles       = 0,
        .DdrMode           = QSPI_DDR_MODE_DISABLE,
        .DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY,
        .SIOOMode          = QSPI_SIOO_INST_EVERY_CMD,
        .Address           = addr,
        .NbData            = N25QXXA_PAGE_SIZE
    };

    status_t write_enable_result = qspi_write_enable_unsafe(&qspi_handle);
    if (write_enable_result != NO_ERROR) {
        return write_enable_result;
    }

    status = HAL_QSPI_Command(&qspi_handle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
    if (status != HAL_OK) {
        return hal_error_to_status(status);
    }

    status = qspi_tx_dma(&qspi_handle, &s_command, (uint8_t *)data);
    if (status != HAL_OK) {
        return hal_error_to_status(status);
    }

    status_t auto_polling_mem_ready_result =
        qspi_auto_polling_mem_ready_unsafe(&qspi_handle, 0, N25QXXA_SR_WIP);
    if (auto_polling_mem_ready_result != NO_ERROR) {
        return auto_polling_mem_ready_result;
    }

    return N25QXXA_PAGE_SIZE;
}

status_t qspi_flash_init(size_t flash_size)
{
    status_t result = NO_ERROR;

    event_init(&cmd_event, false, EVENT_FLAG_AUTOUNSIGNAL);
    event_init(&tx_event, false, EVENT_FLAG_AUTOUNSIGNAL);
    event_init(&rx_event, false, EVENT_FLAG_AUTOUNSIGNAL);
    event_init(&st_event, false, EVENT_FLAG_AUTOUNSIGNAL);

    mutex_init(&spiflash_mutex);
    result = mutex_acquire(&spiflash_mutex);
    if (result != NO_ERROR) {
        return result;
    }

    qspi_handle.Instance = QUADSPI;

    HAL_StatusTypeDef status;

    // Enable the QuadSPI memory interface clock
    __HAL_RCC_QSPI_CLK_ENABLE();

    // Reset the QuadSPI memory interface
    __HAL_RCC_QSPI_FORCE_RESET();
    __HAL_RCC_QSPI_RELEASE_RESET();

    // Setup the QSPI Flash device.
    qspi_handle.Init.ClockPrescaler = 1;
    qspi_handle.Init.FifoThreshold = 4;
    qspi_handle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
    qspi_handle.Init.FlashSize = POSITION_VAL(flash_size) - 1;
    qspi_handle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_2_CYCLE;
    qspi_handle.Init.ClockMode = QSPI_CLOCK_MODE_0;
    qspi_handle.Init.FlashID = QSPI_FLASH_ID_1;
    qspi_handle.Init.DualFlash = QSPI_DUALFLASH_DISABLE;

    status = HAL_QSPI_Init(&qspi_handle);
    if (status != HAL_OK) {
        result = hal_error_to_status(status);
        goto err;
    }

    // enable the qspi interrupt
    HAL_NVIC_EnableIRQ(QUADSPI_IRQn);

    result = qspi_reset_memory_unsafe(&qspi_handle);
    if (result != NO_ERROR) {
        goto err;
    }

    result = qspi_dummy_cycles_cfg_unsafe(&qspi_handle);
    if (result != NO_ERROR) {
        goto err;
    }

    result = qspi_dma_init(&qspi_handle);
    if (result != NO_ERROR) {
        goto err;
    }

    device_state = QSPI_STATE_COMMAND;

    // Initialize the QSPI Flash and register it as a Block I/O device.
    geometry.erase_size = log2_uint(N25QXXA_SUBSECTOR_SIZE);
    geometry.erase_shift = log2_uint(N25QXXA_SUBSECTOR_SIZE);
    geometry.start = 0;
    geometry.size = flash_size;

    bio_initialize_bdev(&qspi_flash_device, device_name, N25QXXA_PAGE_SIZE,
                        (flash_size / N25QXXA_PAGE_SIZE), 1, &geometry,
                        BIO_FLAG_CACHE_ALIGNED_READS);

    // qspi_flash_device.read: Use default hook.
    qspi_flash_device.read_block = &spiflash_bdev_read_block;
    // qspi_flash_device.write has a default hook that will be okay
    qspi_flash_device.write_block = &spiflash_bdev_write_block;
    qspi_flash_device.erase = &spiflash_bdev_erase;
    qspi_flash_device.ioctl = &spiflash_ioctl;

    /* we erase to 0xff */
    qspi_flash_device.erase_byte = 0xff;

    bio_register_device(&qspi_flash_device);

err:
    mutex_release(&spiflash_mutex);
    return result;
}

status_t hal_error_to_status(HAL_StatusTypeDef hal_status)
{
    switch (hal_status) {
        case HAL_OK:
            return NO_ERROR;
        case HAL_ERROR:
            return ERR_GENERIC;
        case HAL_BUSY:
            return ERR_BUSY;
        case HAL_TIMEOUT:
            return ERR_TIMED_OUT;
        default:
            return ERR_GENERIC;
    }
}

static ssize_t qspi_erase(bdev_t *device, uint32_t block_addr, uint32_t instruction)
{
    if (instruction == BULK_ERASE_CMD && block_addr != 0) {
        // This call was probably not what the user intended since the
        // block_addr is irrelevant when performing a bulk erase.
        return ERR_INVALID_ARGS;
    }

    QSPI_CommandTypeDef erase_cmd;
    ssize_t num_erased_bytes;
    switch (instruction) {
        case SUBSECTOR_ERASE_CMD: {
            num_erased_bytes = N25QXXA_SUBSECTOR_SIZE;
            erase_cmd.AddressSize = get_address_size(block_addr);
            erase_cmd.Instruction = get_specialized_instruction(instruction, block_addr);
            erase_cmd.AddressMode = QSPI_ADDRESS_1_LINE;
            erase_cmd.Address     = block_addr;

            break;
        }
        case SECTOR_ERASE_CMD: {
            num_erased_bytes = N25QXXA_SECTOR_SIZE;
            erase_cmd.AddressSize = get_address_size(block_addr);
            erase_cmd.Instruction = get_specialized_instruction(instruction, block_addr);
            erase_cmd.AddressMode = QSPI_ADDRESS_1_LINE;
            erase_cmd.Address     = block_addr;

            break;
        }
        case BULK_ERASE_CMD: {
            num_erased_bytes = device->total_size;
            erase_cmd.AddressMode = QSPI_ADDRESS_NONE;
            erase_cmd.Instruction = instruction;
            break;
        }
        default: {
            // Instruction must be a valid erase instruction.
            return ERR_INVALID_ARGS;
        }
    }

    erase_cmd.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
    erase_cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
    erase_cmd.DataMode          = QSPI_DATA_NONE;
    erase_cmd.DummyCycles       = 0;
    erase_cmd.DdrMode           = QSPI_DDR_MODE_DISABLE;
    erase_cmd.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
    erase_cmd.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;

    /* Enable write operations */
    status_t qspi_write_enable_result = qspi_write_enable_unsafe(&qspi_handle);
    if (qspi_write_enable_result != NO_ERROR) {
        return qspi_write_enable_result;
    }

    /* Send the command */
    if (HAL_QSPI_Command(&qspi_handle, &erase_cmd, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
        return ERR_GENERIC;
    }

    /* Configure automatic polling mode to wait for end of erase */
    status_t auto_polling_mem_ready_result =
        qspi_auto_polling_mem_ready_unsafe(&qspi_handle, 0, N25QXXA_SR_WIP);
    if (auto_polling_mem_ready_result != NO_ERROR) {
        return auto_polling_mem_ready_result;
    }

    return num_erased_bytes;
}

static ssize_t qspi_bulk_erase(bdev_t *device)
{
    return qspi_erase(device, 0, BULK_ERASE_CMD);
}

static ssize_t qspi_erase_sector(bdev_t *device, uint32_t block_addr)
{
    return qspi_erase(device, block_addr, SECTOR_ERASE_CMD);
}

static ssize_t qspi_erase_subsector(bdev_t *device, uint32_t block_addr)
{
    return qspi_erase(device, block_addr, SUBSECTOR_ERASE_CMD);
}

static HAL_StatusTypeDef qspi_cmd(QSPI_HandleTypeDef *qspi_handle,
                                  QSPI_CommandTypeDef *s_command)
{
    HAL_StatusTypeDef result = HAL_QSPI_Command_IT(qspi_handle, s_command);

    if (result != HAL_OK) {
        return result;
    }

    event_wait(&cmd_event);
    return result;
}

static void setup_dma(DMA_Stream_TypeDef *stream, uint32_t peripheral_address,
                      uint32_t memory_address, uint32_t num_bytes,
                      uint32_t direction)
{
    stream->PAR = peripheral_address;
    stream->M0AR = memory_address;
    stream->NDTR = num_bytes;

    uint32_t dma_cr = 0;

    // Select Channel 3
    dma_cr |= DMA_CHANNEL_3;

    // Set the transfer priority.
    dma_cr |= DMA_SxCR_PL;

    // Enable auto memory pointer increment.
    dma_cr |= DMA_SxCR_MINC;

    if (direction == DMA_MEMORY_TO_PERIPH) {
        dma_cr |= DMA_SxCR_DIR_0;
    }

    // Turn on transfer complete and error interrupts.
    dma_cr |= DMA_SxCR_TCIE;
    dma_cr |= DMA_SxCR_TEIE;
    dma_cr |= DMA_SxCR_DMEIE;

    stream->CR = dma_cr;
}

/* IRQ Context */
void DMA_RxCpltCallback(void)
{
    event_signal(&rx_event, false);
}

/* IRQ Context */
void DMA_TxCpltCallback(void)
{
    event_signal(&tx_event, false);
}

/* IRQ Context */
void DMA_ErrorCallback(void)
{
    printf("DMA Error\n");
}

// Send data and wait for interrupt.
static HAL_StatusTypeDef qspi_tx_dma(QSPI_HandleTypeDef *qspi_handle, QSPI_CommandTypeDef *s_command, uint8_t *buf)
{
    MODIFY_REG(qspi_handle->Instance->CCR, QUADSPI_CCR_FMODE, 0);

    if (dma_disable(dma2_stream7) != NO_ERROR) {
        printf("Timed out while waiting for DMA Engine to disable.\n");
        return ERR_TIMED_OUT;
    }

    setup_dma(
        dma2_stream7,
        (uint32_t)&(qspi_handle->Instance->DR),
        (uint32_t)buf,
        s_command->NbData,
        DMA_MEMORY_TO_PERIPH
    );

    // Make sure cache is flushed to RAM before invoking the DMA controller.
    arch_clean_cache_range((addr_t)buf, s_command->NbData);

    cplt_callback = DMA_TxCpltCallback;

    // And we're off to the races...
    dma2_stream7->CR |= DMA_SxCR_EN;
    qspi_handle->Instance->CR |= QUADSPI_CR_DMAEN;

    event_wait(&tx_event);

    return HAL_OK;
}

// Send data and wait for interrupt.
static HAL_StatusTypeDef qspi_rx_dma(QSPI_HandleTypeDef *qspi_handle, QSPI_CommandTypeDef *s_command, uint8_t *buf)
{
    // Make sure the front and back of the buffer are cache aligned.
    DEBUG_ASSERT(IS_ALIGNED((uintptr_t)buf, CACHE_LINE));
    DEBUG_ASSERT(IS_ALIGNED(((uintptr_t)buf) + s_command->NbData, CACHE_LINE));

    MODIFY_REG(qspi_handle->Instance->CCR, QUADSPI_CCR_FMODE, QUADSPI_CCR_FMODE_0);

    if (dma_disable(dma2_stream7) != NO_ERROR) {
        printf("Timed out while waiting for DMA Engine to disable.\n");
        return ERR_TIMED_OUT;
    }

    setup_dma(
        dma2_stream7,
        (uint32_t)&(qspi_handle->Instance->DR),
        (uint32_t)buf,
        s_command->NbData,
        DMA_PERIPH_TO_MEMORY
    );

    cplt_callback = DMA_RxCpltCallback;

    arch_invalidate_cache_range((addr_t)buf, s_command->NbData);

    // And we're off to the races...
    dma2_stream7->CR |= DMA_SxCR_EN;
    uint32_t addr_reg = qspi_handle->Instance->AR;
    qspi_handle->Instance->AR = addr_reg;
    qspi_handle->Instance->CR |= QUADSPI_CR_DMAEN;

    event_wait(&rx_event);

    return HAL_OK;
}

void stm32_QUADSPI_IRQ(void)
{
    arm_cm_irq_entry();
    HAL_QSPI_IRQHandler(&qspi_handle);
    arm_cm_irq_exit(true);
}

void stm32_DMA2_Stream7_IRQ(void)
{
    arm_cm_irq_entry();

    // Make a copy of the interrupts that we're handling.
    uint32_t hisr = DMA2->HISR;

    // Xfer Complete?
    if (hisr & DMA_FLAG_TCIF3_7) {
        DMA2->HIFCR |= DMA_FLAG_TCIF3_7;

        qspi_handle.Instance->CR &= ~QUADSPI_CR_DMAEN;

        dma_disable(dma2_stream7);

        __HAL_QSPI_CLEAR_FLAG((&qspi_handle), QSPI_FLAG_TC);

        HAL_QSPI_Abort(&qspi_handle);
        qspi_handle.State = HAL_QSPI_STATE_READY;

        cplt_callback();
    }

    // Xfer Error?
    if (hisr & DMA_FLAG_TEIF3_7) {
        DMA2->HIFCR |= DMA_FLAG_TEIF3_7;
        DMA_ErrorCallback();
    }

    // Direct mode error?
    if (hisr & DMA_FLAG_DMEIF3_7) {
        DMA2->HIFCR |= DMA_FLAG_DMEIF3_7;
        DMA_ErrorCallback();
    }

    arm_cm_irq_exit(true);
}

/* IRQ Context */
void HAL_QSPI_CmdCpltCallback(QSPI_HandleTypeDef *hqspi)
{
    event_signal(&cmd_event, false);
}

/* IRQ Context */
void HAL_QSPI_StatusMatchCallback(QSPI_HandleTypeDef *hqspi)
{
    event_signal(&st_event, false);
}

/* IRQ Context */
void HAL_QSPI_ErrorCallback(QSPI_HandleTypeDef *hqspi)
{
    printf("HAL QSPI Error.\n");
}

status_t qspi_dma_init(QSPI_HandleTypeDef *hqspi)
{
    /* QSPI DMA Controller Clock */
    __HAL_RCC_DMA2_CLK_ENABLE();

    dma2_stream7 = DMA2_Stream7;

    HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);

    return NO_ERROR;
}

static uint32_t get_address_size(uint32_t address)
{
    if (address >= FOUR_BYTE_ADDR_THRESHOLD) {
        return QSPI_ADDRESS_32_BITS;
    }
    return QSPI_ADDRESS_24_BITS;
}

// Converts a 3 byte instruction into a 4 byte instruction if necessary.
static uint32_t get_specialized_instruction(uint32_t instruction, uint32_t address)
{
    if (address < FOUR_BYTE_ADDR_THRESHOLD) {
        return instruction;
    }

    switch (instruction) {
        case READ_CMD:
            return READ_4_BYTE_ADDR_CMD;
        case FAST_READ_CMD:
            return FAST_READ_4_BYTE_ADDR_CMD;
        case DUAL_OUT_FAST_READ_CMD:
            return DUAL_OUT_FAST_READ_4_BYTE_ADDR_CMD;
        case DUAL_INOUT_FAST_READ_CMD:
            return DUAL_INOUT_FAST_READ_4_BYTE_ADDR_CMD;
        case QUAD_OUT_FAST_READ_CMD:
            return QUAD_OUT_FAST_READ_4_BYTE_ADDR_CMD;
        case QUAD_INOUT_FAST_READ_CMD:
            return QUAD_INOUT_FAST_READ_4_BYTE_ADDR_CMD;
        case PAGE_PROG_CMD:
            return PAGE_PROG_4_BYTE_ADDR_CMD;
        case QUAD_IN_FAST_PROG_CMD:
            return QUAD_IN_FAST_PROG_4_BYTE_ADDR_CMD;
        case SUBSECTOR_ERASE_CMD:
            return SUBSECTOR_ERASE_4_BYTE_ADDR_CMD;
        case SECTOR_ERASE_CMD:
            return SECTOR_ERASE_4_BYTE_ADDR_CMD;
    }

    return instruction;
}

status_t qspi_enable_linear(void)
{
    status_t result = NO_ERROR;

    mutex_acquire(&spiflash_mutex);

    if (device_state == QSPI_STATE_LINEAR) {
        // Device is already in linear mode, nothing to be done.
        goto finish;
    }

    result = qspi_dummy_cycles_cfg_unsafe(&qspi_handle);

    static const QSPI_CommandTypeDef s_command = {
        .InstructionMode   = QSPI_INSTRUCTION_1_LINE,
        .AddressSize       = QSPI_ADDRESS_24_BITS,
        .AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
        .DdrMode           = QSPI_DDR_MODE_DISABLE,
        .DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY,
        .AddressMode       = QSPI_ADDRESS_1_LINE,
        .Instruction       = QUAD_OUT_FAST_READ_CMD,
        .DataMode          = QSPI_DATA_4_LINES,
        .DummyCycles       = 10,
        .SIOOMode          = QSPI_SIOO_INST_EVERY_CMD
    };

    QSPI_MemoryMappedTypeDef linear_mode_cfg = {
        .TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE,
    };

    HAL_StatusTypeDef hal_result = HAL_QSPI_MemoryMapped(&qspi_handle, &s_command, &linear_mode_cfg);
    if (hal_result != HAL_OK) {
        result = hal_error_to_status(hal_result);
        goto finish;
    }

    device_state = QSPI_STATE_LINEAR;

finish:
    mutex_release(&spiflash_mutex);
    return result;
}

status_t qspi_disable_linear(void)
{
    status_t result = NO_ERROR;

    mutex_acquire(&spiflash_mutex);

    if (device_state == QSPI_STATE_COMMAND) {
        // Device is already in Command mode, nothing to be done.
        goto finish;
    }

    result = hal_error_to_status(HAL_QSPI_Abort(&qspi_handle));
    if (result == NO_ERROR) {
        device_state = QSPI_STATE_COMMAND;
    }

finish:
    mutex_release(&spiflash_mutex);
    return result;
}


text:
package cmwell.ctrl.checkers

import cmwell.ctrl.ddata.DData
import cmwell.ctrl.hc.HealthActor
import cmwell.ctrl.utils.ProcUtil
import cmwell.ctrl.config.Config._
import com.typesafe.scalalogging.LazyLogging

import scala.util.{Failure, Success}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._

/**
  * Created by michael on 12/11/14.
  */
object CassandraChecker extends Checker with LazyLogging {
  override val storedStates: Int = 10

  private def getCassandraStatus(host: String = ""): ComponentState = {
    val pingIp = DData.getPingIp //HealthActor.getPingIp
    val com =
      if (host != "")
        s"$cmwellHome/conf/cas/cassandra-status-viewer $host"
      else if (pingIp != "")
        s"$cmwellHome/conf/cas/cassandra-status-viewer $pingIp"
      else
        s"$cmwellHome/conf/cas/cassandra-status-viewer"

    ProcUtil.executeCommand(com) match {
      case Success(res) =>
        val stats = res
          .split("\n")
          .map { r =>
            val t = r.split(" ")
            t(1) -> t(0)
          }
          .toMap

        val racks = res
          .split("\n")
          .map { r =>
            val t = r.split(" ")
            t(1) -> t(2)
          }
          .toMap
        val racksReversed = racks.groupBy { _._2 }.map { case (key, value) => (key, value.unzip._1) }
        CassandraOk(stats, racksReversed)
      case Failure(err) =>
        logger.error("Could not parse cassandra-status-viewer response", err)
        CassandraDown()
    }
  }

  override def check: Future[ComponentState] = {
    blocking {
      Future {
        getCassandraStatus()
      }
    }
  }

  def getReachableHost(hosts: Set[String]): Option[String] = {
    hosts.collectFirst {
      case host if (getCassandraStatus(host).isInstanceOf[CassandraOk]) => host
    }
  }
}

redpajama_set_name: RedPajamaGithub


text:
sudo apt-get install -y zsh curl gconf2
sudo chsh -s $(which zsh)
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"


text:
require.config({
  urlArgs: 'bust=' + cacheBuster,
  baseUrl: '/static/js',
  paths: {
    'jquery': 'vendor/jquery',
    'backbone': 'vendor/backbone',
    'underscore': 'vendor/underscore',

    'jobs-view': 'views/jobs/jobs-view',
    'executions-view': 'views/executions/executions-view',
    'logs-view': 'views/logs/logs-view',

    'jobs-collection': 'models/jobs',
    'executions-collection': 'models/executions',
    'logs-collection': 'models/logs'
  },

  shim: {
    'backbone': {
      deps: ['underscore', 'jquery'],
      exports: 'Backbone'
    }
  }
});

require(['jobs-view',
  'executions-view',
  'logs-view',
  'jobs-collection',
  'executions-collection',
  'logs-collection',
  'backbone'], function(JobsView,
                        ExecutionsView,
                        LogsView,
                        JobsCollection,
                        ExecutionsCollection,
                        LogsCollection) {
  'use strict';

  var jobsCollection = new JobsCollection();
  var executionsCollection = new ExecutionsCollection();
  var logsCollection = new LogsCollection();

  new JobsView({
    collection: jobsCollection
  });

  new ExecutionsView({
    collection: executionsCollection
  });

  new LogsView({
    collection: logsCollection
  });

  //
  // Initialize URL router
  //
  var AppRouter = Backbone.Router.extend({
    routes: {
      'jobs': 'jobsRoute',
      'executions': 'executionsRoute',
      'jobs/:jid': 'jobsRoute',
      'executions/:eid': 'executionsRoute',
      'logs': 'logsRoute',
      '*actions': 'defaultRoute'
    }
  });

  var switchTab = function(switchTo) {
    var pages = ['jobs', 'executions', 'logs'];
    _.each(pages, function(page) {
      $('#' + page + '-page-sidebar').hide();
      $('#' + page + '-page-content').hide();
      $('#' + page + '-tab').removeClass();
    });
    $('#' + switchTo + '-page-sidebar').show();
    $('#' + switchTo + '-page-content').show();
    $('#' + switchTo + '-tab').addClass('active');
  };

  var appRouter = new AppRouter;
  appRouter.on('route:jobsRoute', function(jobId) {
    switchTab('jobs');
    if (jobId) {
      jobsCollection.getJob(jobId);
    } else {
      jobsCollection.getJobs();
    }
  });

  appRouter.on('route:executionsRoute', function(executionId) {
    switchTab('executions');

    if (executionId) {
      executionsCollection.getExecution(executionId);
    } else {
      executionsCollection.getExecutions();
    }
  });

  appRouter.on('route:logsRoute', function() {
    switchTab('logs');
    logsCollection.getLogs();
  });

  appRouter.on('route:defaultRoute', function(actions) {
    // Anything else defaults to jobs view
    switchTab('jobs');
    jobsCollection.getJobs();
  });

  Backbone.history.start();
});


text:
// Copyright 2014 The Serviced Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build unit

package cmd

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	//	"sort"
	"strings"
	"testing"

	"github.com/control-center/serviced/cli/api"
	"github.com/control-center/serviced/dao"
	"github.com/control-center/serviced/domain"
	"github.com/control-center/serviced/domain/applicationendpoint"
	"github.com/control-center/serviced/domain/host"
	"github.com/control-center/serviced/domain/pool"
	"github.com/control-center/serviced/domain/service"
	"github.com/control-center/serviced/domain/servicedefinition"
	"github.com/control-center/serviced/utils"
)

const (
	NilService = "NilService"
)

var DefaultServiceAPITest = ServiceAPITest{
	errs:      make(map[string]error, 10),
	services:  DefaultTestServices,
	pools:     DefaultTestPools,
	hosts:     DefaultTestHosts,
	snapshots: DefaultTestSnapshots,
	endpoints: DefaultEndpoints,
}

var DefaultTestServices = []service.Service{
	{
		ID:             "test-service-1",
		Name:           "Zenoss",
		Startup:        "startup command 1",
		Instances:      0,
		InstanceLimits: domain.MinMax{0, 0, 0},
		ImageID:        "quay.io/zenossinc/tenantid1-core5x",
		PoolID:         "default",
		DesiredState:   int(service.SVCRun),
		Launch:         "auto",
		DeploymentID:   "Zenoss-resmgr",
		Runs: map[string]string{
			"hello":   "echo hello world",
			"goodbye": "echo goodbye world",
		},
		Commands: map[string]domain.Command{
			"hello": domain.Command{
				Command:         "echo hello world",
				Description:     "Just says 'hello world'.",
				CommitOnSuccess: false,
			},
			"goodbye": domain.Command{
				Command:         "echo goodbye world",
				Description:     "Just says 'goodbye world'.",
				CommitOnSuccess: false,
			},
		},
		Endpoints: []service.ServiceEndpoint{
			service.ServiceEndpoint{
				Application: "zproxy",
				Name:        "zproxy",
				PortList:    DefaultTestPublicEndpointPorts,
				PortNumber:  8080,
				Protocol:    "tcp",
				Purpose:     "export",
			},
			service.ServiceEndpoint{
				Application: "zope",
				Name:        "zope",
				PortNumber:  9080,
				Protocol:    "tcp",
				Purpose:     "import",
			},
		},
		ConfigFiles: map[string]servicedefinition.ConfigFile{
			"/etc/test.conf": servicedefinition.ConfigFile{
				Filename:    "/etc/test.conf",
				Owner:       "1001",
				Permissions: "600",
				Content:     "#-----test.conf\n\n# This is a test conf file.\n",
			},
		},
	}, {
		ID:             "test-service-2",
		Name:           "Zope",
		Startup:        "startup command 2",
		Instances:      1,
		InstanceLimits: domain.MinMax{1, 1, 1},
		ImageID:        "quay.io/zenossinc/tenantid2-core5x",
		PoolID:         "default",
		DesiredState:   int(service.SVCRun),
		Launch:         "auto",
		DeploymentID:   "Zenoss-core",
		Context: map[string]interface{}{
			"home.name":  "Alphas",
			"away.name":  "Bravos",
			"home.score": 19,
			"away.score": 12,
		},
	}, {
		ID:             "test-service-3",
		Name:           "zencommand",
		Startup:        "startup command 3",
		Instances:      2,
		InstanceLimits: domain.MinMax{2, 2, 2},
		ImageID:        "quay.io/zenossinc/tenantid1-opentsdb",
		PoolID:         "remote",
		DesiredState:   int(service.SVCRun),
		Launch:         "manual",
		DeploymentID:   "Zenoss-core",
	},
}

var DefaultEndpoints = []applicationendpoint.EndpointReport{
	{
		Endpoint: applicationendpoint.ApplicationEndpoint{
			ServiceID:     "test-service-2",
			InstanceID:    1,
			Application:   "endpointName1",
			Purpose:       "export",
			HostID:        "hostID1",
			HostIP:        "hostIP1",
			HostPort:      10,
			ContainerID:   "containerID1",
			ContainerIP:   "containerIP1",
			ContainerPort: 100,
		},
		Messages: []string{},
	}, {
		Endpoint: applicationendpoint.ApplicationEndpoint{
			ServiceID:     "test-service-2",
			InstanceID:    2,
			Application:   "endpointName2",
			Purpose:       "import",
			HostID:        "hostID2",
			HostIP:        "hostIP2",
			HostPort:      20,
			ContainerID:   "containerID2",
			ContainerIP:   "containerIP2",
			ContainerPort: 200,
		},
		Messages: []string{},
	},
}

var (
	ErrNoServiceFound = errors.New("no service found")
	ErrInvalidService = errors.New("invalid service")
	ErrCmdNotFound    = errors.New("command not found")
	ErrStub           = errors.New("stub for facade failed")
)

type ServiceAPITest struct {
	api.API
	errs      map[string]error
	services  []service.Service
	pools     []pool.ResourcePool
	hosts     []host.Host
	snapshots []dao.SnapshotInfo
	endpoints []applicationendpoint.EndpointReport
}

func InitServiceAPITest(args ...string) {
	c := New(DefaultServiceAPITest, utils.TestConfigReader(make(map[string]string)), MockLogControl{})
	c.exitDisabled = true
	c.Run(args)
}

func (t ServiceAPITest) GetAllServiceDetails() ([]service.ServiceDetails, error) {
	if t.errs["GetAllServiceDetails"] != nil {
		return nil, t.errs["GetAllServiceDetails"]
	}
	return servicesToServiceDetails(t.services), nil
}

func (t ServiceAPITest) ResolveServicePath(name string, noprefix bool) ([]service.ServiceDetails, error) {
	if t.errs["ResolveServicePath"] != nil {
		return nil, t.errs["ResolveServicePath"]
	}
	return serviceDetailsByName(strings.TrimRight(name, "/")), nil
}

func (t ServiceAPITest) GetResourcePools() ([]pool.ResourcePool, error) {
	if t.errs["GetResourcePools"] != nil {
		return nil, t.errs["GetResourcePools"]
	}
	return t.pools, nil
}

func (t ServiceAPITest) GetHosts() ([]host.Host, error) {
	if t.errs["GetHosts"] != nil {
		return nil, t.errs["GetHosts"]
	}
	return t.hosts, nil
}

func (t ServiceAPITest) GetHostMap() (map[string]host.Host, error) {
	if t.errs["GetHostMap"] != nil {
		return nil, t.errs["GetHostMap"]
	}
	return make(map[string]host.Host), nil
}

func (t ServiceAPITest) GetEndpoints(serviceID string, reportImports, reportExports, validate bool) ([]applicationendpoint.EndpointReport, error) {
	if t.errs["GetEndpoints"] != nil {
		return nil, t.errs["GetEndpoints"]
	} else if serviceID == "test-service-2" {
		return t.endpoints, nil
	}
	return []applicationendpoint.EndpointReport{}, nil
}

func (t ServiceAPITest) GetService(id string) (*service.Service, error) {
	if t.errs["GetService"] != nil {
		return nil, t.errs["GetService"]
	}

	for i, s := range t.services {
		if s.ID == id {
			return &t.services[i], nil
		}
	}
	return nil, nil
}

func (t ServiceAPITest) GetServiceDetails(id string) (*service.ServiceDetails, error) {
	if t.errs["GetServiceDetails"] != nil {
		return nil, t.errs["GetServiceDetails"]
	}

	for i, s := range t.services {
		if s.ID == id {
			details := serviceToServiceDetails(t.services[i])
			return &details, nil
		}
	}
	return nil, nil
}

func (t ServiceAPITest) AddService(config api.ServiceConfig) (*service.ServiceDetails, error) {
	if t.errs["AddService"] != nil {
		return nil, t.errs["AddService"]
	} else if config.Name == NilService {
		return nil, nil
	}

	endpoints := make([]service.ServiceEndpoint, len(*config.LocalPorts)+len(*config.RemotePorts))
	i := 0
	for _, e := range *config.LocalPorts {
		e.Purpose = "local"
		endpoints[i] = service.BuildServiceEndpoint(e)
		i++
	}
	for _, e := range *config.RemotePorts {
		e.Purpose = "remote"
		endpoints[i] = service.BuildServiceEndpoint(e)
		i++
	}

	s := service.ServiceDetails{
		ID:              fmt.Sprintf("%s-%s-%s", config.Name, config.ParentServiceID, config.ImageID),
		ParentServiceID: config.ParentServiceID,
		Name:            config.Name,
		ImageID:         config.ImageID,
		//Endpoints:       endpoints,
		Startup:        config.Command,
		Instances:      1,
		InstanceLimits: domain.MinMax{1, 1, 1},
	}

	return &s, nil
}

func (t ServiceAPITest) RemoveService(id string) error {
	if t.errs["RemoveService"] != nil {
		return t.errs["RemoveService"]
	}
	return nil
}

func (t ServiceAPITest) UpdateService(reader io.Reader) (*service.ServiceDetails, error) {
	var svc service.Service

	if err := json.NewDecoder(reader).Decode(&svc); err != nil {
		return nil, ErrInvalidService
	}

	if _, err := t.GetService(svc.ID); err != nil {
		return nil, err
	}

	details := serviceToServiceDetails(svc)
	return &details, nil
}

func (t ServiceAPITest) UpdateServiceObj(svc service.Service) (*service.ServiceDetails, error) {
	if _, err := t.GetService(svc.ID); err != nil {
		return nil, err
	}

	details := serviceToServiceDetails(svc)
	return &details, nil
}

func servicesToServiceDetails(svcs []service.Service) []service.ServiceDetails {
	detailsList := []service.ServiceDetails{}
	for _, svc := range svcs {
		details := serviceToServiceDetails(svc)
		detailsList = append(detailsList, details)
	}
	return detailsList
}

func serviceDetailsByName(name string) []service.ServiceDetails {
	for _, svc := range DefaultTestServices {
		if svc.Name == name || svc.ID == name {
			return servicesToServiceDetails([]service.Service{svc})
		}
	}
	return []service.ServiceDetails{}
}

func serviceToServiceDetails(svc service.Service) service.ServiceDetails {
	details := service.ServiceDetails{
		ID:              svc.ID,
		Name:            svc.Name,
		Description:     svc.Description,
		PoolID:          svc.PoolID,
		ImageID:         svc.ImageID,
		ParentServiceID: svc.ParentServiceID,
		Instances:       svc.Instances,
		InstanceLimits:  svc.InstanceLimits,
		RAMCommitment:   svc.RAMCommitment,
		Startup:         svc.Startup,
		DeploymentID:    svc.DeploymentID,
		DesiredState:    svc.DesiredState,
		Launch:          svc.Launch,
	}
	return details
}

func (t ServiceAPITest) StartService(cfg api.SchedulerConfig) (int, error) {
	if t.errs["StartService"] != nil {
		return 0, t.errs["StartService"]
	}
	return len(cfg.ServiceIDs), nil
}

func (t ServiceAPITest) RestartService(cfg api.SchedulerConfig) (int, error) {
	if t.errs["RestartService"] != nil {
		return 0, t.errs["RestartService"]
	}
	return len(cfg.ServiceIDs), nil
}

func (t ServiceAPITest) StopServiceInstance(serviceID string, instanceID int) error {
	if s, err := t.GetService(serviceID); err != nil {
		return err
	} else if s == nil {
		return errors.New("service not found")
	} else if s.Instances < instanceID {
		return errors.New("service not found")
	}
	return nil
}

func (t ServiceAPITest) StopService(cfg api.SchedulerConfig) (int, error) {
	for _, sid := range cfg.ServiceIDs {
		if s, err := t.GetService(sid); err != nil {
			return 0, err
		} else if s == nil {
			return 0, ErrNoServiceFound
		}
	}
	return len(cfg.ServiceIDs), nil
}

func (t ServiceAPITest) AssignIP(config api.IPConfig) error {
	if t.errs["AssignIP"] != nil {
		return t.errs["AssignIP"]
	}
	return nil
}

func (t ServiceAPITest) RemoveIP(args []string) error {
	if t.errs["RemoveIP"] != nil {
		return t.errs["RemoveIP"]
	}
	return nil
}

func (t ServiceAPITest) SetIP(config api.IPConfig) error {
	if t.errs["SetIP"] != nil {
		return t.errs["SetIP"]
	}
	return nil
}

func (t ServiceAPITest) StartShell(config api.ShellConfig) error {
	if s, err := t.GetService(config.ServiceID); err != nil {
		return err
	} else if s == nil {
		return ErrNoServiceFound
	}

	fmt.Printf("%s %s\n", config.Command, strings.Join(config.Args, " "))
	return nil
}

func (t ServiceAPITest) RunShell(config api.ShellConfig, stopChan chan struct{}) (int, error) {
	s, err := t.GetService(config.ServiceID)
	if err != nil {
		return 1, err
	} else if s == nil {
		return 1, ErrNoServiceFound
	}

	command, ok := s.Runs[config.Command]
	if !ok {
		return 1, ErrCmdNotFound
	}

	fmt.Printf("%s %s\n", command, strings.Join(config.Args, " "))
	return 0, nil
}

func (t ServiceAPITest) GetSnapshotsByServiceID(id string) ([]dao.SnapshotInfo, error) {
	if t.errs["GetSnapshotsByServiceID"] != nil {
		return nil, t.errs["GetSnapshotsByServiceID"]
	}

	var snapshots []dao.SnapshotInfo
	for _, s := range t.snapshots {
		if strings.HasPrefix(s.SnapshotID, id) {
			snapshots = append(snapshots, s)
		}
	}

	return snapshots, nil
}

func (t ServiceAPITest) AddSnapshot(config api.SnapshotConfig) (string, error) {
	if t.errs["AddSnapshot"] != nil {
		return "", t.errs["AddSnapshot"]
	}

	return fmt.Sprintf("%s-snapshot description=%q tags=%q", config.ServiceID, config.Message, config.Tag), nil
}

func (t ServiceAPITest) ClearEmergency(serviceID string) (int, error) {
	if t.errs["ClearEmergency"] != nil {
		return 0, t.errs["ClearEmergency"]
	}
	return 1, nil
}

func TestServicedCLI_CmdServiceList_one(t *testing.T) {
	serviceID := "test-service-1"

	expected, err := DefaultServiceAPITest.GetService(serviceID)
	if err != nil {
		t.Fatal(err)
	}

	var actual service.Service
	output := captureStdout(func() { InitServiceAPITest("serviced", "service", "list", serviceID) })
	if err := json.Unmarshal(output, &actual); err != nil {
		t.Fatalf("error unmarshaling resource: %s", err)
	}

	// Did you remember to update Service.Equals?
	if !actual.Equals(expected) {
		t.Fatalf("\ngot:\n%+v\nwant:\n%+v", actual, expected)
	}
}

func TestServicedCLI_CmdServiceList_all(t *testing.T) {
	expected, err := DefaultServiceAPITest.GetAllServiceDetails()
	if err != nil {
		t.Fatal(err)
	}

	var actual []*service.ServiceDetails
	output := captureStdout(func() { InitServiceAPITest("serviced", "service", "list", "--verbose") })
	if err := json.Unmarshal(output, &actual); err != nil {
		t.Fatalf("error unmarshaling resource: %s", err)
	}

	// Did you remember to update Service.Equals?
	if len(actual) != len(expected) {
		t.Fatalf("\ngot:\n%+v\nwant:\n%+v", actual, expected)
	}
	for i := range actual {
		if !actual[i].Equals(&expected[i]) {
			t.Fatalf("\ngot:\n%+v\nwant:\n%+v", actual, expected)
		}
	}
}

func ExampleServicedCLI_CmdServiceList() {
	// Gofmt cleans up the spaces at the end of each row
	InitServiceAPITest("serviced", "service", "list")
}

func ExampleServicedCLI_CmdServiceList_fail() {
	DefaultServiceAPITest.errs["GetAllServiceDetails"] = ErrInvalidService
	defer func() { DefaultServiceAPITest.errs["GetAllServiceDetails"] = nil }()
	DefaultServiceAPITest.errs["ResolveServicePath"] = ErrInvalidService
	defer func() { DefaultServiceAPITest.errs["ResolveServicePath"] = nil }()
	// Error retrieving service
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "list", "test-service-0") })
	// Error retrieving all services
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "list") })

	// Output:
	// invalid service
	// invalid service
}

func ExampleServicedCLI_CmdServiceList_err() {
	DefaultServiceAPITest.services = nil
	defer func() { DefaultServiceAPITest.services = DefaultTestServices }()
	// Service not found
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "list", "test-service-0") })
	// No Services found
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "list") })

	// Output:
	// service not found
	// no services found
}

func ExampleServicedCLI_CmdServiceList_complete() {
	InitServiceAPITest("serviced", "service", "list", "--generate-bash-completion")

	DefaultServiceAPITest.errs["GetAllServiceDetails"] = ErrInvalidService
	defer func() { DefaultServiceAPITest.errs["GetAllServiceDetails"] = nil }()
	InitServiceAPITest("serviced", "service", "list", "--generate-bash-completion")

	// Output:
	// test-service-1
	// test-service-2
	// test-service-3
}

func ExampleServicedCLI_CmdServiceAdd() {
	InitServiceAPITest("serviced", "service", "add", "--parent-id", "test-service-1", "test-service", "test-image", "bash -c lsof")

	// Output:
	// test-service-test-service-1-test-image
}

func ExampleServicedCLI_CmdServiceAdd_usage() {
	InitServiceAPITest("serviced", "service", "add")

	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    add - Adds a new service
	//
	// USAGE:
	//    command add [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service add NAME IMAGEID COMMAND
	//
	// OPTIONS:
	//    -p 		`-p option -p option` Expose a port for this service (e.g. -p tcp:3306:mysql)
	//    -q 		`-q option -q option` Map a remote service port (e.g. -q tcp:3306:mysql)
	//    --parent-id 	Parent service ID for which this service relates
}

func ExampleServicedCLI_CmdServiceAdd_fail() {
	DefaultServiceAPITest.errs["AddService"] = ErrStub
	defer func() { DefaultServiceAPITest.errs["AddService"] = nil }()
	pipeStderr(func() {
		InitServiceAPITest("serviced", "service", "add", "--parent-id", "test-service-1", "test-service", "test-image", "bash -c lsof")
	})

	// Output:
	// stub for facade failed
}

func ExampleServicedCLI_CmdServiceAdd_missingParentArg() {
	pipeStderr(func() {
		InitServiceAPITest("serviced", "service", "add", "test-service", "test-pool", "test-image", "bash -c lsof")
	})

	// Output:
	// Must specify a parent service ID
}

func ExampleServicedCLI_CmdServiceAdd_parentNotFound() {
	pipeStderr(func() {
		InitServiceAPITest("serviced", "service", "add", "--parent-id", "test-parent", NilService, "test-image", "bash -c lsof")
	})

	// Output:
	// Error searching for parent service: service not found
}

func ExampleServicedCLI_CmdServiceRemove() {
	InitServiceAPITest("serviced", "service", "remove", "test-service-1")
	InitServiceAPITest("serviced", "service", "remove", "test-service-2")

	// Output:
	// test-service-1
	// test-service-2
}

func ExampleServicedCLI_CmdServiceRemove_usage() {
	InitServiceAPITest("serviced", "service", "remove")

	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    remove - Removes an existing service
	//
	// USAGE:
	//    command remove [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service remove SERVICEID
	//
	// OPTIONS:
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches

}

func ExampleServicedCLI_CmdServiceRemove_err() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "remove", "test-service-0") })

	// Output:
	// service not found
}

func ExampleServicedCLI_CmdServiceRemove_failed() {
	DefaultServiceAPITest.errs["RemoveService"] = ErrStub
	defer func() { DefaultServiceAPITest.errs["RemoveService"] = nil }()

	pipeStderr(func() { InitServiceAPITest("serviced", "service", "remove", "test-service-1") })

	// Output:
	// test-service-1: stub for facade failed
}

func ExampleServicedCLI_CmdServiceRemove_complete() {
	InitServiceAPITest("serviced", "service", "remove", "--generate-bash-completion")
	fmt.Println("")
	InitServiceAPITest("serviced", "service", "remove", "test-service-2", "--generate-bash-completion")

	// Output:
	// test-service-1
	// test-service-2
	// test-service-3
	//
	// test-service-1
	// test-service-3
}

func ExampleServicedCLI_CmdServiceEdit() {
	// This opens an editor, so I am not sure how to test this yet :)
	InitServiceAPITest("serviced", "service", "edit", "test-service-1")
}

func ExampleServicedCLI_CmdServiceEdit_usage() {
	// In the output, under OPTIONS, if you see a 'vim' or 'emacs',
	// it is because you have the following
	// environment vairable set: GIT_EDITOR
	// echo $GIT_EDITOR
	InitServiceAPITest("serviced", "service", "edit")

	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    edit - Edits an existing service in a text editor
	//
	// USAGE:
	//    command edit [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service edit SERVICEID
	//
	// OPTIONS:
	//    --editor, -e 		Editor used to update the service definition
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServicedCLI_CmdServiceEdit_fail() {
	DefaultServiceAPITest.errs["GetAllServiceDetails"] = ErrInvalidService
	defer func() { DefaultServiceAPITest.errs["GetAllServiceDetails"] = nil }()
	DefaultServiceAPITest.errs["ResolveServicePath"] = ErrInvalidService
	defer func() { DefaultServiceAPITest.errs["ResolveServicePath"] = nil }()
	// Failed to get service
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "edit", "test-service-0") })
	// TODO: Failed to update service

	// Output:
	// invalid service
}

func ExampleServicedCLI_CmdServiceEdit_err() {
	// Service not found
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "edit", "test-service-0") })
	// TODO: Nil Service after update

	// Output:
	// service not found
}

func ExampleServicedCLI_CmdServiceConfigList_usage() {
	InitServiceAPITest("serviced", "service", "config", "list")
	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    list - List all config files for a given service, or the contents of one named file
	//
	// USAGE:
	//    command list [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service config list SERVICEID [FILENAME]
	//
	// OPTIONS:
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServicedCLI_CmdServiceConfigList() {
	InitServiceAPITest("serviced", "service", "config", "list", "test-service-1")
	// Output:
	// {
	//    "ConfigFiles": [
	//      "/etc/test.conf"
	//    ]
	//  }
}

func ExampleServicedCLI_CmdServiceConfigListSingle() {
	InitServiceAPITest("serviced", "service", "config", "list", "test-service-1", "/etc/test.conf")
	// Output:
	// #-----test.conf
	//
	// # This is a test conf file.
	//
}

func ExampleServicedCLI_CmdServiceConfigList_noservice() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "config", "list", "test-service-0") })
	// Output:
	// service not found
}

func ExampleServicedCLI_CmdServiceConfigListSingle_nofile() {
	pipeStderr(func() {
		InitServiceAPITest("serviced", "service", "config", "list", "test-service-1", "/etc/nothere.conf")
	})
	// Output:
	// Config file /etc/nothere.conf not found.
}

func ExampleServicedCLI_CmdServiceConfigEdit_usage() {
	InitServiceAPITest("serviced", "service", "config", "edit")
	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    edit - Edit one config file for a given service
	//
	// USAGE:
	//    command edit [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service config edit SERVICEID FILENAME
	//
	// OPTIONS:
	//    --editor, -e 		Editor used to update the config file
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServicedCLI_CmdServiceConfigEdit_noservice() {
	pipeStderr(func() {
		InitServiceAPITest("serviced", "service", "config", "edit", "test-service-0", "/etc/nothere.conf")
	})
	// Output:
	// service not found
}

func ExampleServicedCLI_CmdServiceConfigEdit_nofile() {
	// File not found
	pipeStderr(func() {
		InitServiceAPITest("serviced", "service", "config", "edit", "test-service-1", "/etc/nothere.conf")
	})

	// Output:
	// Config file /etc/nothere.conf not found.
}

func ExampleServicedCLI_CmdServiceConfigEdit() {
	// Hard to test that an editor was opened.
	InitServiceAPITest("serviced", "service", "config", "edit", "test-service-1", "/etc/test.conf")
}

func ExampleServicedCLI_CmdServiceAssignIPs() {
	// Auto-assign
	InitServiceAPITest("serviced", "service", "assign-ip", "test-service-1")
	// Manual-assign
	InitServiceAPITest("serviced", "service", "assign-ip", "test-service-2", "127.0.0.1")

	// Output:
	//
}

func ExampleServicedCLI_CmdServiceAssignIPs_usage() {
	InitServiceAPITest("serviced", "service", "assign-ip")

	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    assign-ip - Assigns an IP address to a service's endpoints requiring an explicit IP address
	//
	// USAGE:
	//    command assign-ip [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service assign-ip SERVICEID [IPADDRESS]
	//
	// OPTIONS:
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServicedCLI_CmdServiceAssignIPs_fail() {
	DefaultServiceAPITest.errs["AssignIP"] = ErrInvalidService
	defer func() { DefaultServiceAPITest.errs["AssignIP"] = nil }()
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "assign-ip", "test-service-3") })

	// Output:
	// invalid service
}

func ExampleServicedCLI_CmdServiceAssignIPs_err() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "assign-ip", "test-service-0", "100.99.88.1") })

	// Output:
	// service not found
}

func ExampleServicedCLI_CmdServiceRemoveIPs() {
	//Remove assignments
	InitServiceAPITest("serviced", "service", "remove-ip", "test-service-1", "test-endpoint")
	// Output:
	//
}

func ExampleServicedCLI_CmdServiceRemoveIPs_usage() {
	InitServiceAPITest("serviced", "service", "remove-ip")

	// Incorrect Usage.

	// NAME:
	//    remove-ip - Remove the IP assignment of a service's endpoints

	// USAGE:
	//    ommand remove-ip [command options] [arguments...]

	// DESCRIPTION:
	//    serviced service remove-ip <SERVICEID> <ENDPOINTNAME>

	// OPTIONS:

}

func ExampleServicedCLI_CmdServiceRemoveIPs_fail() {
	DefaultServiceAPITest.errs["RemoveIP"] = ErrInvalidService
	defer func() { DefaultServiceAPITest.errs["RemoveIP"] = nil }()
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "remove-ip", "test-service-3") })

	// Incorrect Usage.

	// NAME:
	//    remove-ip - Remove the IP assignment of a service's endpoints

	// USAGE:
	//    ommand remove-ip [command options] [arguments...]

	// DESCRIPTION:
	//    serviced service remove-ip <SERVICEID> <ENDPOINTNAME>

	// OPTIONS:
}

func ExampleServicedCLI_CmdServiceRemoveIPs_err() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "remove-ip", "test-service-0", "test-endpoint-1") })

	// Output:
	// service not found
}

func ExampleServicedCLI_CmdServiceSetIPs() {
	InitServiceAPITest("serviced", "service", "set-ip", "test-service-1", "test-endpoint", "127.0.0.1", "--port=8080", "--proto=tcp")

	// Output:
	//
}

func ExampleServicedCLI_CmdServiceSetIPs_usage() {
	InitServiceAPITest("serviced", "service", "set-ip")

	// Incorrect Usage.

	//NAME:
	//   set-ip - Setting an IP address to a service's endpoints requiring an explicit IP address. If ip is not provided it does an automatic assignment

	// USAGE:
	//    command set-ip [command options] [arguments...]

	// DESCRIPTION:
	//    serviced service set-ip <SERVICEID> <ENDPOINTNAME> [ADDRESS] [--port=PORT] [--proto=PROTOCOL]

	// OPTIONS:
	//    --port '0'   determine the port your service will use
	//    --proto      determine the port protocol your service will use

}

func ExampleServicedCLI_CmdServiceSetIPs_fail() {
	DefaultServiceAPITest.errs["SetIP"] = ErrInvalidService
	defer func() { DefaultServiceAPITest.errs["SetIP"] = nil }()
	pipeStderr(func() {
		InitServiceAPITest("serviced", "service", "set-ip", "test-service-2", "test-endpoint", "127.0.0.1", "--port=8080", "--proto=tcp")
	})

	// Output:
	// invalid service
}

func ExampleServicedCLI_CmdServiceSetIPs_err() {
	pipeStderr(func() {
		InitServiceAPITest("serviced", "service", "set-ip", "test-service-0", "test-endpoint", "127.0.0.1")
	})

	// Please specify the valid port number.

	// NAME:
	//    set-ip - Setting an IP address to a service's endpoints requiring an explicit IP address. If ip is not provided it does an automatic assignment

	// USAGE:
	//    command set-ip [command options] [arguments...]

	// DESCRIPTION:
	//    serviced service set-ip <SERVICEID> <ENDPOINTNAME> [ADDRESS] [--port=PORT] [--proto=PROTOCOL]

	// OPTIONS:
	//    --port '0'   determine the port your service will use
	//    --proto      determine the port protocol your service will use
}

func ExampleServicedCLI_CmdServiceStart_usage() {
	InitServiceAPITest("serviced", "service", "start")

	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    start - Starts one or more services
	//
	// USAGE:
	//    command start [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service start SERVICEID ...
	//
	// OPTIONS:
	//    --auto-launch		Recursively schedules child services
	//    --sync, -s			Schedules services synchronously
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServicedCLI_CmdServiceStart_fail() {
	DefaultServiceAPITest.errs["StartService"] = ErrStub
	defer func() { DefaultServiceAPITest.errs["StartService"] = nil }()
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "start", "test-service-1") })

	// Output:
	// stub for facade failed
}

func ExampleServicedCLI_CmdServiceStart_err() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "start", "test-service-0") })

	// Output:
	// service not found
}

func ExampleServicedCLI_CmdServiceStart() {
	InitServiceAPITest("serviced", "service", "start", "test-service-2")
	InitServiceAPITest("serviced", "service", "start", "test-service-1", "test-service-2")

	// Output:
	// Scheduled 1 service(s) to start
	// Scheduled 2 service(s) to start
}

func ExampleServicedCLI_CmdServiceRestart_usage() {
	InitServiceAPITest("serviced", "service", "restart")

	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    restart - Restarts one or more services
	//
	// USAGE:
	//    command restart [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service restart { SERVICEID | INSTANCEID } ...
	//
	// OPTIONS:
	//    --auto-launch		Recursively schedules child services
	//    --sync, -s			Schedules services synchronously
	//    --rebalance			Stops all instances before restarting them, instead of performing a rolling restart
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServicedCLI_CmdServiceRestart_fail() {
	DefaultServiceAPITest.errs["ResolveServicePath"] = ErrInvalidService
	defer func() { DefaultServiceAPITest.errs["ResolveServicePath"] = nil }()
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "restart", "test-service-1") })

	// Output:
	// invalid service
}

func ExampleServicedCLI_CmdServiceRestart_err() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "restart", "test-service-0") })    // Non-existant service
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "restart", "test-service-3/4") })  // Non-existant instance
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "restart", "test-service-3/a") })  // Non-numeric instance number
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "restart", "test-service-3/0b") }) // Non-numeric instance number

	// Output:
	// service not found
	// service not found
	// service not found
	// service not found
}

func ExampleServicedCLI_CmdServiceRestart() {
	InitServiceAPITest("serviced", "service", "restart", "test-service-2")
	InitServiceAPITest("serviced", "service", "restart", "test-service-3/1")                     // Specific instance
	InitServiceAPITest("serviced", "service", "restart", "test-service-2", "test-service-3/1")   // Both
	InitServiceAPITest("serviced", "service", "restart", "test-service-2", "test-service-3")     // 2 services
	InitServiceAPITest("serviced", "service", "restart", "test-service-3/0", "test-service-3/1") // 2 instances

	// Output:
	// Restarting 1 service(s)
	// Restarting instance test-service-3/1
	// Restarting 1 service(s)
	// Restarting instance test-service-3/1
	// Restarting 2 service(s)
	// Restarting instance test-service-3/0
	// Restarting instance test-service-3/1

}

func ExampleServicedCLI_CmdServiceStop_usage() {
	InitServiceAPITest("serviced", "service", "stop")

	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    stop - Stops one or more services
	//
	// USAGE:
	//    command stop [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service stop SERVICEID ...
	//
	// OPTIONS:
	//    --auto-launch		Recursively schedules child services
	//    --sync, -s			Schedules services synchronously
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServicedCLI_CmdServiceStop_err() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "stop", "test-service-0") })

	// Output:
	// service not found
}

func ExampleServicedCLI_CmdServiceStop() {
	InitServiceAPITest("serviced", "service", "stop", "test-service-2")
	InitServiceAPITest("serviced", "service", "stop", "test-service-1", "test-service-2")

	// Output:
	// Scheduled 1 service(s) to stop
	// Scheduled 2 service(s) to stop
}

func ExampleServicedCLI_CmdServiceProxy_usage() {
	// FIXME: Non-reproducible error on buildbox
	InitServiceAPITest("serviced", "service", "proxy")

	// Incorrect Usage.
	//
	// NAME:
	//    proxy - Starts a server proxy for a container
	//
	// USAGE:
	//    command proxy [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service proxy SERVICEID COMMAND
	//
	// OPTIONS:
	//    --muxport '22250'			multiplexing port to use
	//    --mux				enable port multiplexing
	//    --keyfile 				path to private key file (defaults to compiled in private keys
	//    --certfile 				path to public certificate file (defaults to compiled in public cert)
	//    --endpoint '10.87.103.1:4979'	serviced endpoint address
	//    --autorestart			restart process automatically when it finishes
	//    --logstash				forward service logs via filebeat
	//
}

func ExampleServicedCLI_CmdServiceShell() {
	InitServiceAPITest("serviced", "service", "shell", "test-service-1", "some", "command")

	// Output:
	// some command
}

/*
removed test due to --endpoint
func ExampleServicedCLI_CmdServiceShell_usage() {
	// FIXME: IP in --endpoint is too specific
	InitServiceAPITest("serviced", "service", "shell")

	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    shell - Starts a service instance
	//
	// USAGE:
	//    command shell [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service shell SERVICEID [COMMAND]
	//
	// OPTIONS:
	//    --saveas, -s 				saves the service instance with the given name
	//    --interactive, -i				runs the service instance as a tty
	//    --mount '--mount option --mount option'	bind mount: HOST_PATH[,CONTAINER_PATH]
	//    --endpoint '10.87.103.1:4979'		endpoint for remote serviced (example.com:4979)
	//    -v '0'					log level for V logs

}
*/

func ExampleServicedCLI_CmdServiceShell_err() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "shell", "test-service-0", "some", "command") })

	// Output:
	// service not found
	// exit code 1
}

/*func ExampleServicedCLI_CmdServiceRun_list() {
	output := captureStdout(func(){InitServiceAPITest( "serviced", "service", "run", "test-service-1")})
	actual := strings.Split(string(output[:]), "\n")
	sort.Strings(actual)

	for _, item := range actual {
		fmt.Printf("%s\n", item)
	}

	// Output:
	// goodbye
	// hello
}
*/
func ExampleServicedCLI_CmdServiceRun_exec_aloha() {
	InitServiceAPITest("serviced", "service", "run", "-i", "test-service-1", "aloha")

	// Output:
	// Command "aloha" not available.
	// Available commands for Zenoss:
	//     goodbye               Just says 'goodbye world'.
	//     hello                 Just says 'hello world'.
}

func ExampleServicedCLI_CmdServiceRun_exec_hello() {
	InitServiceAPITest("serviced", "service", "run", "-i", "test-service-1", "hello")

	// Output:
	// echo hello world
}

func ExampleServicedCLI_CmdServiceRun_help() {
	InitServiceAPITest("serviced", "service", "run", "-i", "test-service-1", "help")

	// Output:
	// Available commands for Zenoss:
	//     goodbye               Just says 'goodbye world'.
	//     hello                 Just says 'hello world'.
}

/*
removed test due to --endpoint
func ExampleServicedCLI_CmdServiceRun_usage() {
	InitServiceAPITest("serviced", "service", "run")

	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    run - Runs a service command in a service instance
	//
	// USAGE:
	//    command run [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service run SERVICEID COMMAND [ARGS]
	//
	// OPTIONS:
	//    --interactive, -i				runs the service instance as a tty
	//    --mount '--mount option --mount option'	bind mount: HOST_PATH[,CONTAINER_PATH]
	//    --endpoint '10.87.103.1:4979'		endpoint for remote serviced (example.com:4979)
}
*/

func ExampleServicedCLI_CmdServiceRun_err() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "run", "test-service-0", "goodbye") })

	// Output:
	// service not found
	// exit code 1
}

func ExampleServicedCLI_CmdServiceRun_complete() {
	// FIXME: Does not print run commands
	InitServiceAPITest("serviced", "service", "run", "--generate-bash-completion")
	fmt.Println("")
	InitServiceAPITest("serviced", "service", "run", "test-service-1", "--generate-bash-completion")
	fmt.Println("")
	InitServiceAPITest("serviced", "service", "run", "test-service-2", "--generate-bash-completion")

	// test-service-1
	// test-service-2
	// test-service-3
	//
	// hello
	// goodbye
}

// TODO: ServicedCLI.CmdServiceAttach
// TODO: ServicedCLI.CmdServiceAction

func ExampleServicedCLI_CmdServiceListSnapshots() {
	InitServiceAPITest("serviced", "service", "list-snapshots", "test-service-1")

	// Output:
	// test-service-1-snapshot-1 description 1
	// test-service-1-snapshot-2 description 2
	// test-service-1-invalid [DEPRECATED]

}

func TestServicedCLI_CmdServiceListSnapshots_ShowTagsShort(t *testing.T) {
	output := captureStdout(func() { InitServiceAPITest("serviced", "service", "list-snapshots", "test-service-1", "-t") })
	expected :=
		"Snapshot                                 Description        Tags" +
			"\ntest-service-1-snapshot-1                description 1      tag-1" +
			"\ntest-service-1-snapshot-2                description 2      tag-2,tag-3" +
			"\ntest-service-1-invalid [DEPRECATED]"

	outStr := TrimLines(fmt.Sprintf("%s", output))
	expected = TrimLines(expected)

	if expected != outStr {
		t.Fatalf("\ngot:\n%s\nwant:\n%s", outStr, expected)
	}
}

func TestServicedCLI_CmdServiceListSnapshots_ShowTagsLong(t *testing.T) {
	output := captureStdout(func() { InitServiceAPITest("serviced", "service", "list-snapshots", "test-service-1", "--show-tags") })
	expected :=
		"Snapshot                                 Description        Tags" +
			"\ntest-service-1-snapshot-1                description 1      tag-1" +
			"\ntest-service-1-snapshot-2                description 2      tag-2,tag-3" +
			"\ntest-service-1-invalid [DEPRECATED]"

	outStr := TrimLines(fmt.Sprintf("%s", output))
	expected = TrimLines(expected)

	if expected != outStr {
		t.Fatalf("\ngot:\n%s\nwant:\n%s", outStr, expected)
	}
}

func ExampleServicedCLI_CmdServiceListSnapshots_usage() {
	InitServiceAPITest("serviced", "service", "list-snapshots")

	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    list-snapshots - Lists the snapshots for a service
	//
	// USAGE:
	//    command list-snapshots [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service list-snapshots SERVICEID
	//
	// OPTIONS:
	//    --show-tags, -t		shows the tags associated with each snapshot
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServicedCLI_CmdServiceListSnapshots_fail() {
	DefaultServiceAPITest.errs["GetSnapshotsByServiceID"] = ErrStub
	defer func() { DefaultServiceAPITest.errs["GetSnapshotsByServiceID"] = nil }()
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "list-snapshots", "test-service-1") })

	// Output:
	// stub for facade failed
}

func ExampleServicedCLI_CmdServiceListSnapshots_err() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "list-snapshots", "test-service-3") })

	// Output:
	// no snapshots found
}

func ExampleServicedCLI_CmdServiceSnapshot() {
	InitServiceAPITest("serviced", "service", "snapshot", "test-service-2")

	// Output:
	// test-service-2-snapshot description="" tags=""
}

func ExampleServicedCLI_CmdServiceSnapshot_withDescription() {
	InitServiceAPITest("serviced", "service", "snapshot", "test-service-2", "-d", "some description")

	// Output:
	// test-service-2-snapshot description="some description" tags=""
}

func ExampleServicedCLI_CmdServiceSnapshot_withDescriptionAndTag() {
	InitServiceAPITest("serviced", "service", "snapshot", "test-service-2", "-d", "some description", "-t", "tag1")

	// Output:
	// test-service-2-snapshot description="some description" tags="tag1"
}

func ExampleServicedCLI_CmdServiceSnapshot_usage() {
	InitServiceAPITest("serviced", "service", "snapshot")

	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    snapshot - Takes a snapshot of the service
	//
	// USAGE:
	//    command snapshot [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service snapshot SERVICEID
	//
	// OPTIONS:
	//    --description, -d 		a description of the snapshot
	//    --tag, -t 			a unique tag for the snapshot
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches

}

func ExampleServicedCLI_CmdServiceSnapshot_fail() {
	DefaultServiceAPITest.errs["AddSnapshot"] = ErrStub
	defer func() { DefaultServiceAPITest.errs["AddSnapshot"] = nil }()
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "snapshot", "test-service-1") })

	// Output:
	// stub for facade failed
}

func ExampleServicedCLI_CmdServiceSnapshot_err() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "snapshot", "test-service-0") })

	// Output:
	// service not found
}

func ExampleServicedCLI_CmdServiceEndpoints_usage() {
	InitServiceAPITest("serviced", "service", "endpoints")

	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    endpoints - List the endpoints defined for the service
	//
	// USAGE:
	//    command endpoints [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service endpoints SERVICEID
	//
	// OPTIONS:
	//    --imports, -i		include only imported endpoints
	//    --all, -a			include all endpoints (imports and exports)
	//    --verify, -v			verify endpoints
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches

}

func ExampleServicedCLI_CmdServiceEndpoints_err() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "endpoints", "test-service-0") })

	// Output:
	// service not found
}

func ExampleServicedCLI_CmdServiceEndpoints_worksNoEndpoints() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "endpoints", "test-service-1") })

	// Output:
	// Zenoss - no endpoints defined
}

func ExampleServicedCLI_CmdServiceEndpoints_works() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "endpoints", "test-service-2") })

	// Output:
	// Name    ServiceID         Endpoint         Purpose    Host       HostIP     HostPort    ContainerID     ContainerIP     ContainerPort
	// Zope    test-service-2    endpointName1    export     hostID1    hostIP1    10          containerID1    containerIP1    100
	// Zope    test-service-2    endpointName2    import     hostID2    hostIP2    20          containerID2    containerIP2    200
}

func ExampleServicedCLI_CmdServiceClearEmergency_works() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "clear-emergency", "test-service-1") })

	// Output:
	// Cleared emergency status for 1 services
}

func ExampleServicedCLI_CmdServiceClearEmergency_errNoService() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "clear-emergency", "test-service-0") })

	// Output:
	// service not found
}

func ExampleServicedCLI_CmdServiceClearEmergency_err() {
	DefaultServiceAPITest.errs["ClearEmergency"] = ErrStub
	defer func() { DefaultServiceAPITest.errs["ClearEmergency"] = nil }()
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "clear-emergency", "test-service-1") })

	// Output:
	// stub for facade failed
}

func ExampleServicedCLI_CmdServiceClearEmergency_usage() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "clear-emergency") })

	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    clear-emergency - Clears the 'emergency shutdown' state for a service and all child services
	//
	// USAGE:
	//    command clear-emergency [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service clear-emergency { SERVICEID | SERVICENAME | DEPLOYMENTID/...PARENTNAME.../SERVICENAME }
	//
	// OPTIONS:
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServiceCLI_CmdServiceTune_usage() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "tune") })
	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    tune - Adjust launch mode, instance count, RAM commitment, or RAM threshold for a service
	//
	// USAGE:
	//    command tune [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service tune SERVICEID
	//
	// OPTIONS:
	//    --launchMode 		Launch mode for this service (auto, manual)
	//    --instances '0'		Instance count for this service
	//    --ramCommitment 		RAM Commitment for this service
	//    --ramThreshold 		RAM Threshold for this service
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServiceCLI_CmdServiceTune_noservice() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "tune", "test-service-0") })
	// Output:
	// service not found
}

func ExampleServiceCLI_CmdServiceTune_nokwargs() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "tune", "test-service-1") })
	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    tune - Adjust launch mode, instance count, RAM commitment, or RAM threshold for a service
	//
	// USAGE:
	//    command tune [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service tune SERVICEID
	//
	// OPTIONS:
	//    --launchMode 		Launch mode for this service (auto, manual)
	//    --instances '0'		Instance count for this service
	//    --ramCommitment 		RAM Commitment for this service
	//    --ramThreshold 		RAM Threshold for this service
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServiceCLI_CmdServiceTune_nochanges() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "tune", "test-service-3", "--instances=2") })
	// Output:
	// Service already reflects desired configured - no changes made
}

func ExampleServiceCLI_CmdServiceTune_toomany() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "tune", "test-service-2", "--instances=5") })
	// Output:
	// test-service-2
}

func ExampleServiceCLI_CmdServiceTune_invalidlaunchmode() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "tune", "test-service-1", "--launchMode=incorrect") })
	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    tune - Adjust launch mode, instance count, RAM commitment, or RAM threshold for a service
	//
	// USAGE:
	//    command tune [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service tune SERVICEID
	//
	// OPTIONS:
	//    --launchMode 		Launch mode for this service (auto, manual)
	//    --instances '0'		Instance count for this service
	//    --ramCommitment 		RAM Commitment for this service
	//    --ramThreshold 		RAM Threshold for this service
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServiceCLI_CmdServiceTune_launch() {
	InitServiceAPITest("serviced", "service", "tune", "test-service-1", "--launchMode=manual")
	InitServiceAPITest("serviced", "service", "tune", "test-service-3", "--launchMode=auto")
}

func ExampleServiceCLI_CmdServiceTune_commitment() {
	InitServiceAPITest("serviced", "service", "tune", "test-service-1", "--ramCommitment=256M")
}

func ExampleServiceCLI_CmdServiceTune_threshold() {
	InitServiceAPITest("serviced", "service", "tune", "test-service-1", "--ramThreshold='80%'")
}

func ExampleServiceCLI_CmdServiceVariableList_usage() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "variable", "list") })
	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    list - List one or all config variables and their values for a given service
	//
	// USAGE:
	//    command list [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service variable list SERVICEID
	//
	// OPTIONS:
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServiceCLI_CmdServiceVariableList_noservice() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "variable", "list", "test-service-0") })
	// Output:
	// service not found
}

func ExampleServiceCLI_CmdServiceVariableList() {
	InitServiceAPITest("serviced", "service", "variable", "list", "test-service-2")
	// Output:
	// away.name Bravos
	// away.score 12
	// home.name Alphas
	// home.score 19
}

func ExampleServiceCLI_CmdServiceVariableGet_usage() {
	InitServiceAPITest("serviced", "service", "variable", "get")
	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    get - Find the value of a config variable for a service
	//
	// USAGE:
	//    command get [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service variable get SERVICEID VARIABLE
	//
	// OPTIONS:
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServiceCLI_CmdServiceVariableGet_noservice() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "variable", "get", "test-service-0", "wickets") })
	// Output:
	// service not found
}

func ExampleServiceCLI_CmdServiceVariableGet_badvariable() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "variable", "get", "test-service-2", "mallets") })
	// Output:
	// Variable mallets not found.
}

func ExampleServiceCLI_CmdServiceVariableGet() {
	InitServiceAPITest("serviced", "service", "variable", "get", "test-service-2", "home.name")
	// Output:
	// Alphas
}

func ExampleServiceCLI_CmdServiceVariableSet_usage() {
	InitServiceAPITest("serviced", "service", "variable", "set")
	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    set - Add or update one variable's value for a given service
	//
	// USAGE:
	//    command set [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service variable set SERVICEID VARIABLE VALUE
	//
	// OPTIONS:
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServiceCLI_CmdServiceVariableSet_noservice() {
	pipeStderr(func() {
		InitServiceAPITest("serviced", "service", "variable", "set", "test-service-0", "wickets", "12")
	})
	// Output:
	// service not found
}

func ExampleServiceCLI_CmdServiceVariableSet_novariable() {
	InitServiceAPITest("serviced", "service", "variable", "set", "test-service-2")
	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    set - Add or update one variable's value for a given service
	//
	// USAGE:
	//    command set [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service variable set SERVICEID VARIABLE VALUE
	//
	// OPTIONS:
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServiceCLI_CmdServiceVariableSet_novalue() {
	InitServiceAPITest("serviced", "service", "variable", "set", "test-service-2", "wickets")
	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    set - Add or update one variable's value for a given service
	//
	// USAGE:
	//    command set [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service variable set SERVICEID VARIABLE VALUE
	//
	// OPTIONS:
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServiceCLI_CmdServiceVariableSet() {
	InitServiceAPITest("serviced", "service", "variable", "set", "test-service-2", "wickets", "9")
	// Output:
	// test-service-2
}

func ExampleServiceCLI_CmdServiceVariableUnset_usage() {
	InitServiceAPITest("serviced", "service", "variable", "unset")
	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    unset - Remove a variable from a given service
	//
	// USAGE:
	//    command unset [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service variable unset SERVICEID VARIABLE
	//
	// OPTIONS:
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServiceCLI_CmdServiceVariableUnset_noservice() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "variable", "unset", "test-service-0", "wickets") })
	// Output:
	// service not found
}

func ExampleServiceCLI_CmdServiceVariableUnset_novariable() {
	InitServiceAPITest("serviced", "service", "variable", "unset", "test-service-2")
	// Output:
	// Incorrect Usage.
	//
	// NAME:
	//    unset - Remove a variable from a given service
	//
	// USAGE:
	//    command unset [command options] [arguments...]
	//
	// DESCRIPTION:
	//    serviced service variable unset SERVICEID VARIABLE
	//
	// OPTIONS:
	//    --no-prefix-match, --np	Make SERVICEID matches on name strict 'ends with' matches
}

func ExampleServiceCLI_CmdServiceVariableUnset_badvariable() {
	pipeStderr(func() { InitServiceAPITest("serviced", "service", "variable", "unset", "test-service-2", "mallets") })
	// Output:
	// Variable mallets not found.
}

func ExampleServiceCLI_CmdServiceVariableUnset() {
	InitServiceAPITest("serviced", "service", "variable", "unset", "test-service-2", "home.name")
	// Output:
	// test-service-2
}


text:
#ifndef cmFunctionCommand_h
#define cmFunctionCommand_h

#include "cmCommand.h"
#include "cmFunctionBlocker.h"

/** \class cmFunctionFunctionBlocker
 * \brief subclass of function blocker
 *
 *
 */
class cmFunctionFunctionBlocker : public cmFunctionBlocker
{
public:
  cmFunctionFunctionBlocker() {this->Depth=0;}
  virtual ~cmFunctionFunctionBlocker() {}
  virtual bool IsFunctionBlocked(const cmListFileFunction&,
                                 cmMakefile &mf,
                                 cmExecutionStatus &);
  virtual bool ShouldRemove(const cmListFileFunction&, cmMakefile &mf);
  virtual void ScopeEnded(cmMakefile &mf);

  std::vector<std::string> Args;
  std::vector<cmListFileFunction> Functions;
  int Depth;
};

/** \class cmFunctionCommand
 * \brief starts an if block
 *
 * cmFunctionCommand starts an if block
 */
class cmFunctionCommand : public cmCommand
{
public:
  /**
   * This is a virtual constructor for the command.
   */
  virtual cmCommand* Clone()
    {
    return new cmFunctionCommand;
    }

  /**
   * This is called when the command is first encountered in
   * the CMakeLists.txt file.
   */
  virtual bool InitialPass(std::vector<std::string> const& args,
                           cmExecutionStatus &status);

  /**
   * This determines if the command is invoked when in script mode.
   */
  virtual bool IsScriptable() { return true; }

  /**
   * The name of the command as specified in CMakeList.txt.
   */
  virtual const char* GetName() { return "function";}

  /**
   * Succinct documentation.
   */
  virtual const char* GetTerseDocumentation()
    {
    return "Start recording a function for later invocation as a command.";
    }

  /**
   * More documentation.
   */
  virtual const char* GetFullDocumentation()
    {
    return
      "  function(<name> [arg1 [arg2 [arg3 ...]]])\n"
      "    COMMAND1(ARGS ...)\n"
      "    COMMAND2(ARGS ...)\n"
      "    ...\n"
      "  endfunction(<name>)\n"
      "Define a function named <name> that takes arguments named "
      "arg1 arg2 arg3 (...).  Commands listed after function, but before "
      "the matching endfunction, are not invoked until the function "
      "is invoked.  When it is invoked, the commands recorded in the "
      "function are first modified by replacing formal parameters (${arg1}) "
      "with the arguments passed, and then invoked as normal commands. In "
      "addition to referencing the formal parameters you can reference "
      "the variable ARGC which will be set to the number of arguments "
      "passed into the function as well as ARGV0 ARGV1 ARGV2 ... which "
      "will have the actual values of the arguments passed in. This "
      "facilitates creating functions with optional arguments. Additionally "
      "ARGV holds the list of all arguments given to the function and ARGN "
      "holds the list of argument pass the last expected argument.";
    }

  cmTypeMacro(cmFunctionCommand, cmCommand);
};

#endif


text:
var VSHADER_SOURCE =
  'attribute vec4 a_Position;\n' +
  'void main() {\n' +
  '  gl_Position = a_Position;\n' +
  '}\n';

// Fragment shader program
var FSHADER_SOURCE =
  'void main() {\n' +
  '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
  '}\n';

function main() {
  // Retrieve <canvas> element
  var canvas = document.getElementById('webgl');

  // Get the rendering context for WebGL
  var gl = getWebGLContext(canvas);
  if (!gl) {
    console.log('Failed to get the rendering context for WebGL');
    return;
  }

  // Initialize shaders
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }

  // Write the positions of vertices to a vertex shader
  var n = initVertexBuffers(gl);
  if (n < 0) {
    console.log('Failed to set the positions of the vertices');
    return;
  }

  // Specify the color for clearing <canvas>
  gl.clearColor(0, 0, 0, 1);

  // Clear <canvas>
  gl.clear(gl.COLOR_BUFFER_BIT);

  // Draw the rectangle
  gl.drawArrays(gl.LINE_LOOP, 0, n);
}

function initVertexBuffers(gl) {
  var vertices = new Float32Array([
    0, 0.5,   -0.5, -0.5,   0.5, -0.5
  ]);
  var n = 3; // The number of vertices

  // Create a buffer object
  var vertexBuffer = gl.createBuffer();
  if (!vertexBuffer) {
    console.log('Failed to create the buffer object');
    return -1;
  }

  // Bind the buffer object to target
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  // Write date into the buffer object
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

  var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  if (a_Position < 0) {
    console.log('Failed to get the storage location of a_Position');
    return -1;
  }
  // Assign the buffer object to a_Position variable
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

  // Enable the assignment to a_Position variable
  gl.enableVertexAttribArray(a_Position);

  return n;
}


text:
require_relative '../../spec_helper'
require_relative 'fixtures/classes'

describe "IO#getbyte" do
  before :each do
    @io = IOSpecs.io_fixture "lines.txt"
  end

  after :each do
    @io.close if @io
  end

  it "returns the next byte from the stream" do
    @io.readline.should == "Voici la ligne une.\n"
    letters = @io.getbyte, @io.getbyte, @io.getbyte, @io.getbyte, @io.getbyte
    letters.should == [81, 117, 105, 32, 195]
  end

  it "returns nil when invoked at the end of the stream" do
    @io.read
    @io.getbyte.should == nil
  end

  it "raises an IOError on closed stream" do
    -> { IOSpecs.closed_io.getbyte }.should raise_error(IOError)
  end
end

describe "IO#getbyte" do
  before :each do
    @io = IOSpecs.io_fixture "empty.txt"
  end

  after :each do
    @io.close if @io
  end

  it "returns nil on empty stream" do
    @io.getbyte.should == nil
  end
end


text:
using System;
using System.Collections.Generic;
using System.Text;

using NUnit.Framework;

using Transloadit;
using Transloadit.Assembly;

namespace Tests
{
    [TestFixture]
    class AuthenticationTests
    {
        [Test]
        public void AuthenticateWithExistingAccount()
        {
            ITransloadit transloadit = new Transloadit.Transloadit("YOUR-PUBLIC-API-KEY", "YOUR-SECRET-KEY");
            IAssemblyBuilder assembly = new Transloadit.Assembly.AssemblyBuilder();
            IStep step = new Transloadit.Assembly.Step();

            step.SetOption("robot", "/image/resize");
            assembly.AddStep("step", step);
            assembly.SetField("test", "200");

            TransloaditResponse response = transloadit.InvokeAssembly(assembly);

            Assert.IsTrue((string)response.Data["ok"] == "ASSEMBLY_COMPLETED" || (string)response.Data["ok"] == "ASSEMBLY_EXECUTING");
        }

        [Test]
        public void AuthenticateWithNonExistingAccount()
        {
            ITransloadit transloadit = new Transloadit.Transloadit("YOUR-PUBLIC-API-KEY", "YOUR-SECRET-KEY");
            IAssemblyBuilder assembly = new AssemblyBuilder();

            TransloaditResponse response = transloadit.InvokeAssembly(assembly);

            Assert.AreEqual("GET_ACCOUNT_UNKNOWN_AUTH_KEY", (string)response.Data["error"]);
        }

        [Test]
        public void WrongSecretKey()
        {
            ITransloadit transloadit = new Transloadit.Transloadit("YOUR-PUBLIC-API-KEY", "YOUR-SECRET-KEY");
            IAssemblyBuilder assembly = new AssemblyBuilder();

            TransloaditResponse response = transloadit.InvokeAssembly(assembly);

            Assert.AreEqual("INVALID_SIGNATURE", (string)response.Data["error"]);
        }
    }
}


text:
package org.docksidestage.mysql.dbflute.freegen.solr.bean.ex;

import org.docksidestage.mysql.dbflute.freegen.solr.bean.bs.BsSolrFooBean;

/**
 * @author FreeGen
 */
public class SolrFooBean extends BsSolrFooBean {

    private static final long serialVersionUID = 1L;
}


text:
var aubrey = require('../..');
var ObjectStore = require('aubrey-object-store');

module.exports = function createCollection() {
  return new aubrey.Collection({
    name: 'abc',
    store: new ObjectStore()
  });
};