text:
package iurii.job.interview.google;

// almost same as https://leetcode.com/discuss/interview-question/390967/google-phone-screen-common-friends
// looks same as https://leetcode.com/discuss/interview-question/486188/Facebook-or-Phone-or-Friend-Suggestion/433306

import java.util.*;
import java.util.stream.Collectors;

/**
 * More links:
 * 1. https://www.geeksforgeeks.org/friends-pairing-problem/
 * 2. https://www.geeksforgeeks.org/number-groups-formed-graph-friends/
 * 3. https://www.geeksforgeeks.org/comparison-between-adjacency-list-and-adjacency-matrix-representation-of-graph/
 */
public class GooglePhoneCall1 {

    /**
     * Given a social network (whatever presentation works best) and a user,
     * Provide recommendations to the user on potential friends.
     *
     * Potential friend is a person, which is friend of user`s friends but not among user friends.`
     *
     * Follow up: return recommendations in sorted order from the biggest number of common friends
     * ------------------------------------------------------------------------
     *
     * 1. which representation to choose?
     * There are the following representations:
     *     1. Adjacency list
     *     2. Adjacency matrix
     *
     * Both have problematic point is that they represent only connections between a pair of vertexes.
     * Storing the whole graph in memory is problematic.
     *
     * Better to have general object-oriented (decoupled) structure:
     *
     * There is a User class with all corresponding fields
     * there should be unique id (name-surname are not unique)
     * there should be a Set<User> (we probably do not care about the order) - immediate friends.
     *
     * Here also important to notice - graph is undirected: if A is friends of B -> B friend of A.
     *
     * In order to find recommendation -> we need to check only friends of immediate friends,
     * because they will have at least one person (user`s friend) in common friends.
     *
     * N - total number of Users
     * Brute-force solution: check all user`s friends` friends Set<User> - O(N)
     * check common number of friends with User (minimum will be one, because there is at least one friend)
     * check will be O(N) based on check if element is in Set.
     *
     * Important: filter out user node itself and its friends - because they should not be recommended.
     *
     * It will be easier, if we pre-compute frequencies of each friends` friend in the Map -
     * frequencies will give
     *
     * If we need to find any one recommendation :
     * Time complexity : O(N) - check each friend (up to N), and if friend has only one friend, which is user - skip.
     * Space Complexity: O(N) - to maintain list of exclusions + one candidate
     *
     * If there is limit on friends M - when regardless all people count in network: Time Complexity : O(1).
     */
    public User getAnyRecommendation(User user) {
        // user and friends can not be null (null safe)
        if (user == null || user.friends == null) {
           return null;
        }
        Set<User> friends = user.friends;
        // user itself and any of friends can not be recommendation
        Set<User> exclusions = new HashSet<>();
        exclusions.add(user);
        exclusions.addAll(user.friends);
        // let`s check friends of each friend
        for (User friend : friends) {
            Set<User> candidates = friend.friends;
            for (User candidate : candidates) {
                if (!exclusions.contains(candidate)) {
                    return candidate;
                }
            }
        }
        return null;
    }

    /**
     * if we need sort recommendations based on frequency :
     *
     * @param user user
     * @return recommendations sorted by frequency
     */
    public List<Recommendation> getRecommendationsSortedByFrequency(User user) {
        // user and friends can not be null (null safe)
        if (user == null || user.friends == null) {
            return null;
        }
        Set<User> friends = user.friends;
        // user itself and any of friends can not be recommendation
        Set<User> exclusions = new HashSet<>();
        exclusions.add(user);
        exclusions.addAll(user.friends);

        // let`s have HashMap user -> frequency (having friends in common) for the suggestion
        // example A <-> B ; A <-> C; B <-> D; C <-> D; C <-> E
        // D -> 2; E -> 1 frequencies, cause D has B and C in common with A and E has C in common with A
        // user should be immutable to be used as a key in Map;
        Map<User, Integer> frequencies = new HashMap<>();

        // let`s check friends of each friend
        for (User friend : friends) {
            Set<User> candidates = friend.friends;
            for (User candidate : candidates) {
                if (!exclusions.contains(candidate)) {
                    int count = frequencies.getOrDefault(candidate, 0);
                    frequencies.put(candidate, count + 1);
                }
            }
        }
        // we found frequencies -> let`s form sorted list of recommendations based on frequency

        // collect recommendations based on user and frequency
        return frequencies.entrySet().stream()
                .map(entry -> {
                    Recommendation recommendation = new Recommendation();
                    recommendation.frequency = entry.getValue();
                    recommendation.user = entry.getKey();
                    return recommendation;
                })
                // sort from most frequent to less frequent
                .sorted()
                .collect(Collectors.toList());

        // there can be many follow ups:
        // 1. return only the one with most common friends (frequent) if there are multiple - return any.
        // 2. return only up to K recommendations after sorting limit; PriorityQueue probably will not help
        // 3. Maybe there will be variations of this task based on Map <frequency ; Set<User>> - reversed index
        // and sorting Map by frequency

        // In general complexity will be the following:
        // Total Number of edges in graph does not matter; but it can be a variable in terms of common friends..
        // Time Complexity : O(M + N log N)
        //     - M : edges (basically friends and friends of friends)
        //     - N log N - number of friends and sorted by frequency
        // assuming that number of edges does not matter much and can grow up to N^2
        // Time Complexity : O(N^2 + N log N) - O(N^2)
    }

    // equals and hashcode should be implemented based on unique id;
    static class User {
        int id;
        Set<User> friends;
    }

    static class Recommendation implements Comparable<Recommendation> {
        int frequency;
        User user;

        @Override
        public int compareTo(Recommendation o) {
            return o.frequency - frequency;
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
import React, { Component } from 'react';
import {MapView} from 'react-native';
import { connect } from 'react-redux';
import { Container, Header, Title, Content, View, Text, Button, Icon } from 'native-base';
import { Grid, Col, Row } from 'react-native-easy-grid';
import myTheme from '../../themes/base-theme';
import styles from './styles';

/*
const APIKEY = 'AIzaSyBU1hHi_2jz1bjkLiEZZMfn5VxJsxmyhT4';
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&type=bar&key=AIzaSyBU1hHi_2jz1bjkLiEZZMfn5VxJsxmyhT4
var api = {

getRequest(long,lat){
  let longitude = long;
  let latitude = lat;
  console.log("nig"+latitude,longitude);
  var url ='https://maps.googleapis.com/maps/api/place/textsearch/json?key='+ APIKEY+'&query="bar"&location='+latitude+','+longitude+'&radius=8000';
  return fetch(url).then((res) => res.json());
}

};
*/

import {GooglePlacesAutocomplete} from 'react-native-google-places-autocomplete';

const homePlace = {description: 'Home', geometry: { location: { lat: 48.8152937, lng: 2.4597668 } }};
const workPlace = {description: 'Work', geometry: { location: { lat: 48.8496818, lng: 2.2940881 } }};

class Example extends Component{
  render() {
    return (
      <View>
      <GooglePlacesAutocomplete
        placeholder='Search'
        minLength={2} // minimum length of text to search
        autoFocus={false}
        fetchDetails={true}
        onPress={(data, details = null) => { // 'details' is provided when fetchDetails = true
          console.log(data);
          console.log(details);
        }}
        getDefaultValue={() => {
          return ''; // text input default value
        }}
        query={{
          // available options: https://developers.google.com/places/web-service/autocomplete
          key: 'AIzaSyBU1hHi_2jz1bjkLiEZZMfn5VxJsxmyhT4',
          language: 'en', // language of the results
          types: '(cities)', // default: 'geocode'
        }}
        styles={{
          description: {
            fontWeight: 'bold',
          },
          predefinedPlacesDescription: {
            color: '#1faadb',
          },
        }}

        currentLocation={true} // Will add a 'Current location' button at the top of the predefined places list
        currentLocationLabel="Current location"
        nearbyPlacesAPI='GooglePlacesSearchQuery' // Which API to use: GoogleReverseGeocoding or GooglePlacesSearch
        GoogleReverseGeocodingQuery={{
          // available options for GoogleReverseGeocoding API : https://developers.google.com/maps/documentation/geocoding/intro
          components:'93635'

        }}
        GooglePlacesSearchQuery={{
          // available options for GooglePlacesSearch API : https://developers.google.com/places/web-service/search
          rankby: 'distance',
          types: 'food'
        }}

        filterReverseGeocodingByTypes={['locality', 'administrative_area_level_3']} // filter the reverse geocoding results by types - ['locality', 'administrative_area_level_3'] if you want to display only cities

        predefinedPlaces={[homePlace, workPlace]}
      />

      </View>
    );
  }
}

module.exports = Example;


text:
import cv2
import os
import numpy as np
from libs.svm import SVMManager
from libs.hog import HOGManager

env = 'development'

def load_files(folder):
    files = []
    for filename in os.listdir(folder):
        files.append(filename)
    return files

def load_images(folder):
    images = []
    files = load_files(folder)
    for file in files:
        img = cv2.imread(os.path.join(folder, file), 0)
        if img is not None:
            images.append(img)
    return images

def extractFeature(pos_images, neg_images):

    hogMgr = HOGManager()
    train_data = []
    label_data = []
    for img in pos_images:
        # cv2.imshow('pos', img)
        # cv2.waitKey(1)
        posHist = hogMgr.compute(img)
        train_data.append(posHist)
        label_data.append(1)

    for img in neg_images:
        # cv2.imshow('neg', img)
        # cv2.waitKey(1)
        negHist = hogMgr.compute(img)
        train_data.append(negHist)
        label_data.append(-1)

    return train_data, label_data

class MediaProcessor:

    def __init__(self):
        self.tmp = ''

    def run(self):
        pos_images = load_images('./images/pos')
        print len(pos_images)

        neg_images = load_images('./images/neg')
        print len(neg_images)

        trainData, labelData = extractFeature(pos_images, neg_images)

        svmMgr = SVMManager()
        svmMgr.train(labelData, trainData)
        hogMgr = HOGManager()

        video = cv2.VideoCapture('C:/Users/user/Desktop/test/3_2016-10-07_16-24-43.mp4')

        frame_index = 0
        while(True):
            ret, frame = video.read()
            frame_index += 1
            if frame_index < 60:
                continue

            frame = cv2.resize(frame, (640,480))
            imgshape = frame.shape
            center_image_x = imgshape[1]/2
            center_image_y = imgshape[0]/2
            roi_range = 100
            search_shift = 12
            search_stride = 8
            default_shift = (search_shift/2)*search_stride
            begin_leftTop_x = center_image_x-roi_range-default_shift
            begin_leftTop_y = center_image_y-roi_range-default_shift
            begin_rightDown_x = center_image_x+roi_range-default_shift
            begin_rightDown_y = center_image_y+roi_range-default_shift
            end_leftTop_x = center_image_x-roi_range+default_shift
            end_leftTop_y = center_image_y-roi_range+default_shift
            end_rightDown_x = center_image_x+roi_range+default_shift
            end_rightDown_y = center_image_y+roi_range+default_shift

            count = 0
            for i in range(search_shift):
                for j in range(search_shift):
                    leftTop_x = begin_leftTop_x+j*search_stride
                    leftTop_y = begin_leftTop_y+i*search_stride
                    rightDown_x = begin_rightDown_x+j*search_stride
                    rightDown_y = begin_rightDown_y+i*search_stride
                    # print leftTop_x, leftTop_y, rightDown_x, rightDown_y
                    image_roi = frame[leftTop_y:rightDown_y, leftTop_x:rightDown_x]
                    image_gray = cv2.cvtColor(image_roi, cv2.COLOR_BGR2GRAY)
                    feature = hogMgr.compute(image_gray)
                    result = svmMgr.predict(feature)
                    label = result[1][0][0]

                    if env is 'development':
                        image_draw = frame.copy()
                        cv2.rectangle(image_draw, (begin_leftTop_x, begin_leftTop_y), (end_rightDown_x, end_rightDown_y), (255, 0, 0), 3)
                        if label == -1.0:
                            cv2.rectangle(image_draw, (leftTop_x, leftTop_y), (rightDown_x, rightDown_y), (0, 0, 255), 3)
                        else:
                            count += 1
                            cv2.rectangle(image_draw, (leftTop_x, leftTop_y), (rightDown_x, rightDown_y), (0, 255, 0), 3)

                        cv2.imshow('search progress', image_draw)
                        cv2.waitKey(10)
                    else:
                        if label != -1.0:
                            count += 1

            print 'detect' , count
            cv2.imshow('frame', frame)
            cv2.waitKey(33)

        video.release()
        cv2.destroyAllWindows()

if __name__ == '__main__':

    mediaRes = MediaProcessor()
    mediaRes.run()


text:
package com.badlogic.gdx.graphics;

import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;

/** A Camera with perspective projection.
 *
 * @author mzechner */
public class PerspectiveCamera extends Camera {

    final Vector3 tmp = new Vector3();
    /** the field of view of the screenHeight, in degrees **/
    public float fieldOfView = 67;

    public PerspectiveCamera(int pixelWidth, int pixelHeight) {
        super(pixelHeight, pixelWidth);
    }

    /** Constructs a new {@link PerspectiveCamera} with the given field of view and viewport size. The aspect ratio is derived from
     * the viewport size.
     *
     * @param fieldOfViewY the field of view of the screenHeight, in degrees, the field of view for the width will be calculated
     *           according to the aspect ratio.
     * @param viewportWidth the viewport width
     * @param viewportHeight the viewport screenHeight */
    public PerspectiveCamera(int pixelWidth, int pixelHeight, float fieldOfViewY, float viewportWidth, float viewportHeight) {
        super(pixelHeight, pixelWidth);
        this.fieldOfView = fieldOfViewY;
        this.viewportWidth = viewportWidth;
        this.viewportHeight = viewportHeight;
        update();
    }

    @Override
    public void update() {
        update(true);
    }

    @Override
    public void update(boolean updateFrustum) {
        float aspect = viewportWidth / viewportHeight;
        projection.setToProjection(Math.abs(near), Math.abs(far), fieldOfView, aspect);
        view.setToLookAt(position, tmp.set(position).add(direction), up);
        combined.set(projection);
        Matrix4.mul(combined.val, view.val);

        if (updateFrustum) {
            invProjectionView.set(combined);
            Matrix4.inv(invProjectionView.val);
            frustum.update(invProjectionView);
        }
    }
}


text:
crashdesk-ruby [![Build Status](https://secure.travis-ci.org/crashdesk/crashdesk-ruby.png?branch=master)](http://travis-ci.org/crashdesk/crashdesk-ruby)
==============

Crashde.sk Ruby client library for [Crashde.sk](http://crashde.sk) service

How to Install
--------------

1. Install gem

    a) Add the `crashdesk` gem to your `Gemfile`

      ```ruby
      gem "crashdesk"
      ```

      ```shell
      bundle install
      ```

    b) Install `crashdesk` gem to your system

      ```shell
      gem install crashdesk
      ```

3.  Copy the configuration to your Ruby project

    ```ruby
    Crashdesk.configure do |config|
      config.app_key = "YOUR_API_KEY"
    end
    ```

Configuration
-------------

To configure additional settings, use the block syntax and set any
settings you need on the `config` block variables. For example:

```ruby
Crashdesk.configure do |config|
  config.app_key = "YOUR_API_KEY"
  config.use_ssl = true
end
```

###app_key

Your Bugsnag APP key (required).

```ruby
config.app_key = "YOUR_API_KEY"
```

###use_ssl

Enforces all communication with servers be made via SSL.

```ruby
config.use_ssl = true
```

By default, `use_ssl` is set to false.

Format of Crashlog:
-------------------

- Hash ID
  MD5 hash of backtrace giving the exception uniq hash.

- CRC hash
  This has is going to be used for displaying for user. It's sort to be read out loud.

- Occured at timestamp
  Exact time of exception/error occurence. Format is ISO-8601.

- Environment
  Whatever you feel is important to capture from application's environment.
  ---
    Eq:
      - Language name [ruby]
      - Language version [1.9.3]
      - Language platform [i486-linux]

- Context
  Capturing context of the data surrounding exception in time of raise/throw.
  ---
    Eq:
      - Framework [rails || sinatra || rack]
      - Framework version string [3.2.x]

- Exception
  Data describing exception.
  ---
    Eq:
      - Exception class [StandardError]
      - Exception message [Whatever you pass in the exception]
      - Backtrace

TODO
----
Add Gemnasium to track dependencies: https://gemnasium.com
Add Travis CI to run test

Reporting bug or Feature request
--------------------------------

Please report any bugs or feature requests on the github issues page for this
project:

<https://github.com/crashdesk/crashdesk-ruby/issues>

Contributing
------------

-   Fork the repo
-   Commit and push
-   [Make a pull request](https://help.github.com/articles/using-pull-requests)
-   Thank you!

License
-------

The Crashdeks Ruby client is free software released under the MIT License.
See [LICENSE.txt](https://github.com/crashdesk/crashdesk-ruby/blob/master/MIT_LICENSE) for details.


text:
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

import { DisplayComponent } from './display.component';

describe('DisplayComponent', () => {
  let component: DisplayComponent;
  let fixture: ComponentFixture<DisplayComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ DisplayComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(DisplayComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});


text:
/**
 * @file Contain the description of the next classes:
 *

 *
[PageEditor]{@link PageEditor}

 *
[PageEditor.BlockEditor]{@link PageEditor.BlockEditor}

 *

 *
 * @requires Energine
 * @requires ckeditor/ckeditor
 * @requires ModalBox
 * @requires Overlay
 *
 * @author Pavel Dubenko
 * @author Andy Karpov
 * @author Valerii Zinchenko
 *
 * @version 1.0.0
 */

ScriptLoader.load('ckeditor/ckeditor', 'ModalBox', 'Overlay');

/**
 * @class PageEditor
 * @classdesc Page editor.
 */
var PageEditor = new Class(/** @lends PageEditor# */{
    // todo: Make it sense to store this two members in the object? They used only by initialize.
    /**
     * Editor class name.
     * @type {string}
     */
    editorClassName: 'nrgnEditor',

    /**
     * Array of block editors.
     * @type {PageEditor.BlockEditor[]}
     */
    editors: [],

    initialize: function () {
        CKEDITOR.disableAutoInline = true;
        CKEDITOR.config.extraPlugins = 'sourcedialog,energineimage,energinevideo,energinefile';
        CKEDITOR.config.removePlugins = 'sourcearea';
        CKEDITOR.config.allowedContent = true;
        CKEDITOR.config.toolbar = [
            { name: 'document', groups: [ 'mode' ], items: [ 'Sourcedialog' ] },
            { name: 'clipboard', groups: [ 'clipboard', 'undo' ], items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] },
            { name: 'editing', groups: [ 'find', 'selection' ], items: [ 'Find', 'Replace', '-', 'SelectAll' ] },
            { name: 'links', items: [ 'Link', 'Unlink', 'Anchor' ] },
            { name: 'insert', items: [ 'Image', 'Flash', 'Table', 'EnergineImage', 'EnergineVideo', 'EnergineFile' ] },
            { name: 'tools', items: [ 'ShowBlocks' ] },
            '/',
            { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] },
            { name: 'paragraph', groups: [ 'list', 'indent', 'align' ], items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ] },
            { name: 'styles', items: [ 'Styles', 'Format', 'Font', 'FontSize' ] },
            { name: 'colors', items: [ 'TextColor', 'BGColor' ] }
        ];
        var styles = [];
        if (window['wysiwyg_styles']) {
            Object.each(window['wysiwyg_styles'], function (style) {
                styles.push({
                    name: style['caption'],
                    element: style['element'],
                    attributes: { 'class': style['class'] }
                });
            });
        }
        CKEDITOR.stylesSet.add('energine', styles);
        CKEDITOR.config.stylesSet = 'energine';
		// allow empty
		CKEDITOR.dtd.$removeEmpty['i'] = false;
		CKEDITOR.dtd.$removeEmpty['em'] = false;

        $(document.body).getElements('.' + this.editorClassName).each(function (element) {
            this.editors.push(new PageEditor.BlockEditor(element));
        }, this);

        window.addEvent(((Browser.opera) ? 'unload' : 'beforeunload'), function () {
            if (this.editors.length) {
                this.editors.each(function (editor) {
                    editor.save.call(editor, false);
                }, this);
            }
            if (Browser.opera) {
                // Dirty Opera hack
                window.location.href = window.location.href;
                return '';
            }
        }.bind(this));
    }
});

/**
 * Block editor.
 *
 * @constructor
 * @param pageEditor
 * @param area
 */
PageEditor.BlockEditor = new Class(/** @lends PageEditor.BlockEditor# */{
    // constructor
    initialize: function (area) {
        /**
         * Area element.
         * @type {Element}
         */
        this.area = area;
        this.area.setProperty('contenteditable', true);

        /**
         * Defines whether the editor is active.
         * @type {boolean}
         */
        this.isActive = false;

        /**
         * Single path.
         * @type {string}
         */
        this.singlePath = this.area.getProperty('single_template');

        /**
         * Block editor ID.
         * @type {string}
         */
        this.ID = this.area.getProperty('eID') ? this.area.getProperty('eID') : '';

        /**
         * Text block ID.
         * @type {string}
         */
        this.num = this.area.getProperty('num') || '';

        /**
         * Editor.
         * @type {CKEDITOR}
         */
        this.editor = CKEDITOR.inline(this.area.get('id'), {
            language: Energine.lang
        });
        this.editor.singleTemplate = this.area.getProperty('single_template');
        this.editor.editorId = this.area.get('id');
        this.editor.on('focus', function () {
                this.editor.setReadOnly(false);
        }.bind(this));
        /**
         * Overlay.
         * @type {Overlay}
         */
        this.overlay = new Overlay();
        /*this.editor.on('blur', function () {
            console.log(this.area)
            this.area.removeClass('activeEditor');
            this.save();
        }.bind(this));
        this.editor.on('focus', function () {
            console.log(this.area)
            this.area.addClass('activeEditor');
        }.bind(this));*/
    },

    /**
     * Save.
     *
     * @function
     * @public
     * @param {boolean} [async = true] Defines whether the request be asynchronous or not.
     * @param {function} [onSuccess = undefined] User defined function that is called after sucess saving
     */
    save: function (async, onSuccess) {
        if (this.editor.checkDirty()) {
            if (async == undefined) {
                async = true;
            }
            if (!async) {
                this.overlay.show();
            }

            var data = 'data=' + encodeURIComponent(this.editor.getData());
            if (this.ID) {
                data += '&ID=' + this.ID;
            }
            if (this.num) {
                data += '&num=' + this.num;
            }

            new Request({
                url: this.singlePath + 'save-text',
                async: async,
                method: 'post',
                data: data,
                onSuccess: function (response) {
                    // Временно убрано, т.к. сбрасывает курсор в начала редактируемой области
                    // и из за этого неправильно работают некоторые ф-ции эдитора.
                    //this.editor.setData(response);
                    if (onSuccess)onSuccess.call(this);
                    this.editor.resetDirty();
                    if (!async) {
                        this.overlay.hide();
                    }
                }.bind(this)
            }).send();
        }

    }
});


text:
* Fix: Make `transferMyPlayback` not require the `options` object, since it should be optional. Thanks for the heads-up [@Simber1](https://github.com/Simber1)!

#### 5.0.1 (Jan 2021)

* Fix error handling in the HTTP client. Thanks [@yamadapc](https://github.com/yamadapc)!
* This package can currently not be built on **Node 15 on Linux**, due to a dependency not being available yet. Issue can be followed on the [node-canvas](https://github.com/Automattic/node-canvas/issues/1688) issue tracker. In the mean time, Travis CI will run on earlier versions of Node.

#### 5.0.0 (Oct 2020)

* **BREAKING CHANGES**.
  * Arguments for some API methods have changed, causing incorrect behaviour using argument order from version 4.x. See the `README.md` for examples of how the methods can be used.
    * Create Playlist (`createPlaylist`) method no longer accepts a `userId` string as its first argument.
    * Transfer A User's Playback (`transferMyPlayback`) method takes a `deviceIds` array as its first argument.
    * Skip to Previous (`skipToPrevious`) method takes an `options` object as its first argument.
    * Skip to Next (`skipToNext`) method takes an `options` object as its first argument.
    * Set Repeat Mode on the Current User's Playback (`setRepeat`) method takes a `state` string as its first argument.
    * Set Shuffle Mode on the Current User's Playback (`setShuffle`) method takes a `state` string as its first argument.

    Cheers [@marinacrachi](https://github.com/marinacrachi) for the createPlaylist update.
  * Removed legacy support for not passing an `options` object while providing a callback method. This was only supported on a few of the older endpoints, and could lead to tricky bugs. The affected endpoints are `getTrack`, `getTracks`, `getAlbum`, `getAlbums`, and  `createPlaylist`. Again, check the `README.md` for examples on how these methods can be used if needed.
  * Removed `options` argument for retrieving an access token using the Client Credentials flow, `clientCredentialsGrant`.
  * API errors come in five different flavours.
    * WebapiRegularError - For errors returned by most API endpoints.
    * WebapiPlayerError - For errors returned by the Player API. These contain a bit more information.
    * WebapiAuthenticationError - For errors related to authentication.
    * WebapiError - For errors that come from the Web API that didn't fit into one of the above.
    * TimeoutError - For network timeout errors.

    More importantly, errors now contain the response body, headers, and status code. One side-effect of this is that rate limited requests can be handled by checking the `Retry-After` header. Thanks for the PRs [@kauffecup](https://github.com/kauffecup), [@lantelyes](https://github.com/lantelyes), [@dkliemsch](https://github.com/dkliemsch), and [@erezny](https://github.com/erezny).

    Much appreciated [@konstantinjdobler](https://github.com/konstantinjdobler) for updates to the Player API errors.
* Added support for [Implicit Grant flow](https://developer.spotify.com/documentation/general/guides/authorization-guide/#implicit-grant-flow) - Thanks [@gaganza](https://github.com/gaganza), [@reblws](https://github.com/reblws) and [@noahp78](https://github.com/noahp78)!
* Starts or Resumes the Current User's Playback (`play`) method now supports the `position_ms` option. Thanks [@alqubo](https://github.com/alqubo), [@koflin](https://github.com/koflin), [@DoctorFishy](https://github.com/DoctorFishy). Thanks [@carmilso](https://github.com/carmilso) for general improvements to the Player API methods.
* Binding for [Add an Item to the User's Playback Queue](https://developer.spotify.com/documentation/web-api/reference/player/add-to-queue/) endpoint added. Thanks [@thattomperson](https://github.com/thattomperson) and [@AriciducaZagaria](https://github.com/AriciducaZagaria)!
* Binding for all [Shows and Episodes endpoints](https://developer.spotify.com/console/shows/). Thanks a _lot_ [@andyruwruw](https://github.com/andyruwruw)!
* Documentation updates to keep up to date with ES6, thanks [@dandv](https://github.com/dandv)! Other documentation improvements by [@terensu-desu](https://github.com/terensu-desu), and examples by [@dersimn](https://github.com/dersimn). Thanks!
* Bumped dependencies to resolve critical security issues.
* Finally, hat off to [@dersimn](https://github.com/dersimn). Thanks for collecting all of the lingering PRs and merging them into a  working and up-to-date fork. You really stepped up.

Likely more changes coming before release to npm, which will happen shortly.

#### 4.0.0 (14 Sep 2018)

* Modified functions that operate on playlists to drop the user id parameter. This is a breaking change. [PR](https://github.com/thelinmichael/spotify-web-api-node/pull/243)
* Updated superagent to fix a security warning [PR](https://github.com/thelinmichael/spotify-web-api-node/pull/211)
* Fixed a bug by which an empty user was not handled properly in getUserPlaylists(). [PR](https://github.com/thelinmichael/spotify-web-api-node/pull/244)

#### 3.1.1 (29 Apr 2018)

* Modernized stack for a better developer experience. Integrated [prettier](https://github.com/thelinmichael/spotify-web-api-node/pull/205) and [jest](https://github.com/thelinmichael/spotify-web-api-node/pull/206). This simplifies the amount of dev dependencies.
* Improved calls to save and remove saved tracks by adding a key as specified in the Spotify docs (See [PR](https://github.com/thelinmichael/spotify-web-api-node/pull/207)). Thanks to [@yanniz0r](https://github.com/yanniz0r) and [@adcar](https://github.com/adcar) for bringing it up.

#### 3.1.0 (26 Apr 2018)

* Added support for seeking and setting volume. Thanks to [@isokar](https://github.com/isokar), [@jamesemwallis](https://github.com/jamesemwallis), [@ashthespy](https://github.com/ashthespy), and [@vanderlin](https://github.com/vanderlin) for your PRs.

#### 3.0.0 (8 Mar 2018)

* @DalerAsrorov added support for uploading a custom image to a playlist in [this PR](https://github.com/thelinmichael/spotify-web-api-node/pull/169).
* You can now pass a `device_id` when playing and pausing playback. @pfftdammitchris started [a PR to add device_id to the play() method](https://github.com/thelinmichael/spotify-web-api-node/pull/185). The changes served to another PR where we included the functionality. Thanks!
* Added documentation in the README for `getMyCurrentPlaybackState()`. Thanks @PanMan for [your PR](https://github.com/thelinmichael/spotify-web-api-node/pull/160)!
* @brodin realized we there was a lot of duplicated code and refactored it in a [great PR](https://github.com/thelinmichael/spotify-web-api-node/pull/123).

#### 2.5.0 (4 Sep 2017)

* Change README to reflect new authorization. Thanks [@arirawr](https://github.com/arirawr) for the [PR](https://github.com/thelinmichael/spotify-web-api-node/pull/146).
* Add support for 'show_dialog' parameter when creating authorization url. Thanks [@ajhaupt7](https://github.com/ajhaupt7) for [the PR](https://github.com/thelinmichael/spotify-web-api-node/pull/101).
* Add support for playback control (play, pause, prev, next), shuffle and repeat. Thanks [@JoseMCO](https://github.com/JoseMCO) for [the PR](https://github.com/thelinmichael/spotify-web-api-node/pull/150).
* Add support for currently playing. Thanks [@dustinblackman](https://github.com/dustinblackman) for [the PR](https://github.com/thelinmichael/spotify-web-api-node/pull/145).
* Fix to remove unnecessary deviceIds parameter from request to transfer playback. Thanks [@philnash](https://github.com/philnash) for [the PR](https://github.com/thelinmichael/spotify-web-api-node/pull/154).

#### 2.4.0 (2 May 2017)

* Change `addTracksToPlaylist` to pass the data in the body, preventing an issue with a long URL when passing many tracks. Thanks [@dolcalmi](https://github.com/dolcalmi) for [the PR](https://github.com/thelinmichael/spotify-web-api-node/pull/117)
* Add support for fetching [recently played tracks](https://developer.spotify.com/web-api/console/get-recently-played/). Thanks [@jeremyboles](https://github.com/jeremyboles) for [the PR](https://github.com/thelinmichael/spotify-web-api-node/pull/111).

#### 2.3.6 (15 October 2016)

* Add language bindings for the **[Get Audio Analysis for a Track](https://developer.spotify.com/web-api/get-audio-analysis/)** endpoint.

#### 2.3.5 (20 July 2016)

* Use `encodeURIComponent` instead of `encodeURI` to encode the user's id. 'encodeURI' wasn't encoding characters like `/` or `#` that were generating an invalid endpoint url. Thanks [@jgranstrom](https://github.com/jgranstrom) for the PR.

#### 2.3.4 (18 July 2016)

* Fixed a bug in `clientCredentialsGrant()`.

#### 2.3.3 (18 July 2016)

* Migrated to the `superagent` request library to support Node.JS and browsers. Thanks [@SomeoneWeird](https://github.com/SomeoneWeird) for the PR to add it, and [@erezny](https://github.com/erezny) for reporting bugs.

#### 2.3.2 (10 July 2016)

* Add language bindings for **[Get a List of Current User's Playlists](https://developer.spotify.com/web-api/get-a-list-of-current-users-playlists/)**. Thanks [@JMPerez](https://github.com/JMPerez) and [@vinialbano](https://github.com/vinialbano).

#### 2.3.1 (3 July 2016)

* Fix for `getRecomendations` method causing client error response from the API when making the request. Thanks [@kyv](https://github.com/kyv) for reporting, and [@Boberober](https://github.com/Boberober) and [@JMPerez](https://github.com/JMPerez) for providing fixes.

#### 2.3.0 (2 April 2016)

* Add language bindings for **[Get Recommendations Based on Seeds](https://developer.spotify.com/web-api/get-recommendations/)**, **[Get a User's Top Artists and Tracks](https://developer.spotify.com/web-api/get-users-top-artists-and-tracks/)**, **[Get Audio Features for a Track](https://developer.spotify.com/web-api/get-audio-features/)**, and **[Get Audio Features for Several Tracks](https://developer.spotify.com/web-api/get-several-audio-features/)**. Read more about the endpoints in the links above or in this [blog post](https://developer.spotify.com/news-stories/2016/03/29/api-improvements-update/).
* Add generic search method enabling searches for several types at once, e.g. search for both tracks and albums in a single request, instead of one request for track results and one request for album results.

#### 2.2.0 (23 November 2015)

* Add language bindings for **[Get User's Saved Albums](https://developer.spotify.com/web-api/get-users-saved-albums/)** and other endpoints related to the user's saved albums.

#### 2.1.1 (23 November 2015)

* Username encoding bugfix.

#### 2.1.0 (16 July 2015)

* Add language binding for **[Get Followed Artists](https://developer.spotify.com/web-api/get-followed-artists/)**

#### 2.0.2 (11 May 2015)

* Bugfix for retrieving an access token through the Client Credentials flow. (Thanks [Nate Wilkins](https://github.com/Nate-Wilkins)!)
* Add test coverage and Travis CI.

#### 2.0.1 (2 Mar 2015)

* Return WebApiError objects if error occurs during authentication.

#### 2.0.0 (27 Feb 2015)

* **Breaking change**: Response object changed. Add headers and status code to all responses to enable users to implement caching.

#### 1.3.13 (26 Feb 2015)

* Add language binding for **[Reorder tracks in a Playlist](https://developer.spotify.com/web-api/reorder-playlists-tracks/)**

#### 1.3.12 (22 Feb 2015)

* Add language binding for **[Remove tracks in a Playlist by Position](https://developer.spotify.com/web-api/remove-tracks-playlist/)**

#### 1.3.11

* Add **[Search for Playlists](https://developer.spotify.com/web-api/search-item/)** endpoint.

#### 1.3.10

* Add market parameter to endpoints supporting **[Track Relinking](https://developer.spotify.com/web-api/track-relinking-guide/)**.
* Improve SEO by adding keywords to the package.json file. ;-)

#### 1.3.8

* Add **[Get a List of Categories](https://developer.spotify.com/web-api/get-list-categories/)**, **[Get a Category](https://developer.spotify.com/web-api/get-category/)**, and **[Get A Category's Playlists](https://developer.spotify.com/web-api/get-categorys-playlists/)** endpoints.

#### 1.3.7

* Add **[Check if Users are Following Playlist](https://developer.spotify.com/web-api/check-user-following-playlist/)** endpoint.

#### 1.3.5

* Add missing options parameter in createPlaylist (issue #19). Thanks for raising this [allinallin](https://github.com/allinallin).

#### 1.3.4

* Add **[Follow Playlist](https://developer.spotify.com/web-api/follow-playlist/)** and **[Unfollow Playlist](https://developer.spotify.com/web-api/unfollow-playlist/)** endpoints.

#### 1.3.3

* [Fix](https://github.com/thelinmichael/spotify-web-api-node/pull/18) error format. Thanks [extrakt](https://github.com/extrakt).

#### 1.3.2

* Add ability to use callback methods instead of promise.

#### 1.2.2

* Bugfix. api.addTracksToPlaylist tracks parameter can be a string or an array. Thanks [ofagbemi](https://github.com/ofagbemi)!

#### 1.2.1

* Add **[Follow endpoints](https://developer.spotify.com/web-api/web-api-follow-endpoints/)**. Great work [JMPerez](https://github.com/JMPerez).

#### 1.1.0

* Add **[Browse endpoints](https://developer.spotify.com/web-api/browse-endpoints/)**. Thanks [fsahin](https://github.com/fsahin).

#### 1.0.2

* Specify module's git repository. Thanks [vincentorback](https://github.com/vincentorback).

#### 1.0.1

* Allow options to be set when retrieving a user's playlists. Thanks [EaterOfCode](https://github.com/EaterOfCode).

#### 1.0.0

* Add **[Replace tracks in a Playlist](https://developer.spotify.com/web-api/replace-playlists-tracks/)** endpoint
* Add **[Remove tracks in a Playlist](https://developer.spotify.com/web-api/remove-tracks-playlist/)** endpoint
* Return errors as Error objects instead of unparsed JSON. Thanks [niftylettuce](https://github.com/niftylettuce).

#### 0.0.11

* Add **[Change Playlist details](https://developer.spotify.com/web-api/change-playlist-details/)** endpoint (change published status and name). Gracias [JMPerez](https://github.com/JMPerez).

#### 0.0.10

* Add Your Music Endpoints (**[Add tracks](https://developer.spotify.com/web-api/save-tracks-user/)**, **[Remove tracks](https://developer.spotify.com/web-api/remove-tracks-user/)**, **[Contains tracks](https://developer.spotify.com/web-api/check-users-saved-tracks/)**, **[Get tracks](https://developer.spotify.com/web-api/get-users-saved-tracks/)**).
* Documentation updates (change scope name of playlist-modify to playlist-modify-public, and a fix to a parameter type). Thanks [JMPerez](https://github.com/JMPerez) and [matiassingers](https://github.com/matiassingers).

#### 0.0.9

* Add **[Related artists](https://developer.spotify.com/web-api/get-related-artists/)** endpoint


text:
<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateEmployeesTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up() {
        Schema::create('employees', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name')->unique();
            $table->string('email')->unique();
            $table->string('contact_number');
            $table->string('position');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down() {
        Schema::drop('employees');
    }

}


text:
package org.apache.james.cli;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.easymock.EasyMock.createControl;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.ParseException;
import org.apache.james.adapter.mailbox.SerializableQuota;
import org.apache.james.cli.exceptions.InvalidArgumentNumberException;
import org.apache.james.cli.exceptions.InvalidPortException;
import org.apache.james.cli.exceptions.MissingCommandException;
import org.apache.james.cli.exceptions.UnrecognizedCommandException;
import org.apache.james.cli.probe.ServerProbe;
import org.apache.james.cli.type.CmdType;
import org.apache.james.mailbox.model.Quota;
import org.easymock.IMocksControl;
import org.junit.Before;
import org.junit.Test;

public class ServerCmdTest {

    public static final String ADDITIONAL_ARGUMENT = "additionalArgument";
    private IMocksControl control;

    private ServerProbe serverProbe;

    private ServerCmd testee;

    @Before
    public void setup() {
        control = createControl();
        serverProbe = control.createMock(ServerProbe.class);
        testee = new ServerCmd(serverProbe);
    }

    @Test
    public void addDomainCommandShouldWork() throws Exception {
        String domain = "example.com";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.ADDDOMAIN.getCommand(), domain};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.addDomain(domain);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void removeDomainCommandShouldWork() throws Exception {
        String domain = "example.com";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.REMOVEDOMAIN.getCommand(), domain};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.removeDomain(domain);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void containsDomainCommandShouldWork() throws Exception {
        String domain = "example.com";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.CONTAINSDOMAIN.getCommand(), domain};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        expect(serverProbe.containsDomain(domain)).andReturn(true);

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void listDomainsCommandShouldWork() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.LISTDOMAINS.getCommand()};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        String[] res = {};
        expect(serverProbe.listDomains()).andReturn(res);

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void addUserCommandShouldWork() throws Exception {
        String user = "user@domain";
        String password = "password";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.ADDUSER.getCommand(), user, password};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.addUser(user, password);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void removeUserCommandShouldWork() throws Exception {
        String user = "user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.REMOVEUSER.getCommand(), user};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.removeUser(user);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void listUsersCommandShouldWork() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.LISTUSERS.getCommand()};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        String[] res = {};
        expect(serverProbe.listUsers()).andReturn(res);

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void listMappingsCommandShouldWork() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.LISTMAPPINGS.getCommand()};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        expect(serverProbe.listMappings()).andReturn(new HashMap<String, Collection<String>>());

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void listUserDomainMappingsCommandShouldWork() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.LISTUSERDOMAINMAPPINGS.getCommand(), user, domain};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        expect(serverProbe.listUserDomainMappings(user, domain)).andReturn(new ArrayList<String>());

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void addAddressCommandShouldWork() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String address = "bis@apache.org";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.ADDADDRESSMAPPING.getCommand(), user, domain, address};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.addAddressMapping(user, domain, address);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void removeAddressCommandShouldWork() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String address = "bis@apache.org";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.REMOVEADDRESSMAPPING.getCommand(), user, domain, address};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.removeAddressMapping(user, domain, address);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void addRegexMappingCommandShouldWork() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String regex = "bis.*@apache.org";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.ADDREGEXMAPPING.getCommand(), user, domain, regex};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.addRegexMapping(user, domain, regex);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void removeRegexMappingCommandShouldWork() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String regex = "bis.*@apache.org";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.REMOVEREGEXMAPPING.getCommand(), user, domain, regex};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.removeRegexMapping(user, domain, regex);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void setPasswordMappingCommandShouldWork() throws Exception {
        String user = "user@domain";
        String password = "pass";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.SETPASSWORD.getCommand(), user, password};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.setPassword(user, password);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void copyMailboxMappingCommandShouldWork() throws Exception {
        String srcBean = "srcBean";
        String dstBean = "dstBean";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.COPYMAILBOX.getCommand(), srcBean, dstBean};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.copyMailbox(srcBean, dstBean);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void deleteUserMailboxesMappingCommandShouldWork() throws Exception {
        String user = "user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.DELETEUSERMAILBOXES.getCommand(), user};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.deleteUserMailboxesNames(user);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void createMailboxMappingCommandShouldWork() throws Exception {
        String user = "user@domain";
        String namespace = "#private";
        String name = "INBOX.test";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.CREATEMAILBOX.getCommand(), namespace, user, name};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.createMailbox(namespace, user, name);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void deleteMailboxMappingCommandShouldWork() throws Exception {
        String user = "user@domain";
        String namespace = "#private";
        String name = "INBOX.test";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.DELETEMAILBOX.getCommand(), namespace, user, name};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.deleteMailbox(namespace, user, name);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void listUserMailboxesMappingsCommandShouldWork() throws Exception {
        String user = "user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.LISTUSERMAILBOXES.getCommand(), user};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        expect(serverProbe.listUserMailboxes(user)).andReturn(new ArrayList<String>());

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void getQuotaRootCommandShouldWork() throws Exception {
        String namespace = "#private";
        String user = "user@domain";
        String name = "INBOX";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.GETQUOTAROOT.getCommand(), namespace, user, name};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        expect(serverProbe.getQuotaRoot(namespace, user, name)).andReturn(namespace + "&" + user);

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void getDefaultMaxMessageCountCommandShouldWork() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.GETDEFAULTMAXMESSAGECOUNTQUOTA.getCommand()};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        expect(serverProbe.getDefaultMaxMessageCount()).andReturn(1024L * 1024L);

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void getDefaultMaxStorageCommandShouldWork() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.GETDEFAULTMAXSTORAGEQUOTA.getCommand()};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        expect(serverProbe.getDefaultMaxStorage()).andReturn(1024L * 1024L * 1024L);

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void setDefaultMaxMessageCountCommandShouldWork() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.SETDEFAULTMAXMESSAGECOUNTQUOTA.getCommand(), "1054"};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

       serverProbe.setDefaultMaxMessageCount(1054);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void setDefaultMaxStorageCommandShouldWork() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.SETDEFAULTMAXSTORAGEQUOTA.getCommand(), "1G"};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.setDefaultMaxStorage(1024 * 1024 * 1024);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void setMaxMessageCountCommandShouldWork() throws Exception {
        String quotaroot = "#private&user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.SETMAXMESSAGECOUNTQUOTA.getCommand(), quotaroot, "1000"};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.setMaxMessageCount(quotaroot, 1000);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void setMaxStorageCommandShouldWork() throws Exception {
        String quotaroot = "#private&user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.SETMAXSTORAGEQUOTA.getCommand(), quotaroot, "5M"};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        serverProbe.setMaxStorage(quotaroot, 5 * 1024 * 1024);
        expectLastCall();

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void getMaxMessageCountCommandShouldWork() throws Exception {
        String quotaroot = "#private&user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.GETMAXMESSAGECOUNTQUOTA.getCommand(), quotaroot};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        expect(serverProbe.getMaxMessageCount(quotaroot)).andReturn(Quota.UNLIMITED);

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void getMaxStorageQuotaCommandShouldWork() throws Exception {
        String quotaroot = "#private&user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.GETMAXSTORAGEQUOTA.getCommand(), quotaroot};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        expect(serverProbe.getMaxStorage(quotaroot)).andReturn(Quota.UNLIMITED);

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void getStorageQuotaCommandShouldWork() throws Exception {
        String quotaroot = "#private&user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.GETSTORAGEQUOTA.getCommand(), quotaroot};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        expect(serverProbe.getStorageQuota(quotaroot)).andReturn(new SerializableQuota(Quota.UNLIMITED, Quota.UNKNOWN));

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test
    public void getMessageCountQuotaCommandShouldWork() throws Exception {
        String quotaroot = "#private&user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.GETMESSAGECOUNTQUOTA.getCommand(), quotaroot};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        expect(serverProbe.getMessageCountQuota(quotaroot)).andReturn(new SerializableQuota(Quota.UNLIMITED, Quota.UNKNOWN));

        control.replay();
        testee.executeCommandLine(commandLine);
        control.verify();
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void addDomainCommandShouldThrowOnMissingArguments() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.ADDDOMAIN.getCommand()};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void removeDomainCommandShouldThrowOnMissingArguments() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.REMOVEDOMAIN.getCommand()};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void containsDomainCommandShouldThrowOnMissingArguments() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.CONTAINSDOMAIN.getCommand()};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void addUserCommandShouldThrowOnMissingArguments() throws Exception {
        String user = "user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.ADDUSER.getCommand(), user};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void removeUserCommandShouldThrowOnMissingArguments() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.REMOVEUSER.getCommand()};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void listUserDomainMappingsCommandShouldThrowOnMissingArguments() throws Exception {
        String user = "user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.LISTUSERDOMAINMAPPINGS.getCommand(), user};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void addAddressCommandShouldThrowOnMissingArguments() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.ADDADDRESSMAPPING.getCommand(), user, domain};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void removeAddressCommandShouldThrowOnMissingArguments() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.REMOVEADDRESSMAPPING.getCommand(), user, domain};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void addRegexMappingCommandShouldThrowOnMissingArguments() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.ADDREGEXMAPPING.getCommand(), user, domain};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void removeRegexMappingCommandShouldThrowOnMissingArguments() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.REMOVEREGEXMAPPING.getCommand(), user, domain};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void setPasswordMappingCommandShouldThrowOnMissingArguments() throws Exception {
        String user = "user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.SETPASSWORD.getCommand(), user};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void copyMailboxMappingCommandShouldThrowOnMissingArguments() throws Exception {
        String srcBean = "srcBean";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.COPYMAILBOX.getCommand(), srcBean};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void deleteUserMailboxesMappingCommandShouldThrowOnMissingArguments() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.DELETEUSERMAILBOXES.getCommand()};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void createMailboxMappingCommandShouldThrowOnMissingArguments() throws Exception {
        String user = "user@domain";
        String namespace = "#private";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.CREATEMAILBOX.getCommand(), namespace, user};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void deleteMailboxMappingCommandShouldThrowOnMissingArguments() throws Exception {
        String user = "user@domain";
        String namespace = "#private";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.DELETEMAILBOX.getCommand(), namespace, user};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void listUserMailboxesMappingsCommandShouldThrowOnMissingArguments() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.LISTUSERMAILBOXES.getCommand()};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void addDomainCommandShouldThrowOnAdditionalArguments() throws Exception {
        String domain = "example.com";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.ADDDOMAIN.getCommand(), domain, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void removeDomainCommandShouldThrowOnAdditionalArguments() throws Exception {
        String domain = "example.com";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.REMOVEDOMAIN.getCommand(), domain, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void containsDomainCommandShouldThrowOnAdditionalArguments() throws Exception {
        String domain = "example.com";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.CONTAINSDOMAIN.getCommand(), domain, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void listDomainsCommandShouldThrowOnAdditionalArguments() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.LISTDOMAINS.getCommand(), ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void addUserCommandShouldThrowOnAdditionalArguments() throws Exception {
        String user = "user@domain";
        String password = "password";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.ADDUSER.getCommand(), user, password, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void removeUserCommandShouldThrowOnAdditionalArguments() throws Exception {
        String user = "user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.REMOVEUSER.getCommand(), user, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void listUsersCommandShouldThrowOnAdditionalArguments() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.LISTUSERS.getCommand(), ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void listMappingsCommandShouldThrowOnAdditionalArguments() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.LISTMAPPINGS.getCommand(), ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void listUserDomainMappingsCommandShouldThrowOnAdditionalArguments() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.LISTUSERDOMAINMAPPINGS.getCommand(), user, domain, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void addAddressCommandShouldThrowOnAdditionalArguments() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String address = "bis@apache.org";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.ADDADDRESSMAPPING.getCommand(), user, domain, address, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void removeAddressCommandShouldThrowOnAdditionalArguments() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String address = "bis@apache.org";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.REMOVEADDRESSMAPPING.getCommand(), user, domain, address, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void addRegexMappingCommandShouldThrowOnAdditionalArguments() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String regex = "bis.*@apache.org";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.ADDREGEXMAPPING.getCommand(), user, domain, regex, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void removeRegexMappingCommandShouldThrowOnAdditionalArguments() throws Exception {
        String user = "user@domain";
        String domain = "domain";
        String regex = "bis.*@apache.org";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.REMOVEREGEXMAPPING.getCommand(), user, domain, regex, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void setPasswordMappingCommandShouldThrowOnAdditionalArguments() throws Exception {
        String user = "user@domain";
        String password = "pass";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.SETPASSWORD.getCommand(), user, password, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void copyMailboxMappingCommandShouldThrowOnAdditionalArguments() throws Exception {
        String srcBean = "srcBean";
        String dstBean = "dstBean";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.COPYMAILBOX.getCommand(), srcBean, dstBean, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void deleteUserMailboxesMappingCommandShouldThrowOnAdditionalArguments() throws Exception {
        String user = "user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.DELETEUSERMAILBOXES.getCommand(), user, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void createMailboxMappingCommandShouldThrowOnAdditionalArguments() throws Exception {
        String user = "user@domain";
        String namespace = "#private";
        String name = "INBOX.test";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.CREATEMAILBOX.getCommand(), namespace, user, name, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void deleteMailboxMappingCommandShouldThrowOnAdditionalArguments() throws Exception {
        String user = "user@domain";
        String namespace = "#private";
        String name = "INBOX.test";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.DELETEMAILBOX.getCommand(), namespace, user, name, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = InvalidArgumentNumberException.class)
    public void listUserMailboxesMappingsCommandShouldThrowOnAdditionalArguments() throws Exception {
        String user = "user@domain";
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", CmdType.LISTUSERMAILBOXES.getCommand(), user, ADDITIONAL_ARGUMENT };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = UnrecognizedCommandException.class)
    public void executeCommandLineShouldThrowOnUnrecognizedCommands() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", "wrongCommand"};
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);

        control.replay();
        try {
            testee.executeCommandLine(commandLine);
        } finally {
            control.verify();
        }
    }

    @Test(expected = MissingCommandException.class)
    public void parseCommandLineShouldThrowWhenOnlyOptionAreProvided() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999" };
        ServerCmd.parseCommandLine(arguments);
    }

    @Test(expected = ParseException.class)
    public void parseCommandLineShouldThrowWhenInvalidOptionIsProvided() throws Exception {
        String[] arguments = { "-v", "-h", "127.0.0.1", "-p", "9999" };
        ServerCmd.parseCommandLine(arguments);
    }

    @Test(expected = ParseException.class)
    public void parseCommandLineShouldThrowWhenMandatoryOptionIsMissing() throws Exception {
        String[] arguments = { "-v", "-h", "127.0.0.1", "-p", "9999" };
        ServerCmd.parseCommandLine(arguments);
    }

    @Test
    public void parseCommandLineShouldReturnACommandLineWithCorrectArguments() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", "command", "arg1", "arg2", "arg3" };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
        assertThat(commandLine.getArgs()).containsExactly("command", "arg1", "arg2", "arg3");
    }

    @Test
    public void parseCommandLineShouldReturnACommandLineWithCorrectPortOption() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", "command", "arg1", "arg2", "arg3" };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
        assertThat(commandLine.getOptionValue(ServerCmd.PORT_OPT_LONG)).isEqualTo("9999");
    }

    @Test
    public void parseCommandLineShouldReturnACommandLineWithCorrectHostOption() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", "command", "arg1", "arg2", "arg3" };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
        assertThat(commandLine.getOptionValue(ServerCmd.HOST_OPT_LONG)).isEqualTo("127.0.0.1");
    }

    @Test
    public void getPortShouldRetrievePort() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "9999", "command", "arg1", "arg2", "arg3" };
        CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
        assertThat(ServerCmd.getPort(commandLine)).isEqualTo(9999);
    }

    @Test(expected = InvalidPortException.class)
    public void getPortShouldThrowOnNullPortValueOption() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "0", "command", "arg1", "arg2", "arg3" };
        CommandLine commandLine;
        try {
            commandLine = ServerCmd.parseCommandLine(arguments);
        } catch (Exception e) {
            fail("Exception received", e);
            return;
        }
        ServerCmd.getPort(commandLine);
    }

    @Test(expected = InvalidPortException.class)
    public void getPortShouldThrowOnNegativePortValueOption() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "-1", "command", "arg1", "arg2", "arg3" };
        CommandLine commandLine;
        try {
            commandLine = ServerCmd.parseCommandLine(arguments);
        } catch (Exception e) {
            fail("Exception received", e);
            return;
        }
        ServerCmd.getPort(commandLine);
    }

    @Test(expected = InvalidPortException.class)
    public void getPortShouldThrowOnTooHighPortValueOption() throws Exception {
        String[] arguments = { "-h", "127.0.0.1", "-p", "99999", "command", "arg1", "arg2", "arg3" };
        CommandLine commandLine;
        try {
            commandLine = ServerCmd.parseCommandLine(arguments);
        } catch (Exception e) {
            fail("Exception received", e);
            return;
        }
        ServerCmd.getPort(commandLine);
    }

}


text:
Screen
******

Allows you to control multiple screens on a remote Linux computer.  Like
terminal server for Linux consoles.

Links
=====

- `The GNU Screen Mini Tutorial`_
- `Stayin' alive with Screen`_
- :doc:`apps/tmux`

Setup
=====

Copy the .screenrc_ configuration file to your home folder to bind *F11* and
*F12* to the next and previous window commands.

Usage
=====

::

  screen

List
====

To list screens::

  screen -ls

Attach
======

To attach to a screen, do an "-ls" to get the name then::

  screen -r "name"

e.g::

  screen -r 31619.ttyp2.gigan

Detach
======

See *Shortcuts* below...

Reattach
========

Attach  here and now. In detail this means: If a session is running, then
reattach::

  screen -D -R

Scrollback
==========

`Working with the Scrollback Buffer`_

Edit your ``~/.screenrc`` file and add the following::

  defscrollback 5000

This will give you 5000 lines of scrollback.

To enter scrollback mode: *Ctrl* *a*, *[*.  Note: The screen will say
``Copy mode``.
Use the normal vim commands to move around the screen.

To copy:

- move to the start of the text and press *spacebar*.
- move to the end and press *spacebar*.
- To paste the text: *Ctrl* *a*, *]*.

Press *Escape* to exit this mode.

Shortcuts
=========

================================  ==============
To create a new screen            *Ctrl-a* **c**
To get to the next screen         *Ctrl-a* **n**
To detach from a screen           *Ctrl-a* **d**
Split horizontally into regions   *Ctrl-a* **S**
Split vertically into regions     *Ctrl-a* ``|``
Then move to the region and
*create a new screen*
Move to next region               *Ctrl-a* *Tab*
================================  ==============

Issues
======

If you have problems with the delete key, put the following line in your
``.bashrc``::

  alias screen=TERM=screen screen

27/09/2011, Removed a couple of control characters from around
``TERM=screen screen`` above.  Not sure if this is correct, or not.

Execute the following command to re-source your ``.bashrc file``:
``. ~/.bashrc``.

.. _`The GNU Screen Mini Tutorial`: http://lolcodrz.com/blog/2009/01/gnu-screen-mini-tutorial/
.. _`Stayin' alive with Screen`: http://www.ibm.com/developerworks/aix/library/au-gnu_screen/
.. _.screenrc: ../../misc/howto/linux/.screenrc
.. _`Working with the Scrollback Buffer`: http://www.samsarin.com/blog/2007/03/11/gnu-screen-working-with-the-scrollback-buffer/


text:
/**
 * @constructor
 * @extends {WebInspector.Object}
 * @param {!WebInspector.Target} target
 * @param {boolean} isMainFrontend
 */
WebInspector.WorkerManager = function(target, isMainFrontend)
{
    this._reset();
    target.registerWorkerDispatcher(new WebInspector.WorkerDispatcher(this));
    if (isMainFrontend) {
        target.workerAgent().enable();
        target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameNavigated, this);
    }
}

WebInspector.WorkerManager.Events = {
    WorkerAdded: "WorkerAdded",
    WorkerRemoved: "WorkerRemoved",
    WorkersCleared: "WorkersCleared",
    WorkerSelectionChanged: "WorkerSelectionChanged",
    WorkerDisconnected: "WorkerDisconnected",
    MessageFromWorker: "MessageFromWorker",
}

WebInspector.WorkerManager.MainThreadId = 0;

WebInspector.WorkerManager.prototype = {

    _reset: function()
    {
        /** @type {!Object.<number, string>} */
        this._threadUrlByThreadId = {};
        this._threadUrlByThreadId[WebInspector.WorkerManager.MainThreadId] = WebInspector.UIString("Thread: Main");
        this._threadsList = [WebInspector.WorkerManager.MainThreadId];
        this._selectedThreadId = WebInspector.WorkerManager.MainThreadId;
    },

    _workerCreated: function(workerId, url, inspectorConnected)
    {
        this._threadsList.push(workerId);
        this._threadUrlByThreadId[workerId] = url;
        this.dispatchEventToListeners(WebInspector.WorkerManager.Events.WorkerAdded, {workerId: workerId, url: url, inspectorConnected: inspectorConnected});
     },

    _workerTerminated: function(workerId)
    {
        this._threadsList.remove(workerId);
        delete this._threadUrlByThreadId[workerId];
        this.dispatchEventToListeners(WebInspector.WorkerManager.Events.WorkerRemoved, workerId);
    },

    _dispatchMessageFromWorker: function(workerId, message)
    {
        this.dispatchEventToListeners(WebInspector.WorkerManager.Events.MessageFromWorker, {workerId: workerId, message: message});
    },

    _disconnectedFromWorker: function()
    {
        this.dispatchEventToListeners(WebInspector.WorkerManager.Events.WorkerDisconnected);
    },

    _mainFrameNavigated: function(event)
    {
        this._reset();
        this.dispatchEventToListeners(WebInspector.WorkerManager.Events.WorkersCleared);
    },

    /**
     * @return {!Array.<number>}
     */
    threadsList: function()
    {
        return this._threadsList;
    },

    /**
     * @param {number} threadId
     * @return {string}
     */
    threadUrl: function(threadId)
    {
        return this._threadUrlByThreadId[threadId];
    },

    /**
     * @param {number} threadId
     */
    setSelectedThreadId: function(threadId)
    {
        this._selectedThreadId = threadId;
    },

    /**
     * @return {number}
     */
    selectedThreadId: function()
    {
        return this._selectedThreadId;
    },

    __proto__: WebInspector.Object.prototype
}

/**
 * @constructor
 * @implements {WorkerAgent.Dispatcher}
 */
WebInspector.WorkerDispatcher = function(workerManager)
{
    this._workerManager = workerManager;
}

WebInspector.WorkerDispatcher.prototype = {
    /**
     * @override
     * @param {number} workerId
     * @param {string} url
     * @param {boolean} inspectorConnected
     */
    workerCreated: function(workerId, url, inspectorConnected)
    {
        this._workerManager._workerCreated(workerId, url, inspectorConnected);
    },

    /**
     * @override
     * @param {number} workerId
     */
    workerTerminated: function(workerId)
    {
        this._workerManager._workerTerminated(workerId);
    },

    /**
     * @override
     * @param {number} workerId
     * @param {!Object} message
     */
    dispatchMessageFromWorker: function(workerId, message)
    {
        this._workerManager._dispatchMessageFromWorker(workerId, message);
    },

    /**
     * @override
     */
    disconnectedFromWorker: function()
    {
        this._workerManager._disconnectedFromWorker();
    }
}

/**
 * @type {!WebInspector.WorkerManager}
 */
WebInspector.workerManager;